aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Documentation/ABI/stable/sysfs-devices-node7
-rw-r--r--Documentation/HOWTO113
-rw-r--r--Documentation/cpu-freq/pcc-cpufreq.txt207
-rw-r--r--Documentation/device-mapper/snapshot.txt44
-rw-r--r--Documentation/fault-injection/provoke-crashes.txt38
-rw-r--r--Documentation/feature-removal-schedule.txt6
-rw-r--r--Documentation/filesystems/00-INDEX2
-rw-r--r--Documentation/filesystems/logfs.txt241
-rw-r--r--Documentation/filesystems/nfs/nfs41-server.txt5
-rw-r--r--Documentation/filesystems/proc.txt53
-rw-r--r--Documentation/gpio.txt64
-rw-r--r--Documentation/hwmon/adt741142
-rw-r--r--Documentation/hwmon/adt747374
-rw-r--r--Documentation/hwmon/asc7621296
-rw-r--r--Documentation/hwmon/it8753
-rw-r--r--Documentation/hwmon/lm9022
-rw-r--r--Documentation/init.txt49
-rw-r--r--Documentation/kernel-parameters.txt6
-rw-r--r--Documentation/kobject.txt2
-rw-r--r--Documentation/power/runtime_pm.txt93
-rw-r--r--Documentation/powerpc/dts-bindings/fsl/i2c.txt30
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt2
-rw-r--r--MAINTAINERS63
-rw-r--r--Makefile4
-rw-r--r--arch/alpha/kernel/osf_sys.c3
-rw-r--r--arch/arm/mach-ep93xx/include/mach/ts72xx.h2
-rw-r--r--arch/arm/mach-ep93xx/ts72xx.c21
-rw-r--r--arch/arm/mach-pxa/corgi_ssp.c2
-rw-r--r--arch/arm/mach-pxa/sharpsl_pm.c2
-rw-r--r--arch/arm/mach-s3c2410/h1940-bluetooth.c2
-rw-r--r--arch/arm/mach-sa1100/jornada720_ssp.c2
-rw-r--r--arch/cris/Kconfig6
-rw-r--r--arch/cris/arch-v32/drivers/cryptocop.c2
-rw-r--r--arch/cris/arch-v32/mach-fs/arbiter.c2
-rw-r--r--arch/cris/kernel/time.c68
-rw-r--r--arch/frv/include/asm/pci.h37
-rw-r--r--arch/ia64/include/asm/elf.h48
-rw-r--r--arch/ia64/kernel/Makefile2
-rw-r--r--arch/ia64/kernel/elfcore.c80
-rw-r--r--arch/ia64/kernel/perfmon.c1
-rw-r--r--arch/ia64/kernel/topology.c2
-rw-r--r--arch/ia64/mm/init.c2
-rw-r--r--arch/mips/txx9/generic/7segled.c5
-rw-r--r--arch/parisc/Kconfig.debug14
-rw-r--r--arch/parisc/include/asm/param.h23
-rw-r--r--arch/parisc/include/asm/system.h2
-rw-r--r--arch/parisc/include/asm/uaccess.h27
-rw-r--r--arch/parisc/include/asm/unistd.h4
-rw-r--r--arch/parisc/kernel/cache.c4
-rw-r--r--arch/parisc/kernel/syscall_table.S2
-rw-r--r--arch/parisc/kernel/time.c29
-rw-r--r--arch/parisc/kernel/unaligned.c14
-rw-r--r--arch/parisc/lib/memcpy.c3
-rw-r--r--arch/powerpc/kernel/cacheinfo.c2
-rw-r--r--arch/powerpc/mm/numa.c6
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_gpt.c2
-rw-r--r--arch/s390/include/asm/qdio.h7
-rw-r--r--arch/s390/kernel/smp.c12
-rw-r--r--arch/s390/kernel/time.c59
-rw-r--r--arch/s390/lib/Makefile3
-rw-r--r--arch/s390/mm/cmm.c2
-rw-r--r--arch/sh/boards/mach-migor/setup.c16
-rw-r--r--arch/sh/boot/compressed/cache.c2
-rw-r--r--arch/sh/include/asm/cacheflush.h4
-rw-r--r--arch/sh/include/asm/dma-register.h51
-rw-r--r--arch/sh/include/asm/dma-sh.h88
-rw-r--r--arch/sh/include/asm/dmaengine.h93
-rw-r--r--arch/sh/include/asm/io.h23
-rw-r--r--arch/sh/include/asm/mmu.h31
-rw-r--r--arch/sh/include/asm/siu.h2
-rw-r--r--arch/sh/include/asm/topology.h2
-rw-r--r--arch/sh/include/cpu-sh3/cpu/dma-register.h41
-rw-r--r--arch/sh/include/cpu-sh3/cpu/dma.h27
-rw-r--r--arch/sh/include/cpu-sh4/cpu/dma-register.h112
-rw-r--r--arch/sh/include/cpu-sh4/cpu/dma-sh4a.h62
-rw-r--r--arch/sh/include/cpu-sh4/cpu/dma.h36
-rw-r--r--arch/sh/include/mach-migor/mach/migor.h1
-rw-r--r--arch/sh/kernel/cpu/sh4/sq.c2
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7722.c190
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7724.c186
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7780.c134
-rw-r--r--arch/sh/kernel/cpu/sh4a/setup-sh7785.c134
-rw-r--r--arch/sh/kernel/hw_breakpoint.c30
-rw-r--r--arch/sh/kernel/setup.c3
-rw-r--r--arch/sh/kernel/time.c6
-rw-r--r--arch/sh/lib/libgcc.h3
-rw-r--r--arch/sh/mm/ioremap.c70
-rw-r--r--arch/sh/mm/ioremap_fixed.c11
-rw-r--r--arch/sh/mm/numa.c3
-rw-r--r--arch/sh/mm/pmb.c412
-rw-r--r--arch/um/.gitignore3
-rw-r--r--arch/um/drivers/line.c4
-rw-r--r--arch/um/sys-i386/Makefile2
-rw-r--r--arch/um/sys-i386/asm/elf.h43
-rw-r--r--arch/um/sys-i386/elfcore.c83
-rw-r--r--arch/x86/Kconfig15
-rw-r--r--arch/x86/include/asm/apb_timer.h70
-rw-r--r--arch/x86/include/asm/hw_irq.h7
-rw-r--r--arch/x86/include/asm/i8259.h19
-rw-r--r--arch/x86/include/asm/io_apic.h7
-rw-r--r--arch/x86/include/asm/irq.h1
-rw-r--r--arch/x86/include/asm/mrst.h19
-rw-r--r--arch/x86/include/asm/numaq.h1
-rw-r--r--arch/x86/include/asm/olpc.h20
-rw-r--r--arch/x86/include/asm/pci.h9
-rw-r--r--arch/x86/include/asm/pci_x86.h22
-rw-r--r--arch/x86/include/asm/setup.h2
-rw-r--r--arch/x86/include/asm/visws/cobalt.h2
-rw-r--r--arch/x86/include/asm/x86_init.h15
-rw-r--r--arch/x86/kernel/Makefile1
-rw-r--r--arch/x86/kernel/acpi/boot.c4
-rw-r--r--arch/x86/kernel/apb_timer.c784
-rw-r--r--arch/x86/kernel/apic/apic.c8
-rw-r--r--arch/x86/kernel/apic/io_apic.c86
-rw-r--r--arch/x86/kernel/apic/nmi.c2
-rw-r--r--arch/x86/kernel/apic/numaq_32.c1
-rw-r--r--arch/x86/kernel/cpu/cpufreq/Kconfig14
-rw-r--r--arch/x86/kernel/cpu/cpufreq/Makefile1
-rw-r--r--arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c620
-rw-r--r--arch/x86/kernel/cpu/intel_cacheinfo.c2
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c1
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_amd.c2
-rw-r--r--arch/x86/kernel/cpu/perf_event.c2
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel.c2
-rw-r--r--arch/x86/kernel/i8259.c64
-rw-r--r--arch/x86/kernel/irqinit.c9
-rw-r--r--arch/x86/kernel/mrst.c216
-rw-r--r--arch/x86/kernel/olpc.c10
-rw-r--r--arch/x86/kernel/smpboot.c9
-rw-r--r--arch/x86/kernel/visws_quirks.c21
-rw-r--r--arch/x86/kernel/x86_init.c8
-rw-r--r--arch/x86/pci/Makefile2
-rw-r--r--arch/x86/pci/acpi.c7
-rw-r--r--arch/x86/pci/common.c6
-rw-r--r--arch/x86/pci/init.c8
-rw-r--r--arch/x86/pci/irq.c16
-rw-r--r--arch/x86/pci/legacy.c24
-rw-r--r--arch/x86/pci/mrst.c262
-rw-r--r--arch/x86/pci/numaq_32.c6
-rw-r--r--arch/x86/pci/olpc.c3
-rw-r--r--arch/x86/pci/visws.c6
-rw-r--r--block/blk-integrity.c2
-rw-r--r--block/blk-sysfs.c2
-rw-r--r--block/elevator.c2
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/acpi/processor_core.c2
-rw-r--r--drivers/acpi/system.c2
-rw-r--r--drivers/auxdisplay/cfag12864bfb.c2
-rw-r--r--drivers/base/Kconfig51
-rw-r--r--drivers/base/bus.c26
-rw-r--r--drivers/base/class.c16
-rw-r--r--drivers/base/core.c46
-rw-r--r--drivers/base/cpu.c105
-rw-r--r--drivers/base/dd.c38
-rw-r--r--drivers/base/devtmpfs.c13
-rw-r--r--drivers/base/firmware_class.c11
-rw-r--r--drivers/base/memory.c20
-rw-r--r--drivers/base/node.c81
-rw-r--r--drivers/base/platform.c76
-rw-r--r--drivers/base/power/Makefile1
-rw-r--r--drivers/base/power/generic_ops.c233
-rw-r--r--drivers/base/power/main.c20
-rw-r--r--drivers/base/sys.c17
-rw-r--r--drivers/block/osdblk.c12
-rw-r--r--drivers/block/pktcdvd.c14
-rw-r--r--drivers/char/hvc_iucv.c6
-rw-r--r--drivers/char/virtio_console.c29
-rw-r--r--drivers/clocksource/Kconfig9
-rw-r--r--drivers/cpufreq/cpufreq.c2
-rw-r--r--drivers/cpuidle/governors/menu.c2
-rw-r--r--drivers/cpuidle/sysfs.c8
-rw-r--r--drivers/dma/ioat/dma.c4
-rw-r--r--drivers/dma/ioat/dma.h2
-rw-r--r--drivers/dma/shdma.c500
-rw-r--r--drivers/dma/shdma.h26
-rw-r--r--drivers/edac/edac_device_sysfs.c6
-rw-r--r--drivers/edac/edac_mc_sysfs.c4
-rw-r--r--drivers/edac/edac_pci_sysfs.c4
-rw-r--r--drivers/eisa/eisa-bus.c240
-rw-r--r--drivers/firewire/core-device.c5
-rw-r--r--drivers/firmware/edd.c2
-rw-r--r--drivers/firmware/efivars.c2
-rw-r--r--drivers/firmware/iscsi_ibft.c2
-rw-r--r--drivers/firmware/memmap.c59
-rw-r--r--drivers/gpio/Kconfig57
-rw-r--r--drivers/gpio/Makefile6
-rw-r--r--drivers/gpio/cs5535-gpio.c4
-rw-r--r--drivers/gpio/gpiolib.c66
-rw-r--r--drivers/gpio/it8761e_gpio.c231
-rw-r--r--drivers/gpio/max7300.c94
-rw-r--r--drivers/gpio/max7301.c293
-rw-r--r--drivers/gpio/max730x.c244
-rw-r--r--drivers/gpio/pca953x.c249
-rw-r--r--drivers/gpio/pl061.c2
-rw-r--r--drivers/gpio/sch_gpio.c295
-rw-r--r--drivers/gpio/timbgpio.c35
-rw-r--r--drivers/gpio/wm831x-gpio.c45
-rw-r--r--drivers/gpio/wm8350-gpiolib.c181
-rw-r--r--drivers/gpio/wm8994-gpio.c204
-rw-r--r--drivers/gpu/drm/drm_sysfs.c18
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c2
-rw-r--r--drivers/gpu/drm/ttm/ttm_memory.c2
-rw-r--r--drivers/hwmon/Kconfig45
-rw-r--r--drivers/hwmon/Makefile3
-rw-r--r--drivers/hwmon/adcxx.c15
-rw-r--r--drivers/hwmon/adt7411.c366
-rw-r--r--drivers/hwmon/adt7473.c1180
-rw-r--r--drivers/hwmon/asc7621.c1255
-rw-r--r--drivers/hwmon/fschmd.c15
-rw-r--r--drivers/hwmon/g760a.c2
-rw-r--r--drivers/hwmon/it87.c939
-rw-r--r--drivers/hwmon/lm90.c89
-rw-r--r--drivers/hwmon/tmp401.c7
-rw-r--r--drivers/hwmon/tmp421.c24
-rw-r--r--drivers/hwmon/vt8231.c3
-rw-r--r--drivers/hwmon/w83793.c482
-rw-r--r--drivers/i2c/busses/Kconfig26
-rw-r--r--drivers/i2c/busses/Makefile2
-rw-r--r--drivers/i2c/busses/i2c-designware.c4
-rw-r--r--drivers/i2c/busses/i2c-imx.c1
-rw-r--r--drivers/i2c/busses/i2c-isch.c68
-rw-r--r--drivers/i2c/busses/i2c-mpc.c194
-rw-r--r--drivers/i2c/busses/i2c-nomadik.c959
-rw-r--r--drivers/i2c/busses/i2c-omap.c46
-rw-r--r--drivers/i2c/busses/i2c-pnx.c11
-rw-r--r--drivers/i2c/busses/i2c-xiic.c824
-rw-r--r--drivers/ieee1394/nodemgr.c5
-rw-r--r--drivers/infiniband/core/cm.c2
-rw-r--r--drivers/infiniband/core/mad.c21
-rw-r--r--drivers/infiniband/core/sysfs.c2
-rw-r--r--drivers/infiniband/core/ucm.c13
-rw-r--r--drivers/infiniband/core/user_mad.c9
-rw-r--r--drivers/infiniband/core/uverbs_main.c9
-rw-r--r--drivers/input/misc/88pm860x_onkey.c155
-rw-r--r--drivers/input/misc/Kconfig10
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/touchscreen/88pm860x-ts.c236
-rw-r--r--drivers/input/touchscreen/Kconfig12
-rw-r--r--drivers/input/touchscreen/Makefile1
-rw-r--r--drivers/input/touchscreen/mc13783_ts.c4
-rw-r--r--drivers/leds/Kconfig7
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-88pm860x.c325
-rw-r--r--drivers/macintosh/windfarm_core.c1
-rw-r--r--drivers/macintosh/windfarm_smu_controls.c1
-rw-r--r--drivers/md/dm-crypt.c3
-rw-r--r--drivers/md/dm-delay.c8
-rw-r--r--drivers/md/dm-ioctl.c24
-rw-r--r--drivers/md/dm-linear.c3
-rw-r--r--drivers/md/dm-log.c3
-rw-r--r--drivers/md/dm-mpath.c111
-rw-r--r--drivers/md/dm-raid1.c53
-rw-r--r--drivers/md/dm-snap.c34
-rw-r--r--drivers/md/dm-stripe.c3
-rw-r--r--drivers/md/dm-sysfs.c2
-rw-r--r--drivers/md/dm-table.c12
-rw-r--r--drivers/md/dm-uevent.c7
-rw-r--r--drivers/md/dm.c25
-rw-r--r--drivers/md/dm.h4
-rw-r--r--drivers/md/md.c4
-rw-r--r--drivers/media/video/omap24xxcam.c2
-rw-r--r--drivers/mfd/88pm8607.c302
-rw-r--r--drivers/mfd/88pm860x-core.c740
-rw-r--r--drivers/mfd/88pm860x-i2c.c236
-rw-r--r--drivers/mfd/Kconfig72
-rw-r--r--drivers/mfd/Makefile8
-rw-r--r--drivers/mfd/ab3100-core.c54
-rw-r--r--drivers/mfd/ab3100-otp.c13
-rw-r--r--drivers/mfd/htc-egpio.c2
-rw-r--r--drivers/mfd/htc-i2cpld.c710
-rw-r--r--drivers/mfd/lpc_sch.c133
-rw-r--r--drivers/mfd/max8925-core.c656
-rw-r--r--drivers/mfd/max8925-i2c.c211
-rw-r--r--drivers/mfd/mc13783-core.c73
-rw-r--r--drivers/mfd/mfd-core.c5
-rw-r--r--drivers/mfd/sh_mobile_sdhi.c6
-rw-r--r--drivers/mfd/sm501.c7
-rw-r--r--drivers/mfd/t7l66xb.c4
-rw-r--r--drivers/mfd/tc6393xb.c2
-rw-r--r--drivers/mfd/twl-core.c41
-rw-r--r--drivers/mfd/twl4030-power.c52
-rw-r--r--drivers/mfd/ucb1x00-core.c1
-rw-r--r--drivers/mfd/wm831x-core.c51
-rw-r--r--drivers/mfd/wm8350-core.c35
-rw-r--r--drivers/mfd/wm8350-irq.c155
-rw-r--r--drivers/mfd/wm8994-core.c537
-rw-r--r--drivers/misc/Kconfig9
-rw-r--r--drivers/misc/iwmc3200top/main.c2
-rw-r--r--drivers/misc/lkdtm.c472
-rw-r--r--drivers/misc/phantom.c13
-rw-r--r--drivers/misc/sgi-xp/xpnet.c2
-rw-r--r--drivers/mmc/core/core.c12
-rw-r--r--drivers/mmc/core/sdio.c64
-rw-r--r--drivers/mmc/core/sdio_io.c56
-rw-r--r--drivers/mmc/host/Kconfig15
-rw-r--r--drivers/mmc/host/Makefile1
-rw-r--r--drivers/mmc/host/at91_mci.c224
-rw-r--r--drivers/mmc/host/bfin_sdh.c10
-rw-r--r--drivers/mmc/host/davinci_mmc.c45
-rw-r--r--drivers/mmc/host/ricoh_mmc.c262
-rw-r--r--drivers/mmc/host/s3cmci.c4
-rw-r--r--drivers/mmc/host/sdhci-pci.c24
-rw-r--r--drivers/mmc/host/sdhci.c76
-rw-r--r--drivers/mmc/host/tmio_mmc.c13
-rw-r--r--drivers/mmc/host/tmio_mmc.h6
-rw-r--r--drivers/mtd/ubi/build.c136
-rw-r--r--drivers/mtd/ubi/debug.h4
-rw-r--r--drivers/mtd/ubi/io.c120
-rw-r--r--drivers/mtd/ubi/scan.c11
-rw-r--r--drivers/mtd/ubi/wl.c17
-rw-r--r--drivers/net/bonding/bond_sysfs.c5
-rw-r--r--drivers/net/gianfar.c12
-rw-r--r--drivers/net/ibmveth.c2
-rw-r--r--drivers/net/iseries_veth.c4
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c2
-rw-r--r--drivers/net/ixgbevf/ixgbevf_main.c2
-rw-r--r--drivers/net/wireless/ath/ar9170/main.c2
-rw-r--r--drivers/net/wireless/iwmc3200wifi/debugfs.c2
-rw-r--r--drivers/net/wireless/iwmc3200wifi/rx.c2
-rw-r--r--drivers/parisc/eisa_enumerator.c2
-rw-r--r--drivers/parisc/pdc_stable.c2
-rw-r--r--drivers/parisc/superio.c2
-rw-r--r--drivers/pci/bus.c4
-rw-r--r--drivers/pci/hotplug/fakephp.c2
-rw-r--r--drivers/pci/pci-sysfs.c5
-rw-r--r--drivers/pci/pci.c47
-rw-r--r--drivers/pci/quirks.c85
-rw-r--r--drivers/pci/slot.c2
-rw-r--r--drivers/pcmcia/ds.c8
-rw-r--r--drivers/platform/x86/Kconfig1
-rw-r--r--drivers/platform/x86/hp-wmi.c4
-rw-r--r--drivers/platform/x86/msi-laptop.c360
-rw-r--r--drivers/power/Kconfig7
-rw-r--r--drivers/power/Makefile1
-rw-r--r--drivers/power/max8925_power.c534
-rw-r--r--drivers/power/wm8350_power.c26
-rw-r--r--drivers/regulator/88pm8607.c318
-rw-r--r--drivers/regulator/Kconfig8
-rw-r--r--drivers/regulator/Makefile1
-rw-r--r--drivers/regulator/max8925-regulator.c306
-rw-r--r--drivers/regulator/wm8350-regulator.c2
-rw-r--r--drivers/rtc/Kconfig10
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/class.c1
-rw-r--r--drivers/rtc/rtc-at91sam9.c2
-rw-r--r--drivers/rtc/rtc-coh901331.c5
-rw-r--r--drivers/rtc/rtc-ep93xx.c71
-rw-r--r--drivers/rtc/rtc-max8925.c314
-rw-r--r--drivers/rtc/rtc-mc13783.c214
-rw-r--r--drivers/rtc/rtc-mxc.c7
-rw-r--r--drivers/rtc/rtc-pcf2123.c2
-rw-r--r--drivers/rtc/rtc-twl.c4
-rw-r--r--drivers/rtc/rtc-wm8350.c11
-rw-r--r--drivers/s390/block/dasd.c36
-rw-r--r--drivers/s390/block/dasd_3990_erp.c4
-rw-r--r--drivers/s390/block/dasd_devmap.c13
-rw-r--r--drivers/s390/block/dasd_diag.c6
-rw-r--r--drivers/s390/block/dasd_eckd.c27
-rw-r--r--drivers/s390/block/dasd_fba.c10
-rw-r--r--drivers/s390/block/dasd_genhd.c3
-rw-r--r--drivers/s390/block/dasd_int.h7
-rw-r--r--drivers/s390/block/dasd_ioctl.c6
-rw-r--r--drivers/s390/cio/device.c5
-rw-r--r--drivers/s390/cio/qdio_debug.c1
-rw-r--r--drivers/s390/cio/qdio_main.c3
-rw-r--r--drivers/s390/net/Kconfig10
-rw-r--r--drivers/s390/net/Makefile1
-rw-r--r--drivers/s390/net/qeth_core_main.c3
-rw-r--r--drivers/s390/net/smsgiucv.c15
-rw-r--r--drivers/s390/net/smsgiucv.h8
-rw-r--r--drivers/s390/net/smsgiucv_app.c211
-rw-r--r--drivers/s390/scsi/zfcp_qdio.c2
-rw-r--r--drivers/scsi/sgiwd93.c2
-rw-r--r--drivers/scsi/sni_53c710.c2
-rw-r--r--drivers/serial/Kconfig4
-rw-r--r--drivers/serial/sh-sci.c616
-rw-r--r--drivers/staging/Kconfig14
-rw-r--r--drivers/staging/Makefile8
-rw-r--r--drivers/staging/altpciechdma/Kconfig10
-rw-r--r--drivers/staging/altpciechdma/Makefile2
-rw-r--r--drivers/staging/altpciechdma/TODO15
-rw-r--r--drivers/staging/altpciechdma/altpciechdma.c1182
-rw-r--r--drivers/staging/arlan/Makefile2
-rw-r--r--drivers/staging/arlan/arlan.h136
-rw-r--r--drivers/staging/asus_oled/asus_oled.c34
-rw-r--r--drivers/staging/b3dfg/Kconfig10
-rw-r--r--drivers/staging/b3dfg/Makefile1
-rw-r--r--drivers/staging/b3dfg/TODO4
-rw-r--r--drivers/staging/b3dfg/b3dfg.c1100
-rw-r--r--drivers/staging/batman-adv/Kconfig6
-rw-r--r--drivers/staging/batman-adv/Makefile2
-rw-r--r--drivers/staging/batman-adv/README84
-rw-r--r--drivers/staging/batman-adv/TODO24
-rw-r--r--drivers/staging/batman-adv/aggregation.c13
-rw-r--r--drivers/staging/batman-adv/bitarray.c15
-rw-r--r--drivers/staging/batman-adv/compat.h75
-rw-r--r--drivers/staging/batman-adv/device.c53
-rw-r--r--drivers/staging/batman-adv/hard-interface.c209
-rw-r--r--drivers/staging/batman-adv/hard-interface.h4
-rw-r--r--drivers/staging/batman-adv/hash.c23
-rw-r--r--drivers/staging/batman-adv/hash.h5
-rw-r--r--drivers/staging/batman-adv/log.c179
-rw-r--r--drivers/staging/batman-adv/main.c55
-rw-r--r--drivers/staging/batman-adv/main.h46
-rw-r--r--drivers/staging/batman-adv/originator.c252
-rw-r--r--drivers/staging/batman-adv/originator.h (renamed from drivers/staging/batman-adv/log.h)19
-rw-r--r--drivers/staging/batman-adv/packet.h2
-rw-r--r--drivers/staging/batman-adv/proc.c508
-rw-r--r--drivers/staging/batman-adv/proc.h13
-rw-r--r--drivers/staging/batman-adv/routing.c1304
-rw-r--r--drivers/staging/batman-adv/routing.h21
-rw-r--r--drivers/staging/batman-adv/send.c172
-rw-r--r--drivers/staging/batman-adv/send.h5
-rw-r--r--drivers/staging/batman-adv/soft-interface.c96
-rw-r--r--drivers/staging/batman-adv/soft-interface.h3
-rw-r--r--drivers/staging/batman-adv/translation-table.c94
-rw-r--r--drivers/staging/batman-adv/translation-table.h1
-rw-r--r--drivers/staging/batman-adv/types.h14
-rw-r--r--drivers/staging/batman-adv/vis.c201
-rw-r--r--drivers/staging/batman-adv/vis.h13
-rw-r--r--drivers/staging/comedi/comedi_compat32.c1
-rw-r--r--drivers/staging/comedi/comedi_fops.c12
-rw-r--r--drivers/staging/comedi/drivers.c30
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c7
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_common.h4
-rw-r--r--drivers/staging/comedi/drivers/addi-data/addi_eeprom.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c12
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c121
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c2
-rw-r--r--drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c6
-rw-r--r--drivers/staging/comedi/drivers/adl_pci9118.c6
-rw-r--r--drivers/staging/comedi/drivers/adq12b.c66
-rw-r--r--drivers/staging/comedi/drivers/adv_pci1710.c21
-rw-r--r--drivers/staging/comedi/drivers/aio_iiro_16.c4
-rw-r--r--drivers/staging/comedi/drivers/amplc_dio200.c122
-rw-r--r--drivers/staging/comedi/drivers/amplc_pc236.c46
-rw-r--r--drivers/staging/comedi/drivers/amplc_pci224.c16
-rw-r--r--drivers/staging/comedi/drivers/c6xdigio.c57
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidas.c28
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidda.c12
-rw-r--r--drivers/staging/comedi/drivers/cb_pcidio.c6
-rw-r--r--drivers/staging/comedi/drivers/cb_pcimdas.c8
-rw-r--r--drivers/staging/comedi/drivers/cb_pcimdda.c8
-rw-r--r--drivers/staging/comedi/drivers/comedi_bond.c2
-rw-r--r--drivers/staging/comedi/drivers/contec_pci_dio.c3
-rw-r--r--drivers/staging/comedi/drivers/das08_cs.c4
-rw-r--r--drivers/staging/comedi/drivers/das6402.c2
-rw-r--r--drivers/staging/comedi/drivers/das800.c6
-rw-r--r--drivers/staging/comedi/drivers/dmm32at.c5
-rw-r--r--drivers/staging/comedi/drivers/dt2801.c33
-rw-r--r--drivers/staging/comedi/drivers/dt2815.c89
-rw-r--r--drivers/staging/comedi/drivers/dt9812.c2
-rw-r--r--drivers/staging/comedi/drivers/fl512.c72
-rw-r--r--drivers/staging/comedi/drivers/jr3_pci.c2
-rw-r--r--drivers/staging/comedi/drivers/mpc624.c2
-rw-r--r--drivers/staging/comedi/drivers/ni_65xx.c49
-rw-r--r--drivers/staging/comedi/drivers/ni_660x.c73
-rw-r--r--drivers/staging/comedi/drivers/ni_670x.c32
-rw-r--r--drivers/staging/comedi/drivers/ni_atmio.c34
-rw-r--r--drivers/staging/comedi/drivers/ni_daq_700.c24
-rw-r--r--drivers/staging/comedi/drivers/ni_labpc.c276
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_common.c2
-rw-r--r--drivers/staging/comedi/drivers/ni_pcidio.c83
-rw-r--r--drivers/staging/comedi/drivers/pcl711.c29
-rw-r--r--drivers/staging/comedi/drivers/pcl724.c26
-rw-r--r--drivers/staging/comedi/drivers/pcl725.c6
-rw-r--r--drivers/staging/comedi/drivers/pcl730.c6
-rw-r--r--drivers/staging/comedi/drivers/pcl812.c16
-rw-r--r--drivers/staging/comedi/drivers/pcl816.c66
-rw-r--r--drivers/staging/comedi/drivers/pcl818.c39
-rw-r--r--drivers/staging/comedi/drivers/pcm3724.c85
-rw-r--r--drivers/staging/comedi/drivers/pcm3730.c6
-rw-r--r--drivers/staging/comedi/drivers/pcmad.c22
-rw-r--r--drivers/staging/comedi/drivers/pcmmio.c2
-rw-r--r--drivers/staging/comedi/drivers/poc.c14
-rw-r--r--drivers/staging/comedi/drivers/rti800.c61
-rw-r--r--drivers/staging/comedi/drivers/rti802.c8
-rw-r--r--drivers/staging/comedi/drivers/s626.c2
-rw-r--r--drivers/staging/comedi/drivers/serial2002.c2
-rw-r--r--drivers/staging/comedi/drivers/ssv_dnp.c6
-rw-r--r--drivers/staging/comedi/drivers/usbdux.c5
-rw-r--r--drivers/staging/comedi/drivers/usbduxfast.c5
-rw-r--r--drivers/staging/comedi/drivers/vmk80xx.c2
-rw-r--r--drivers/staging/crystalhd/Kconfig6
-rw-r--r--drivers/staging/crystalhd/Makefile6
-rw-r--r--drivers/staging/crystalhd/TODO16
-rw-r--r--drivers/staging/crystalhd/bc_dts_defs.h498
-rw-r--r--drivers/staging/crystalhd/bc_dts_glob_lnx.h299
-rw-r--r--drivers/staging/crystalhd/bc_dts_types.h121
-rw-r--r--drivers/staging/crystalhd/bcm_70012_regs.h757
-rw-r--r--drivers/staging/crystalhd/crystalhd_cmds.c1058
-rw-r--r--drivers/staging/crystalhd/crystalhd_cmds.h88
-rw-r--r--drivers/staging/crystalhd/crystalhd_fw_if.h369
-rw-r--r--drivers/staging/crystalhd/crystalhd_hw.c2395
-rw-r--r--drivers/staging/crystalhd/crystalhd_hw.h398
-rw-r--r--drivers/staging/crystalhd/crystalhd_lnx.c765
-rw-r--r--drivers/staging/crystalhd/crystalhd_lnx.h96
-rw-r--r--drivers/staging/crystalhd/crystalhd_misc.c1030
-rw-r--r--drivers/staging/crystalhd/crystalhd_misc.h229
-rw-r--r--drivers/staging/cx25821/cx25821-audups11.c3
-rw-r--r--drivers/staging/cx25821/cx25821-medusa-video.c4
-rw-r--r--drivers/staging/cx25821/cx25821-video.c5
-rw-r--r--drivers/staging/dream/camera/Kconfig2
-rw-r--r--drivers/staging/dream/camera/Makefile1
-rw-r--r--drivers/staging/dream/camera/msm_camera.c69
-rw-r--r--drivers/staging/dream/camera/msm_vfe7x.c3
-rw-r--r--drivers/staging/dream/camera/s5k3e2fx.c30
-rw-r--r--drivers/staging/dream/include/linux/android_pmem.h80
-rw-r--r--drivers/staging/dream/include/linux/gpio_event.h154
-rw-r--r--drivers/staging/dream/include/linux/msm_adsp.h84
-rw-r--r--drivers/staging/dream/include/linux/msm_audio.h115
-rw-r--r--drivers/staging/dream/include/linux/msm_rpcrouter.h47
-rw-r--r--drivers/staging/dream/include/linux/wakelock.h91
-rw-r--r--drivers/staging/dream/include/mach/camera.h279
-rw-r--r--drivers/staging/dream/include/mach/msm_adsp.h112
-rw-r--r--drivers/staging/dream/include/mach/msm_rpcrouter.h179
-rw-r--r--drivers/staging/dream/include/mach/msm_smd.h107
-rw-r--r--drivers/staging/dream/include/mach/qdsp5/qdsp5audplaycmdi.h94
-rw-r--r--drivers/staging/dream/include/mach/qdsp5/qdsp5audplaymsg.h70
-rw-r--r--drivers/staging/dream/include/mach/qdsp5/qdsp5audppcmdi.h914
-rw-r--r--drivers/staging/dream/include/mach/qdsp5/qdsp5audppmsg.h318
-rw-r--r--drivers/staging/dream/include/mach/qdsp5/qdsp5audpreproccmdi.h256
-rw-r--r--drivers/staging/dream/include/mach/qdsp5/qdsp5audpreprocmsg.h85
-rw-r--r--drivers/staging/dream/include/mach/qdsp5/qdsp5audreccmdi.h176
-rw-r--r--drivers/staging/dream/include/mach/qdsp5/qdsp5audrecmsg.h127
-rw-r--r--drivers/staging/dream/include/mach/qdsp5/qdsp5jpegcmdi.h376
-rw-r--r--drivers/staging/dream/include/mach/qdsp5/qdsp5jpegmsg.h177
-rw-r--r--drivers/staging/dream/include/mach/qdsp5/qdsp5lpmcmdi.h82
-rw-r--r--drivers/staging/dream/include/mach/qdsp5/qdsp5lpmmsg.h80
-rw-r--r--drivers/staging/dream/include/mach/qdsp5/qdsp5vdeccmdi.h235
-rw-r--r--drivers/staging/dream/include/mach/qdsp5/qdsp5vdecmsg.h107
-rw-r--r--drivers/staging/dream/include/mach/qdsp5/qdsp5venccmdi.h212
-rw-r--r--drivers/staging/dream/include/mach/qdsp5/qdsp5vfecmdi.h910
-rw-r--r--drivers/staging/dream/include/mach/qdsp5/qdsp5vfemsg.h290
-rw-r--r--drivers/staging/dream/include/media/msm_camera.h388
-rw-r--r--drivers/staging/dream/pmem.c26
-rw-r--r--drivers/staging/dream/qdsp5/Makefile1
-rw-r--r--drivers/staging/dream/qdsp5/audio_mp3.c3
-rw-r--r--drivers/staging/dream/smd/Makefile1
-rw-r--r--drivers/staging/dream/smd/smd_rpcrouter.c2
-rw-r--r--drivers/staging/dt3155/Kconfig4
-rw-r--r--drivers/staging/dt3155/Makefile6
-rw-r--r--drivers/staging/dt3155/TODO10
-rw-r--r--drivers/staging/dt3155/allocator.README98
-rw-r--r--drivers/staging/dt3155/allocator.c295
-rw-r--r--drivers/staging/dt3155/allocator.h28
-rw-r--r--drivers/staging/dt3155/dt3155.h171
-rw-r--r--drivers/staging/dt3155/dt3155.sysvinit60
-rw-r--r--drivers/staging/dt3155/dt3155_drv.c1095
-rw-r--r--drivers/staging/dt3155/dt3155_drv.h45
-rw-r--r--drivers/staging/dt3155/dt3155_io.c175
-rw-r--r--drivers/staging/dt3155/dt3155_io.h358
-rw-r--r--drivers/staging/dt3155/dt3155_isr.c516
-rw-r--r--drivers/staging/dt3155/dt3155_isr.h77
-rw-r--r--drivers/staging/et131x/et1310_address_map.h617
-rw-r--r--drivers/staging/et131x/et1310_eeprom.c41
-rw-r--r--drivers/staging/et131x/et1310_eeprom.h103
-rw-r--r--drivers/staging/et131x/et1310_jagcore.h94
-rw-r--r--drivers/staging/et131x/et1310_mac.c104
-rw-r--r--drivers/staging/et131x/et1310_mac.h93
-rw-r--r--drivers/staging/et131x/et1310_phy.c7
-rw-r--r--drivers/staging/et131x/et1310_phy.h34
-rw-r--r--drivers/staging/et131x/et1310_pm.c6
-rw-r--r--drivers/staging/et131x/et1310_pm.h85
-rw-r--r--drivers/staging/et131x/et1310_rx.c301
-rw-r--r--drivers/staging/et131x/et1310_rx.h253
-rw-r--r--drivers/staging/et131x/et1310_tx.c10
-rw-r--r--drivers/staging/et131x/et1310_tx.h14
-rw-r--r--drivers/staging/et131x/et131x.h153
-rw-r--r--drivers/staging/et131x/et131x_adapter.h43
-rw-r--r--drivers/staging/et131x/et131x_config.h67
-rw-r--r--drivers/staging/et131x/et131x_initpci.c12
-rw-r--r--drivers/staging/et131x/et131x_initpci.h73
-rw-r--r--drivers/staging/et131x/et131x_isr.c34
-rw-r--r--drivers/staging/et131x/et131x_isr.h65
-rw-r--r--drivers/staging/et131x/et131x_netdev.c63
-rw-r--r--drivers/staging/et131x/et131x_netdev.h64
-rw-r--r--drivers/staging/et131x/et131x_version.h9
-rw-r--r--drivers/staging/frontier/alphatrack.c2
-rw-r--r--drivers/staging/frontier/tranzport.c2
-rw-r--r--drivers/staging/go7007/go7007-driver.c2
-rw-r--r--drivers/staging/go7007/go7007-usb.c4
-rw-r--r--drivers/staging/go7007/s2250-board.c2
-rw-r--r--drivers/staging/go7007/s2250-loader.c4
-rw-r--r--drivers/staging/go7007/saa7134-go7007.c1
-rw-r--r--drivers/staging/go7007/wis-ov7640.c2
-rw-r--r--drivers/staging/go7007/wis-saa7113.c2
-rw-r--r--drivers/staging/go7007/wis-saa7115.c2
-rw-r--r--drivers/staging/go7007/wis-sony-tuner.c2
-rw-r--r--drivers/staging/go7007/wis-tw2804.c2
-rw-r--r--drivers/staging/go7007/wis-tw9903.c2
-rw-r--r--drivers/staging/go7007/wis-uda1342.c2
-rw-r--r--drivers/staging/hv/Channel.c3
-rw-r--r--drivers/staging/hv/Hv.c205
-rw-r--r--drivers/staging/hv/Hv.h10
-rw-r--r--drivers/staging/hv/NetVscApi.h4
-rw-r--r--drivers/staging/hv/RingBuffer.c153
-rw-r--r--drivers/staging/hv/RndisFilter.c10
-rw-r--r--drivers/staging/hv/StorVsc.c3
-rw-r--r--drivers/staging/hv/StorVscApi.h5
-rw-r--r--drivers/staging/hv/VersionInfo.h22
-rw-r--r--drivers/staging/hv/Vmbus.c6
-rw-r--r--drivers/staging/hv/blkvsc_drv.c10
-rw-r--r--drivers/staging/hv/netvsc_drv.c29
-rw-r--r--drivers/staging/hv/storvsc_drv.c227
-rw-r--r--drivers/staging/hv/vmbus.h12
-rw-r--r--drivers/staging/hv/vmbus_drv.c68
-rw-r--r--drivers/staging/iio/industrialio-core.c35
-rw-r--r--drivers/staging/iio/ring_generic.h3
-rw-r--r--drivers/staging/iio/ring_sw.c3
-rw-r--r--drivers/staging/iio/trigger_consumer.h4
-rw-r--r--drivers/staging/line6/driver.c2
-rw-r--r--drivers/staging/line6/variax.c2
-rw-r--r--drivers/staging/mimio/Kconfig10
-rw-r--r--drivers/staging/mimio/Makefile1
-rw-r--r--drivers/staging/mimio/mimio.c914
-rw-r--r--drivers/staging/otus/80211core/cagg.c18
-rw-r--r--drivers/staging/otus/80211core/ccmd.c2
-rw-r--r--drivers/staging/otus/80211core/cfunc.c2
-rw-r--r--drivers/staging/otus/80211core/cmm.c4
-rw-r--r--drivers/staging/otus/80211core/cmmsta.c7
-rw-r--r--drivers/staging/otus/80211core/cpsmgr.c2
-rw-r--r--drivers/staging/otus/80211core/cscanmgr.c2
-rw-r--r--drivers/staging/otus/80211core/ctkip.c5
-rw-r--r--drivers/staging/otus/80211core/ctxrx.c8
-rw-r--r--drivers/staging/otus/80211core/ledmgr.c1
-rw-r--r--drivers/staging/otus/80211core/pub_zfi.h1
-rw-r--r--drivers/staging/otus/Kconfig2
-rw-r--r--drivers/staging/otus/apdbg.c53
-rw-r--r--drivers/staging/otus/hal/hpmain.c4
-rw-r--r--drivers/staging/otus/hal/hpreg.c133
-rw-r--r--drivers/staging/otus/hal/hprw.c1
-rw-r--r--drivers/staging/otus/ioctl.c16
-rw-r--r--drivers/staging/otus/usbdrv.c4
-rw-r--r--drivers/staging/otus/wrap_pkt.c10
-rw-r--r--drivers/staging/otus/zdusb.c2
-rw-r--r--drivers/staging/p9auth/Kconfig9
-rw-r--r--drivers/staging/p9auth/Makefile1
-rw-r--r--drivers/staging/p9auth/p9auth.c408
-rw-r--r--drivers/staging/panel/panel.c1
-rw-r--r--drivers/staging/phison/phison.c2
-rw-r--r--drivers/staging/pohmelfs/inode.c28
-rw-r--r--drivers/staging/pohmelfs/netfs.h3
-rw-r--r--drivers/staging/quatech_usb2/quatech_usb2.c2
-rw-r--r--drivers/staging/ramzswap/Kconfig2
-rw-r--r--drivers/staging/ramzswap/ramzswap.txt6
-rw-r--r--drivers/staging/ramzswap/ramzswap_drv.c144
-rw-r--r--drivers/staging/ramzswap/ramzswap_drv.h67
-rw-r--r--drivers/staging/ramzswap/ramzswap_ioctl.h7
-rw-r--r--drivers/staging/ramzswap/xvmalloc.c4
-rw-r--r--drivers/staging/ramzswap/xvmalloc.h2
-rw-r--r--drivers/staging/ramzswap/xvmalloc_int.h4
-rw-r--r--drivers/staging/rar/Kconfig17
-rw-r--r--drivers/staging/rar/Makefile2
-rw-r--r--drivers/staging/rar/rar_driver.c444
-rw-r--r--drivers/staging/rar/rar_driver.h99
-rw-r--r--drivers/staging/rar_register/Kconfig30
-rw-r--r--drivers/staging/rar_register/Makefile2
-rw-r--r--drivers/staging/rar_register/rar_register.c615
-rw-r--r--drivers/staging/rar_register/rar_register.h84
-rw-r--r--drivers/staging/rt2860/Kconfig2
-rw-r--r--drivers/staging/rt2860/common/firmware.h558
-rw-r--r--drivers/staging/rt2860/common/firmware_3070.h517
-rw-r--r--drivers/staging/rt2860/common/rtmp_mcu.c167
-rw-r--r--drivers/staging/rt2860/rt_linux.c13
-rw-r--r--drivers/staging/rt2860/rt_linux.h4
-rw-r--r--drivers/staging/rt2860/rt_main_dev.c2
-rw-r--r--drivers/staging/rt2860/rtmp.h7
-rw-r--r--drivers/staging/rt2860/sta/connect.c4
-rw-r--r--drivers/staging/rt2860/sta_ioctl.c5
-rw-r--r--drivers/staging/rt2860/usb_main_dev.c6
-rw-r--r--drivers/staging/rt2870/Kconfig2
-rw-r--r--drivers/staging/rt2870/common/rtusb_io.c10
-rw-r--r--drivers/staging/rt3070/firmware.h558
-rw-r--r--drivers/staging/rt3070/md4.h8
-rw-r--r--drivers/staging/rt3090/firmware.h517
-rw-r--r--drivers/staging/rtl8187se/Kconfig1
-rw-r--r--drivers/staging/rtl8187se/Makefile1
-rw-r--r--drivers/staging/rtl8187se/TODO1
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211.h5
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c21
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c20
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c48
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c2
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c3
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c6
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c6
-rw-r--r--drivers/staging/rtl8187se/r8180.h4
-rw-r--r--drivers/staging/rtl8187se/r8180_93cx6.c146
-rw-r--r--drivers/staging/rtl8187se/r8180_93cx6.h17
-rw-r--r--drivers/staging/rtl8187se/r8180_core.c502
-rw-r--r--drivers/staging/rtl8187se/r8180_dm.c67
-rw-r--r--drivers/staging/rtl8187se/r8180_rtl8225z2.c232
-rw-r--r--drivers/staging/rtl8187se/r8185b_init.c986
-rw-r--r--drivers/staging/rtl8192e/Makefile9
-rw-r--r--drivers/staging/rtl8192e/dot11d.h138
-rw-r--r--drivers/staging/rtl8192e/ieee80211.h3
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211.h160
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c2
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c37
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c29
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c148
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c246
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c26
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c80
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c6
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c6
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h4
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c65
-rw-r--r--drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c6
-rw-r--r--drivers/staging/rtl8192e/r8180_93cx6.c63
-rw-r--r--drivers/staging/rtl8192e/r8180_93cx6.h33
-rw-r--r--drivers/staging/rtl8192e/r8190_rtl8256.c360
-rw-r--r--drivers/staging/rtl8192e/r8190_rtl8256.h49
-rw-r--r--drivers/staging/rtl8192e/r8192E.h23
-rw-r--r--drivers/staging/rtl8192e/r8192E_core.c773
-rw-r--r--drivers/staging/rtl8192e/r8192E_dm.c40
-rw-r--r--drivers/staging/rtl8192e/r8192E_hw.h8
-rw-r--r--drivers/staging/rtl8192e/r8192E_wx.c212
-rw-r--r--drivers/staging/rtl8192e/r8192E_wx.h1
-rw-r--r--drivers/staging/rtl8192e/r819xE_cmdpkt.c2
-rw-r--r--drivers/staging/rtl8192e/r819xE_firmware.c85
-rw-r--r--drivers/staging/rtl8192e/r819xE_phy.c2
-rw-r--r--drivers/staging/rtl8192e/r819xE_phy.h194
-rw-r--r--drivers/staging/rtl8192e/r819xE_phyreg.h1117
-rw-r--r--drivers/staging/rtl8192su/Kconfig3
-rw-r--r--drivers/staging/rtl8192su/TODO1
-rw-r--r--drivers/staging/rtl8192su/ieee80211/ieee80211.h5
-rw-r--r--drivers/staging/rtl8192su/ieee80211/ieee80211_crypt.c19
-rw-r--r--drivers/staging/rtl8192su/ieee80211/ieee80211_crypt_ccmp.c21
-rw-r--r--drivers/staging/rtl8192su/ieee80211/ieee80211_crypt_tkip.c20
-rw-r--r--drivers/staging/rtl8192su/ieee80211/ieee80211_module.c2
-rw-r--r--drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c48
-rw-r--r--drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c6
-rw-r--r--drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c4
-rw-r--r--drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c6
-rw-r--r--drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c21
-rw-r--r--drivers/staging/rtl8192su/ieee80211/rtl819x_HTProc.c2
-rw-r--r--drivers/staging/rtl8192su/ieee80211/rtl819x_TSProc.c6
-rw-r--r--drivers/staging/rtl8192su/r8192SU_HWImg.c4276
-rw-r--r--drivers/staging/rtl8192su/r8192SU_HWImg.h2
-rw-r--r--drivers/staging/rtl8192su/r8192S_firmware.c126
-rw-r--r--drivers/staging/rtl8192su/r8192S_firmware.h7
-rw-r--r--drivers/staging/rtl8192su/r8192S_phy.c16
-rw-r--r--drivers/staging/rtl8192su/r8192U.h1
-rw-r--r--drivers/staging/rtl8192su/r8192U_core.c183
-rw-r--r--drivers/staging/rtl8192su/r8192U_dm.c2
-rw-r--r--drivers/staging/rtl8192u/Kconfig3
-rw-r--r--drivers/staging/rtl8192u/Makefile2
-rw-r--r--drivers/staging/rtl8192u/ieee80211.h3
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211.h4
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c21
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c20
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_module.c2
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c48
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c2
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c4
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c6
-rw-r--r--drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c6
-rw-r--r--drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c4
-rw-r--r--drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c6
-rw-r--r--drivers/staging/rtl8192u/r8192U_core.c8
-rw-r--r--drivers/staging/samsung-laptop/samsung-laptop.c9
-rw-r--r--drivers/staging/sep/sep_driver.c28
-rw-r--r--drivers/staging/serqt_usb2/serqt_usb2.c4
-rw-r--r--drivers/staging/slicoss/slic.h9
-rw-r--r--drivers/staging/slicoss/slicoss.c116
-rw-r--r--drivers/staging/sm7xx/Kconfig7
-rw-r--r--drivers/staging/sm7xx/TODO1
-rw-r--r--drivers/staging/sm7xx/smtc2d.c979
-rw-r--r--drivers/staging/sm7xx/smtc2d.h530
-rw-r--r--drivers/staging/sm7xx/smtcfb.c131
-rw-r--r--drivers/staging/udlfb/Kconfig14
-rw-r--r--drivers/staging/udlfb/udlfb.c1993
-rw-r--r--drivers/staging/udlfb/udlfb.h281
-rw-r--r--drivers/staging/usbip/Kconfig7
-rw-r--r--drivers/staging/usbip/Makefile2
-rw-r--r--drivers/staging/usbip/usbip_common.c90
-rw-r--r--drivers/staging/usbip/usbip_common.h8
-rw-r--r--drivers/staging/vme/Kconfig2
-rw-r--r--drivers/staging/vme/Makefile1
-rw-r--r--drivers/staging/vme/TODO28
-rw-r--r--drivers/staging/vme/boards/Kconfig9
-rw-r--r--drivers/staging/vme/boards/Makefile5
-rw-r--r--drivers/staging/vme/boards/vme_vmivme7805.c124
-rw-r--r--drivers/staging/vme/boards/vme_vmivme7805.h37
-rw-r--r--drivers/staging/vme/bridges/Kconfig2
-rw-r--r--drivers/staging/vme/bridges/vme_ca91cx42.c1592
-rw-r--r--drivers/staging/vme/bridges/vme_ca91cx42.h136
-rw-r--r--drivers/staging/vme/bridges/vme_tsi148.c1010
-rw-r--r--drivers/staging/vme/bridges/vme_tsi148.h16
-rw-r--r--drivers/staging/vme/devices/vme_user.c65
-rw-r--r--drivers/staging/vme/vme.c248
-rw-r--r--drivers/staging/vme/vme.h33
-rw-r--r--drivers/staging/vme/vme_api.txt27
-rw-r--r--drivers/staging/vme/vme_bridge.h107
-rw-r--r--drivers/staging/vt6655/card.c6
-rw-r--r--drivers/staging/vt6655/device_main.c5
-rw-r--r--drivers/staging/vt6655/iwctl.c2
-rw-r--r--drivers/staging/winbond/core.h2
-rw-r--r--drivers/staging/winbond/localpara.h34
-rw-r--r--drivers/staging/winbond/mds_f.h3
-rw-r--r--drivers/staging/winbond/mds_s.h28
-rw-r--r--drivers/staging/winbond/mlme_s.h8
-rw-r--r--drivers/staging/winbond/mto.h5
-rw-r--r--drivers/staging/winbond/reg.c10
-rw-r--r--drivers/staging/winbond/scan_s.h1
-rw-r--r--drivers/staging/winbond/sme_api.h4
-rw-r--r--drivers/staging/winbond/wb35reg_f.h2
-rw-r--r--drivers/staging/winbond/wbusb.c24
-rw-r--r--drivers/staging/wlags49_h2/wl_main.c2
-rw-r--r--drivers/staging/wlags49_h2/wl_netdev.c2
-rw-r--r--drivers/staging/wlags49_h2/wl_pci.c1
-rw-r--r--drivers/staging/wlags49_h2/wl_profile.c76
-rw-r--r--drivers/staging/wlags49_h2/wl_util.c49
-rw-r--r--drivers/staging/wlags49_h2/wl_util.h2
-rw-r--r--drivers/staging/wlan-ng/Kconfig4
-rw-r--r--drivers/staging/wlan-ng/hfa384x.h180
-rw-r--r--drivers/staging/wlan-ng/hfa384x_usb.c42
-rw-r--r--drivers/staging/wlan-ng/p80211conv.c16
-rw-r--r--drivers/staging/wlan-ng/p80211conv.h4
-rw-r--r--drivers/staging/wlan-ng/p80211metadef.h18
-rw-r--r--drivers/staging/wlan-ng/p80211mgmt.h42
-rw-r--r--drivers/staging/wlan-ng/p80211netdev.c7
-rw-r--r--drivers/staging/wlan-ng/p80211netdev.h44
-rw-r--r--drivers/staging/wlan-ng/p80211req.c2
-rw-r--r--drivers/staging/wlan-ng/p80211req.h2
-rw-r--r--drivers/staging/wlan-ng/p80211types.h18
-rw-r--r--drivers/staging/wlan-ng/p80211wext.c83
-rw-r--r--drivers/staging/wlan-ng/prism2fw.c69
-rw-r--r--drivers/staging/wlan-ng/prism2mgmt.c30
-rw-r--r--drivers/staging/wlan-ng/prism2mgmt.h48
-rw-r--r--drivers/staging/wlan-ng/prism2mib.c10
-rw-r--r--drivers/staging/wlan-ng/prism2sta.c20
-rw-r--r--drivers/staging/wlan-ng/prism2usb.c6
-rw-r--r--drivers/uio/Kconfig24
-rw-r--r--drivers/uio/Makefile2
-rw-r--r--drivers/uio/uio.c4
-rw-r--r--drivers/uio/uio_netx.c172
-rw-r--r--drivers/uio/uio_smx.c140
-rw-r--r--drivers/usb/core/devices.c69
-rw-r--r--drivers/usb/core/driver.c4
-rw-r--r--drivers/uwb/driver.c5
-rw-r--r--drivers/uwb/umc-bus.c4
-rw-r--r--drivers/uwb/uwb-internal.h4
-rw-r--r--drivers/uwb/wlp/sysfs.c3
-rw-r--r--drivers/video/acornfb.c2
-rw-r--r--drivers/video/arcfb.c2
-rw-r--r--drivers/video/backlight/88pm860x_bl.c304
-rw-r--r--drivers/video/backlight/Kconfig13
-rw-r--r--drivers/video/backlight/Makefile2
-rw-r--r--drivers/video/backlight/max8925_bl.c200
-rw-r--r--drivers/video/cobalt_lcdfb.c2
-rw-r--r--drivers/video/console/Kconfig1
-rw-r--r--drivers/video/console/vgacon.c2
-rw-r--r--drivers/video/efifb.c2
-rw-r--r--drivers/video/epson1355fb.c2
-rw-r--r--drivers/video/gbefb.c2
-rw-r--r--drivers/video/hgafb.c2
-rw-r--r--drivers/video/hitfb.c2
-rw-r--r--drivers/video/omap2/dss/manager.c2
-rw-r--r--drivers/video/omap2/dss/overlay.c2
-rw-r--r--drivers/video/q40fb.c2
-rw-r--r--drivers/video/s3c2410fb.c4
-rw-r--r--drivers/video/sa1100fb.c2
-rw-r--r--drivers/video/sgivwfb.c2
-rw-r--r--drivers/video/sh_mobile_lcdcfb.c2
-rw-r--r--drivers/video/vesafb.c2
-rw-r--r--drivers/video/vfb.c2
-rw-r--r--drivers/video/vga16fb.c2
-rw-r--r--drivers/video/w100fb.c2
-rw-r--r--drivers/virtio/virtio_pci.c1
-rw-r--r--drivers/w1/masters/omap_hdq.c4
-rw-r--r--drivers/watchdog/Kconfig20
-rw-r--r--drivers/watchdog/Makefile2
-rw-r--r--drivers/watchdog/acquirewdt.c2
-rw-r--r--drivers/watchdog/advantechwdt.c2
-rw-r--r--drivers/watchdog/adx_wdt.c2
-rw-r--r--drivers/watchdog/alim1535_wdt.c2
-rw-r--r--drivers/watchdog/alim7101_wdt.c2
-rw-r--r--drivers/watchdog/ar7_wdt.c2
-rw-r--r--drivers/watchdog/at32ap700x_wdt.c2
-rw-r--r--drivers/watchdog/at91rm9200_wdt.c2
-rw-r--r--drivers/watchdog/bcm47xx_wdt.c2
-rw-r--r--drivers/watchdog/bfin_wdt.c56
-rw-r--r--drivers/watchdog/booke_wdt.c2
-rw-r--r--drivers/watchdog/coh901327_wdt.c2
-rw-r--r--drivers/watchdog/cpu5wdt.c2
-rw-r--r--drivers/watchdog/cpwd.c2
-rw-r--r--drivers/watchdog/davinci_wdt.c2
-rw-r--r--drivers/watchdog/ep93xx_wdt.c2
-rw-r--r--drivers/watchdog/eurotechwdt.c2
-rw-r--r--drivers/watchdog/gef_wdt.c16
-rw-r--r--drivers/watchdog/geodewdt.c2
-rw-r--r--drivers/watchdog/hpwdt.c2
-rw-r--r--drivers/watchdog/i6300esb.c101
-rw-r--r--drivers/watchdog/iTCO_wdt.c21
-rw-r--r--drivers/watchdog/ib700wdt.c2
-rw-r--r--drivers/watchdog/indydog.c2
-rw-r--r--drivers/watchdog/it8712f_wdt.c2
-rw-r--r--drivers/watchdog/it87_wdt.c2
-rw-r--r--drivers/watchdog/ixp2000_wdt.c2
-rw-r--r--drivers/watchdog/ixp4xx_wdt.c2
-rw-r--r--drivers/watchdog/ks8695_wdt.c2
-rw-r--r--drivers/watchdog/machzwd.c2
-rw-r--r--drivers/watchdog/max63xx_wdt.c397
-rw-r--r--drivers/watchdog/mixcomwd.c2
-rw-r--r--drivers/watchdog/mpc8xxx_wdt.c2
-rw-r--r--drivers/watchdog/mpcore_wdt.c2
-rw-r--r--drivers/watchdog/mv64x60_wdt.c2
-rw-r--r--drivers/watchdog/pc87413_wdt.c2
-rw-r--r--drivers/watchdog/pcwd.c2
-rw-r--r--drivers/watchdog/pcwd_pci.c2
-rw-r--r--drivers/watchdog/pcwd_usb.c2
-rw-r--r--drivers/watchdog/pika_wdt.c2
-rw-r--r--drivers/watchdog/pnx833x_wdt.c2
-rw-r--r--drivers/watchdog/rc32434_wdt.c2
-rw-r--r--drivers/watchdog/rdc321x_wdt.c2
-rw-r--r--drivers/watchdog/riowd.c2
-rw-r--r--drivers/watchdog/sbc_fitpc2_wdt.c2
-rw-r--r--drivers/watchdog/sch311x_wdt.c2
-rw-r--r--drivers/watchdog/stmp3xxx_wdt.c2
-rw-r--r--drivers/watchdog/ts72xx_wdt.c520
-rw-r--r--drivers/watchdog/txx9wdt.c25
-rw-r--r--drivers/watchdog/w83627hf_wdt.c2
-rw-r--r--drivers/watchdog/w83977f_wdt.c2
-rw-r--r--drivers/watchdog/wdrtas.c2
-rw-r--r--drivers/watchdog/wdt.c2
-rw-r--r--drivers/watchdog/wdt_pci.c2
-rw-r--r--drivers/watchdog/wm831x_wdt.c2
-rw-r--r--drivers/watchdog/wm8350_wdt.c2
-rw-r--r--drivers/xen/Kconfig12
-rw-r--r--drivers/xen/sys-hypervisor.c2
-rw-r--r--fs/Kconfig1
-rw-r--r--fs/Makefile1
-rw-r--r--fs/attr.c2
-rw-r--r--fs/binfmt_aout.c38
-rw-r--r--fs/binfmt_elf.c151
-rw-r--r--fs/binfmt_elf_fdpic.c181
-rw-r--r--fs/binfmt_flat.c2
-rw-r--r--fs/btrfs/disk-io.c4
-rw-r--r--fs/btrfs/extent_io.c4
-rw-r--r--fs/btrfs/extent_map.c2
-rw-r--r--fs/btrfs/free-space-cache.c4
-rw-r--r--fs/btrfs/ordered-data.h2
-rw-r--r--fs/btrfs/ref-cache.h2
-rw-r--r--fs/btrfs/relocation.c4
-rw-r--r--fs/btrfs/super.c5
-rw-r--r--fs/btrfs/sysfs.c4
-rw-r--r--fs/btrfs/transaction.c2
-rw-r--r--fs/compat_binfmt_elf.c2
-rw-r--r--fs/compat_ioctl.c4
-rw-r--r--fs/dlm/lockspace.c2
-rw-r--r--fs/exec.c50
-rw-r--r--fs/ext4/super.c2
-rw-r--r--fs/fcntl.c2
-rw-r--r--fs/file.c2
-rw-r--r--fs/file_table.c2
-rw-r--r--fs/fscache/Kconfig1
-rw-r--r--fs/gfs2/sys.c4
-rw-r--r--fs/lockd/host.c2
-rw-r--r--fs/lockd/mon.c12
-rw-r--r--fs/lockd/svc.c2
-rw-r--r--fs/logfs/Kconfig17
-rw-r--r--fs/logfs/Makefile13
-rw-r--r--fs/logfs/compr.c95
-rw-r--r--fs/logfs/dev_bdev.c327
-rw-r--r--fs/logfs/dev_mtd.c254
-rw-r--r--fs/logfs/dir.c827
-rw-r--r--fs/logfs/file.c263
-rw-r--r--fs/logfs/gc.c730
-rw-r--r--fs/logfs/inode.c417
-rw-r--r--fs/logfs/journal.c883
-rw-r--r--fs/logfs/logfs.h724
-rw-r--r--fs/logfs/logfs_abi.h629
-rw-r--r--fs/logfs/readwrite.c2246
-rw-r--r--fs/logfs/segment.c927
-rw-r--r--fs/logfs/super.c650
-rw-r--r--fs/namei.c2
-rw-r--r--fs/nfs/callback.c2
-rw-r--r--fs/nfsd/nfs4callback.c5
-rw-r--r--fs/nfsd/nfs4recover.c4
-rw-r--r--fs/nfsd/nfs4state.c6
-rw-r--r--fs/nfsd/nfs4xdr.c2
-rw-r--r--fs/nfsd/nfsctl.c24
-rw-r--r--fs/nfsd/vfs.c153
-rw-r--r--fs/ocfs2/cluster/masklog.c2
-rw-r--r--fs/ocfs2/quota_local.c2
-rw-r--r--fs/proc/array.c4
-rw-r--r--fs/proc/generic.c33
-rw-r--r--fs/proc/task_mmu.c13
-rw-r--r--fs/select.c2
-rw-r--r--fs/seq_file.c4
-rw-r--r--fs/sysfs/bin.c50
-rw-r--r--fs/sysfs/dir.c132
-rw-r--r--fs/sysfs/file.c47
-rw-r--r--fs/sysfs/inode.c13
-rw-r--r--fs/sysfs/mount.c4
-rw-r--r--fs/sysfs/symlink.c38
-rw-r--r--fs/sysfs/sysfs.h17
-rw-r--r--fs/xfs/Makefile1
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c221
-rw-r--r--fs/xfs/linux-2.6/xfs_export.c20
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c854
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c10
-rw-r--r--fs/xfs/linux-2.6/xfs_linux.h1
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.c796
-rw-r--r--fs/xfs/linux-2.6/xfs_lrw.h29
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c10
-rw-r--r--fs/xfs/linux-2.6/xfs_trace.c16
-rw-r--r--fs/xfs/linux-2.6/xfs_trace.h22
-rw-r--r--fs/xfs/xfs_bmap.c220
-rw-r--r--fs/xfs/xfs_fs.h3
-rw-r--r--fs/xfs/xfs_iget.c19
-rw-r--r--fs/xfs/xfs_inode.c68
-rw-r--r--fs/xfs/xfs_inode.h3
-rw-r--r--fs/xfs/xfs_inode_item.c18
-rw-r--r--fs/xfs/xfs_itable.c2
-rw-r--r--fs/xfs/xfs_log.c106
-rw-r--r--fs/xfs/xfs_log.h16
-rw-r--r--fs/xfs/xfs_mount.c69
-rw-r--r--fs/xfs/xfs_mount.h2
-rw-r--r--fs/xfs/xfs_trans.c2
-rw-r--r--fs/xfs/xfs_trans.h2
-rw-r--r--fs/xfs/xfs_trans_buf.c216
-rw-r--r--fs/xfs/xfs_vnodeops.c107
-rw-r--r--fs/xfs/xfs_vnodeops.h15
-rw-r--r--include/asm-generic/gpio.h26
-rw-r--r--include/linux/binfmts.h1
-rw-r--r--include/linux/bitops.h4
-rw-r--r--include/linux/btree-128.h109
-rw-r--r--include/linux/btree-type.h147
-rw-r--r--include/linux/btree.h243
-rw-r--r--include/linux/coredump.h41
-rw-r--r--include/linux/cpumask.h8
-rw-r--r--include/linux/device-mapper.h5
-rw-r--r--include/linux/device.h40
-rw-r--r--include/linux/dm-io.h4
-rw-r--r--include/linux/dm-ioctl.h9
-rw-r--r--include/linux/elf.h28
-rw-r--r--include/linux/elfcore.h17
-rw-r--r--include/linux/exportfs.h5
-rw-r--r--include/linux/firmware-map.h6
-rw-r--r--include/linux/fs.h23
-rw-r--r--include/linux/gfp.h12
-rw-r--r--include/linux/htcpld.h24
-rw-r--r--include/linux/i2c/pca953x.h11
-rw-r--r--include/linux/i2c/twl.h28
-rw-r--r--include/linux/kobject.h14
-rw-r--r--include/linux/list.h6
-rw-r--r--include/linux/mfd/88pm8607.h217
-rw-r--r--include/linux/mfd/88pm860x.h375
-rw-r--r--include/linux/mfd/ab3100.h3
-rw-r--r--include/linux/mfd/max8925.h253
-rw-r--r--include/linux/mfd/mc13783.h26
-rw-r--r--include/linux/mfd/tmio.h3
-rw-r--r--include/linux/mfd/ucb1x00.h1
-rw-r--r--include/linux/mfd/wm831x/core.h6
-rw-r--r--include/linux/mfd/wm831x/gpio.h4
-rw-r--r--include/linux/mfd/wm8350/core.h49
-rw-r--r--include/linux/mfd/wm8350/gpio.h1
-rw-r--r--include/linux/mfd/wm8350/rtc.h1
-rw-r--r--include/linux/mfd/wm8994/core.h54
-rw-r--r--include/linux/mfd/wm8994/gpio.h72
-rw-r--r--include/linux/mfd/wm8994/pdata.h97
-rw-r--r--include/linux/mfd/wm8994/registers.h4292
-rw-r--r--include/linux/mm.h104
-rw-r--r--include/linux/mm_types.h43
-rw-r--r--include/linux/mmc/card.h7
-rw-r--r--include/linux/mmc/host.h5
-rw-r--r--include/linux/mmc/pm.h30
-rw-r--r--include/linux/mmc/sdio.h2
-rw-r--r--include/linux/mmc/sdio_func.h5
-rw-r--r--include/linux/mmzone.h7
-rw-r--r--include/linux/nodemask.h11
-rw-r--r--include/linux/pci.h2
-rw-r--r--include/linux/pci_regs.h1
-rw-r--r--include/linux/platform_device.h9
-rw-r--r--include/linux/pm.h51
-rw-r--r--include/linux/pm_runtime.h6
-rw-r--r--include/linux/rmap.h38
-rw-r--r--include/linux/sched.h58
-rw-r--r--include/linux/serial_sci.h6
-rw-r--r--include/linux/smp.h2
-rw-r--r--include/linux/spi/max7301.h18
-rw-r--r--include/linux/sysdev.h21
-rw-r--r--include/linux/sysfs.h61
-rw-r--r--include/linux/usb.h6
-rw-r--r--include/linux/usb/audio.h2
-rw-r--r--include/sound/asound.h2
-rw-r--r--init/initramfs.c12
-rw-r--r--init/main.c7
-rw-r--r--kernel/Makefile3
-rw-r--r--kernel/cpu.c2
-rw-r--r--kernel/elfcore.c28
-rw-r--r--kernel/exit.c5
-rw-r--r--kernel/fork.c19
-rw-r--r--kernel/module.c3
-rw-r--r--kernel/panic.c46
-rw-r--r--kernel/params.c6
-rw-r--r--kernel/perf_event.c15
-rw-r--r--kernel/pid.c2
-rw-r--r--kernel/posix-cpu-timers.c36
-rw-r--r--kernel/power/hibernate.c9
-rw-r--r--kernel/power/suspend.c3
-rw-r--r--kernel/printk.c3
-rw-r--r--kernel/relay.c5
-rw-r--r--kernel/sched.c8
-rw-r--r--kernel/sched_cpupri.c2
-rw-r--r--kernel/sched_rt.c5
-rw-r--r--kernel/signal.c2
-rw-r--r--kernel/sys.c3
-rw-r--r--kernel/tsacct.c1
-rw-r--r--lib/Kconfig3
-rw-r--r--lib/Kconfig.debug5
-rw-r--r--lib/Makefile1
-rw-r--r--lib/bitmap.c19
-rw-r--r--lib/btree.c797
-rw-r--r--lib/crc32.c30
-rw-r--r--lib/kobject.c6
-rw-r--r--lib/kobject_uevent.c2
-rw-r--r--lib/list_sort.c263
-rw-r--r--lib/show_mem.c14
-rw-r--r--lib/string.c40
-rw-r--r--lib/vsprintf.c71
-rw-r--r--mm/fadvise.c10
-rw-r--r--mm/filemap.c2
-rw-r--r--mm/filemap_xip.c2
-rw-r--r--mm/fremap.c2
-rw-r--r--mm/ksm.c12
-rw-r--r--mm/memcontrol.c2
-rw-r--r--mm/memory-failure.c5
-rw-r--r--mm/memory.c161
-rw-r--r--mm/memory_hotplug.c4
-rw-r--r--mm/mempolicy.c112
-rw-r--r--mm/migrate.c4
-rw-r--r--mm/mlock.c12
-rw-r--r--mm/mmap.c151
-rw-r--r--mm/mremap.c9
-rw-r--r--mm/nommu.c6
-rw-r--r--mm/oom_kill.c4
-rw-r--r--mm/page_alloc.c53
-rw-r--r--mm/readahead.c6
-rw-r--r--mm/rmap.c185
-rw-r--r--mm/slub.c4
-rw-r--r--mm/swap.c2
-rw-r--r--mm/swapfile.c40
-rw-r--r--mm/vmscan.c177
-rw-r--r--mm/vmstat.c2
-rw-r--r--net/bluetooth/l2cap.c4
-rw-r--r--net/bluetooth/rfcomm/core.c4
-rw-r--r--net/bluetooth/rfcomm/sock.c4
-rw-r--r--net/bluetooth/sco.c4
-rw-r--r--net/bridge/br_private.h2
-rw-r--r--net/bridge/br_sysfs_if.c2
-rw-r--r--net/sunrpc/svc.c2
-rw-r--r--net/sunrpc/svc_xprt.c27
-rw-r--r--net/sunrpc/svcauth_unix.c49
-rw-r--r--net/sunrpc/svcsock.c3
-rw-r--r--samples/kobject/kobject-example.c4
-rw-r--r--samples/kobject/kset-example.c6
-rwxr-xr-xscripts/checkpatch.pl78
-rwxr-xr-xscripts/get_maintainer.pl185
-rw-r--r--sound/core/timer.c2
-rw-r--r--sound/isa/opti9xx/miro.c2
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c120
-rw-r--r--sound/isa/sb/jazz16.c1
-rw-r--r--sound/oss/coproc.h2
-rw-r--r--sound/oss/v_midi.h5
-rw-r--r--sound/pci/hda/Kconfig2
-rw-r--r--sound/pci/hda/Makefile4
-rw-r--r--sound/pci/hda/hda_codec.c69
-rw-r--r--sound/pci/hda/hda_eld.c6
-rw-r--r--sound/pci/hda/hda_intel.c9
-rw-r--r--sound/pci/hda/patch_hdmi.c849
-rw-r--r--sound/pci/hda/patch_intelhdmi.c821
-rw-r--r--sound/pci/hda/patch_nvhdmi.c275
-rw-r--r--sound/pci/hda/patch_realtek.c10
-rw-r--r--sound/pci/oxygen/xonar_wm87x6.c2
-rw-r--r--sound/pci/riptide/riptide.c6
-rw-r--r--sound/soc/codecs/ak4104.c6
-rw-r--r--sound/soc/codecs/uda1380.c2
-rw-r--r--sound/soc/codecs/wm8350.c8
-rw-r--r--sound/soc/sh/siu.h2
-rw-r--r--sound/soc/sh/siu_pcm.c2
-rw-r--r--sound/soc/soc-core.c14
-rw-r--r--sound/usb/Kconfig6
-rw-r--r--sound/usb/caiaq/midi.h2
-rw-r--r--sound/usb/ua101.c100
-rw-r--r--sound/usb/usbaudio.c57
-rw-r--r--sound/usb/usbaudio.h3
-rw-r--r--sound/usb/usbquirks.h30
1212 files changed, 73085 insertions, 34400 deletions
diff --git a/.gitignore b/.gitignore
index de6344e1570..efab0ebec85 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,6 +36,7 @@ modules.builtin
#
tags
TAGS
+linux
vmlinux
vmlinuz
System.map
diff --git a/Documentation/ABI/stable/sysfs-devices-node b/Documentation/ABI/stable/sysfs-devices-node
new file mode 100644
index 00000000000..49b82cad700
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-devices-node
@@ -0,0 +1,7 @@
+What: /sys/devices/system/node/nodeX
+Date: October 2002
+Contact: Linux Memory Management list <linux-mm@kvack.org>
+Description:
+ When CONFIG_NUMA is enabled, this is a directory containing
+ information on node X such as what CPUs are local to the
+ node.
diff --git a/Documentation/HOWTO b/Documentation/HOWTO
index 8495fc97039..f5395af88a4 100644
--- a/Documentation/HOWTO
+++ b/Documentation/HOWTO
@@ -221,8 +221,8 @@ branches. These different branches are:
- main 2.6.x kernel tree
- 2.6.x.y -stable kernel tree
- 2.6.x -git kernel patches
- - 2.6.x -mm kernel patches
- subsystem specific kernel trees and patches
+ - the 2.6.x -next kernel tree for integration tests
2.6.x kernel tree
-----------------
@@ -232,7 +232,7 @@ process is as follows:
- As soon as a new kernel is released a two weeks window is open,
during this period of time maintainers can submit big diffs to
Linus, usually the patches that have already been included in the
- -mm kernel for a few weeks. The preferred way to submit big changes
+ -next kernel for a few weeks. The preferred way to submit big changes
is using git (the kernel's source management tool, more information
can be found at http://git.or.cz/) but plain patches are also just
fine.
@@ -293,84 +293,43 @@ daily and represent the current state of Linus' tree. They are more
experimental than -rc kernels since they are generated automatically
without even a cursory glance to see if they are sane.
-2.6.x -mm kernel patches
-------------------------
-These are experimental kernel patches released by Andrew Morton. Andrew
-takes all of the different subsystem kernel trees and patches and mushes
-them together, along with a lot of patches that have been plucked from
-the linux-kernel mailing list. This tree serves as a proving ground for
-new features and patches. Once a patch has proved its worth in -mm for
-a while Andrew or the subsystem maintainer pushes it on to Linus for
-inclusion in mainline.
-
-It is heavily encouraged that all new patches get tested in the -mm tree
-before they are sent to Linus for inclusion in the main kernel tree. Code
-which does not make an appearance in -mm before the opening of the merge
-window will prove hard to merge into the mainline.
-
-These kernels are not appropriate for use on systems that are supposed
-to be stable and they are more risky to run than any of the other
-branches.
-
-If you wish to help out with the kernel development process, please test
-and use these kernel releases and provide feedback to the linux-kernel
-mailing list if you have any problems, and if everything works properly.
-
-In addition to all the other experimental patches, these kernels usually
-also contain any changes in the mainline -git kernels available at the
-time of release.
-
-The -mm kernels are not released on a fixed schedule, but usually a few
--mm kernels are released in between each -rc kernel (1 to 3 is common).
-
Subsystem Specific kernel trees and patches
-------------------------------------------
-A number of the different kernel subsystem developers expose their
-development trees so that others can see what is happening in the
-different areas of the kernel. These trees are pulled into the -mm
-kernel releases as described above.
-
-Here is a list of some of the different kernel trees available:
- git trees:
- - Kbuild development tree, Sam Ravnborg <sam@ravnborg.org>
- git.kernel.org:/pub/scm/linux/kernel/git/sam/kbuild.git
-
- - ACPI development tree, Len Brown <len.brown@intel.com>
- git.kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
-
- - Block development tree, Jens Axboe <jens.axboe@oracle.com>
- git.kernel.org:/pub/scm/linux/kernel/git/axboe/linux-2.6-block.git
-
- - DRM development tree, Dave Airlie <airlied@linux.ie>
- git.kernel.org:/pub/scm/linux/kernel/git/airlied/drm-2.6.git
-
- - ia64 development tree, Tony Luck <tony.luck@intel.com>
- git.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
-
- - infiniband, Roland Dreier <rolandd@cisco.com>
- git.kernel.org:/pub/scm/linux/kernel/git/roland/infiniband.git
-
- - libata, Jeff Garzik <jgarzik@pobox.com>
- git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git
-
- - network drivers, Jeff Garzik <jgarzik@pobox.com>
- git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git
-
- - pcmcia, Dominik Brodowski <linux@dominikbrodowski.net>
- git.kernel.org:/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git
-
- - SCSI, James Bottomley <James.Bottomley@hansenpartnership.com>
- git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
-
- - x86, Ingo Molnar <mingo@elte.hu>
- git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git
-
- quilt trees:
- - USB, Driver Core, and I2C, Greg Kroah-Hartman <gregkh@suse.de>
- kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
+The maintainers of the various kernel subsystems --- and also many
+kernel subsystem developers --- expose their current state of
+development in source repositories. That way, others can see what is
+happening in the different areas of the kernel. In areas where
+development is rapid, a developer may be asked to base his submissions
+onto such a subsystem kernel tree so that conflicts between the
+submission and other already ongoing work are avoided.
+
+Most of these repositories are git trees, but there are also other SCMs
+in use, or patch queues being published as quilt series. Addresses of
+these subsystem repositories are listed in the MAINTAINERS file. Many
+of them can be browsed at http://git.kernel.org/.
+
+Before a proposed patch is committed to such a subsystem tree, it is
+subject to review which primarily happens on mailing lists (see the
+respective section below). For several kernel subsystems, this review
+process is tracked with the tool patchwork. Patchwork offers a web
+interface which shows patch postings, any comments on a patch or
+revisions to it, and maintainers can mark patches as under review,
+accepted, or rejected. Most of these patchwork sites are listed at
+http://patchwork.kernel.org/ or http://patchwork.ozlabs.org/.
+
+2.6.x -next kernel tree for integration tests
+---------------------------------------------
+Before updates from subsystem trees are merged into the mainline 2.6.x
+tree, they need to be integration-tested. For this purpose, a special
+testing repository exists into which virtually all subsystem trees are
+pulled on an almost daily basis:
+ http://git.kernel.org/?p=linux/kernel/git/sfr/linux-next.git
+ http://linux.f-seidel.de/linux-next/pmwiki/
+
+This way, the -next kernel gives a summary outlook onto what will be
+expected to go into the mainline kernel at the next merge period.
+Adventurous testers are very welcome to runtime-test the -next kernel.
- Other kernel trees can be found listed at http://git.kernel.org/ and in
- the MAINTAINERS file.
Bug Reporting
-------------
diff --git a/Documentation/cpu-freq/pcc-cpufreq.txt b/Documentation/cpu-freq/pcc-cpufreq.txt
new file mode 100644
index 00000000000..9e3c3b33514
--- /dev/null
+++ b/Documentation/cpu-freq/pcc-cpufreq.txt
@@ -0,0 +1,207 @@
+/*
+ * pcc-cpufreq.txt - PCC interface documentation
+ *
+ * Copyright (C) 2009 Red Hat, Matthew Garrett <mjg@redhat.com>
+ * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
+ * Nagananda Chumbalkar <nagananda.chumbalkar@hp.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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or NON
+ * INFRINGEMENT. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+
+ Processor Clocking Control Driver
+ ---------------------------------
+
+Contents:
+---------
+1. Introduction
+1.1 PCC interface
+1.1.1 Get Average Frequency
+1.1.2 Set Desired Frequency
+1.2 Platforms affected
+2. Driver and /sys details
+2.1 scaling_available_frequencies
+2.2 cpuinfo_transition_latency
+2.3 cpuinfo_cur_freq
+2.4 related_cpus
+3. Caveats
+
+1. Introduction:
+----------------
+Processor Clocking Control (PCC) is an interface between the platform
+firmware and OSPM. It is a mechanism for coordinating processor
+performance (ie: frequency) between the platform firmware and the OS.
+
+The PCC driver (pcc-cpufreq) allows OSPM to take advantage of the PCC
+interface.
+
+OS utilizes the PCC interface to inform platform firmware what frequency the
+OS wants for a logical processor. The platform firmware attempts to achieve
+the requested frequency. If the request for the target frequency could not be
+satisfied by platform firmware, then it usually means that power budget
+conditions are in place, and "power capping" is taking place.
+
+1.1 PCC interface:
+------------------
+The complete PCC specification is available here:
+http://www.acpica.org/download/Processor-Clocking-Control-v1p0.pdf
+
+PCC relies on a shared memory region that provides a channel for communication
+between the OS and platform firmware. PCC also implements a "doorbell" that
+is used by the OS to inform the platform firmware that a command has been
+sent.
+
+The ACPI PCCH() method is used to discover the location of the PCC shared
+memory region. The shared memory region header contains the "command" and
+"status" interface. PCCH() also contains details on how to access the platform
+doorbell.
+
+The following commands are supported by the PCC interface:
+* Get Average Frequency
+* Set Desired Frequency
+
+The ACPI PCCP() method is implemented for each logical processor and is
+used to discover the offsets for the input and output buffers in the shared
+memory region.
+
+When PCC mode is enabled, the platform will not expose processor performance
+or throttle states (_PSS, _TSS and related ACPI objects) to OSPM. Therefore,
+the native P-state driver (such as acpi-cpufreq for Intel, powernow-k8 for
+AMD) will not load.
+
+However, OSPM remains in control of policy. The governor (eg: "ondemand")
+computes the required performance for each processor based on server workload.
+The PCC driver fills in the command interface, and the input buffer and
+communicates the request to the platform firmware. The platform firmware is
+responsible for delivering the requested performance.
+
+Each PCC command is "global" in scope and can affect all the logical CPUs in
+the system. Therefore, PCC is capable of performing "group" updates. With PCC
+the OS is capable of getting/setting the frequency of all the logical CPUs in
+the system with a single call to the BIOS.
+
+1.1.1 Get Average Frequency:
+----------------------------
+This command is used by the OSPM to query the running frequency of the
+processor since the last time this command was completed. The output buffer
+indicates the average unhalted frequency of the logical processor expressed as
+a percentage of the nominal (ie: maximum) CPU frequency. The output buffer
+also signifies if the CPU frequency is limited by a power budget condition.
+
+1.1.2 Set Desired Frequency:
+----------------------------
+This command is used by the OSPM to communicate to the platform firmware the
+desired frequency for a logical processor. The output buffer is currently
+ignored by OSPM. The next invocation of "Get Average Frequency" will inform
+OSPM if the desired frequency was achieved or not.
+
+1.2 Platforms affected:
+-----------------------
+The PCC driver will load on any system where the platform firmware:
+* supports the PCC interface, and the associated PCCH() and PCCP() methods
+* assumes responsibility for managing the hardware clocking controls in order
+to deliver the requested processor performance
+
+Currently, certain HP ProLiant platforms implement the PCC interface. On those
+platforms PCC is the "default" choice.
+
+However, it is possible to disable this interface via a BIOS setting. In
+such an instance, as is also the case on platforms where the PCC interface
+is not implemented, the PCC driver will fail to load silently.
+
+2. Driver and /sys details:
+---------------------------
+When the driver loads, it merely prints the lowest and the highest CPU
+frequencies supported by the platform firmware.
+
+The PCC driver loads with a message such as:
+pcc-cpufreq: (v1.00.00) driver loaded with frequency limits: 1600 MHz, 2933
+MHz
+
+This means that the OPSM can request the CPU to run at any frequency in
+between the limits (1600 MHz, and 2933 MHz) specified in the message.
+
+Internally, there is no need for the driver to convert the "target" frequency
+to a corresponding P-state.
+
+The VERSION number for the driver will be of the format v.xy.ab.
+eg: 1.00.02
+ ----- --
+ | |
+ | -- this will increase with bug fixes/enhancements to the driver
+ |-- this is the version of the PCC specification the driver adheres to
+
+
+The following is a brief discussion on some of the fields exported via the
+/sys filesystem and how their values are affected by the PCC driver:
+
+2.1 scaling_available_frequencies:
+----------------------------------
+scaling_available_frequencies is not created in /sys. No intermediate
+frequencies need to be listed because the BIOS will try to achieve any
+frequency, within limits, requested by the governor. A frequency does not have
+to be strictly associated with a P-state.
+
+2.2 cpuinfo_transition_latency:
+-------------------------------
+The cpuinfo_transition_latency field is 0. The PCC specification does
+not include a field to expose this value currently.
+
+2.3 cpuinfo_cur_freq:
+---------------------
+A) Often cpuinfo_cur_freq will show a value different than what is declared
+in the scaling_available_frequencies or scaling_cur_freq, or scaling_max_freq.
+This is due to "turbo boost" available on recent Intel processors. If certain
+conditions are met the BIOS can achieve a slightly higher speed than requested
+by OSPM. An example:
+
+scaling_cur_freq : 2933000
+cpuinfo_cur_freq : 3196000
+
+B) There is a round-off error associated with the cpuinfo_cur_freq value.
+Since the driver obtains the current frequency as a "percentage" (%) of the
+nominal frequency from the BIOS, sometimes, the values displayed by
+scaling_cur_freq and cpuinfo_cur_freq may not match. An example:
+
+scaling_cur_freq : 1600000
+cpuinfo_cur_freq : 1583000
+
+In this example, the nominal frequency is 2933 MHz. The driver obtains the
+current frequency, cpuinfo_cur_freq, as 54% of the nominal frequency:
+
+ 54% of 2933 MHz = 1583 MHz
+
+Nominal frequency is the maximum frequency of the processor, and it usually
+corresponds to the frequency of the P0 P-state.
+
+2.4 related_cpus:
+-----------------
+The related_cpus field is identical to affected_cpus.
+
+affected_cpus : 4
+related_cpus : 4
+
+Currently, the PCC driver does not evaluate _PSD. The platforms that support
+PCC do not implement SW_ALL. So OSPM doesn't need to perform any coordination
+to ensure that the same frequency is requested of all dependent CPUs.
+
+3. Caveats:
+-----------
+The "cpufreq_stats" module in its present form cannot be loaded and
+expected to work with the PCC driver. Since the "cpufreq_stats" module
+provides information wrt each P-state, it is not applicable to the PCC driver.
diff --git a/Documentation/device-mapper/snapshot.txt b/Documentation/device-mapper/snapshot.txt
index e3a77b21513..0d5bc46dc16 100644
--- a/Documentation/device-mapper/snapshot.txt
+++ b/Documentation/device-mapper/snapshot.txt
@@ -122,3 +122,47 @@ volumeGroup-base: 0 2097152 snapshot-merge 254:11 254:12 P 16
brw------- 1 root root 254, 11 29 ago 18:15 /dev/mapper/volumeGroup-base-real
brw------- 1 root root 254, 12 29 ago 18:16 /dev/mapper/volumeGroup-base-cow
brw------- 1 root root 254, 10 29 ago 18:16 /dev/mapper/volumeGroup-base
+
+
+How to determine when a merging is complete
+===========================================
+The snapshot-merge and snapshot status lines end with:
+ <sectors_allocated>/<total_sectors> <metadata_sectors>
+
+Both <sectors_allocated> and <total_sectors> include both data and metadata.
+During merging, the number of sectors allocated gets smaller and
+smaller. Merging has finished when the number of sectors holding data
+is zero, in other words <sectors_allocated> == <metadata_sectors>.
+
+Here is a practical example (using a hybrid of lvm and dmsetup commands):
+
+# lvs
+ LV VG Attr LSize Origin Snap% Move Log Copy% Convert
+ base volumeGroup owi-a- 4.00g
+ snap volumeGroup swi-a- 1.00g base 18.97
+
+# dmsetup status volumeGroup-snap
+0 8388608 snapshot 397896/2097152 1560
+ ^^^^ metadata sectors
+
+# lvconvert --merge -b volumeGroup/snap
+ Merging of volume snap started.
+
+# lvs volumeGroup/snap
+ LV VG Attr LSize Origin Snap% Move Log Copy% Convert
+ base volumeGroup Owi-a- 4.00g 17.23
+
+# dmsetup status volumeGroup-base
+0 8388608 snapshot-merge 281688/2097152 1104
+
+# dmsetup status volumeGroup-base
+0 8388608 snapshot-merge 180480/2097152 712
+
+# dmsetup status volumeGroup-base
+0 8388608 snapshot-merge 16/2097152 16
+
+Merging has finished.
+
+# lvs
+ LV VG Attr LSize Origin Snap% Move Log Copy% Convert
+ base volumeGroup owi-a- 4.00g
diff --git a/Documentation/fault-injection/provoke-crashes.txt b/Documentation/fault-injection/provoke-crashes.txt
new file mode 100644
index 00000000000..7a9d3d81525
--- /dev/null
+++ b/Documentation/fault-injection/provoke-crashes.txt
@@ -0,0 +1,38 @@
+The lkdtm module provides an interface to crash or injure the kernel at
+predefined crashpoints to evaluate the reliability of crash dumps obtained
+using different dumping solutions. The module uses KPROBEs to instrument
+crashing points, but can also crash the kernel directly without KRPOBE
+support.
+
+
+You can provide the way either through module arguments when inserting
+the module, or through a debugfs interface.
+
+Usage: insmod lkdtm.ko [recur_count={>0}] cpoint_name=<> cpoint_type=<>
+ [cpoint_count={>0}]
+
+ recur_count : Recursion level for the stack overflow test. Default is 10.
+
+ cpoint_name : Crash point where the kernel is to be crashed. It can be
+ one of INT_HARDWARE_ENTRY, INT_HW_IRQ_EN, INT_TASKLET_ENTRY,
+ FS_DEVRW, MEM_SWAPOUT, TIMERADD, SCSI_DISPATCH_CMD,
+ IDE_CORE_CP, DIRECT
+
+ cpoint_type : Indicates the action to be taken on hitting the crash point.
+ It can be one of PANIC, BUG, EXCEPTION, LOOP, OVERFLOW,
+ CORRUPT_STACK, UNALIGNED_LOAD_STORE_WRITE, OVERWRITE_ALLOCATION,
+ WRITE_AFTER_FREE,
+
+ cpoint_count : Indicates the number of times the crash point is to be hit
+ to trigger an action. The default is 10.
+
+You can also induce failures by mounting debugfs and writing the type to
+<mountpoint>/provoke-crash/<crashpoint>. E.g.,
+
+ mount -t debugfs debugfs /mnt
+ echo EXCEPTION > /mnt/provoke-crash/INT_HARDWARE_ENTRY
+
+
+A special file is `DIRECT' which will induce the crash directly without
+KPROBE instrumentation. This mode is the only one available when the module
+is built on a kernel without KPROBEs support.
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 31575e220f3..a5cc0db63d7 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -449,12 +449,6 @@ Who: Alok N Kataria <akataria@vmware.com>
----------------------------
-What: adt7473 hardware monitoring driver
-When: February 2010
-Why: Obsoleted by the adt7475 driver.
-Who: Jean Delvare <khali@linux-fr.org>
-
----------------------------
What: Support for lcd_switch and display_get in asus-laptop driver
When: March 2010
Why: These two features use non-standard interfaces. There are the
diff --git a/Documentation/filesystems/00-INDEX b/Documentation/filesystems/00-INDEX
index 875d49696b6..5139b8c9d5a 100644
--- a/Documentation/filesystems/00-INDEX
+++ b/Documentation/filesystems/00-INDEX
@@ -62,6 +62,8 @@ jfs.txt
- info and mount options for the JFS filesystem.
locks.txt
- info on file locking implementations, flock() vs. fcntl(), etc.
+logfs.txt
+ - info on the LogFS flash filesystem.
mandatory-locking.txt
- info on the Linux implementation of Sys V mandatory file locking.
ncpfs.txt
diff --git a/Documentation/filesystems/logfs.txt b/Documentation/filesystems/logfs.txt
new file mode 100644
index 00000000000..e64c94ba401
--- /dev/null
+++ b/Documentation/filesystems/logfs.txt
@@ -0,0 +1,241 @@
+
+The LogFS Flash Filesystem
+==========================
+
+Specification
+=============
+
+Superblocks
+-----------
+
+Two superblocks exist at the beginning and end of the filesystem.
+Each superblock is 256 Bytes large, with another 3840 Bytes reserved
+for future purposes, making a total of 4096 Bytes.
+
+Superblock locations may differ for MTD and block devices. On MTD the
+first non-bad block contains a superblock in the first 4096 Bytes and
+the last non-bad block contains a superblock in the last 4096 Bytes.
+On block devices, the first 4096 Bytes of the device contain the first
+superblock and the last aligned 4096 Byte-block contains the second
+superblock.
+
+For the most part, the superblocks can be considered read-only. They
+are written only to correct errors detected within the superblocks,
+move the journal and change the filesystem parameters through tunefs.
+As a result, the superblock does not contain any fields that require
+constant updates, like the amount of free space, etc.
+
+Segments
+--------
+
+The space in the device is split up into equal-sized segments.
+Segments are the primary write unit of LogFS. Within each segments,
+writes happen from front (low addresses) to back (high addresses. If
+only a partial segment has been written, the segment number, the
+current position within and optionally a write buffer are stored in
+the journal.
+
+Segments are erased as a whole. Therefore Garbage Collection may be
+required to completely free a segment before doing so.
+
+Journal
+--------
+
+The journal contains all global information about the filesystem that
+is subject to frequent change. At mount time, it has to be scanned
+for the most recent commit entry, which contains a list of pointers to
+all currently valid entries.
+
+Object Store
+------------
+
+All space except for the superblocks and journal is part of the object
+store. Each segment contains a segment header and a number of
+objects, each consisting of the object header and the payload.
+Objects are either inodes, directory entries (dentries), file data
+blocks or indirect blocks.
+
+Levels
+------
+
+Garbage collection (GC) may fail if all data is written
+indiscriminately. One requirement of GC is that data is seperated
+roughly according to the distance between the tree root and the data.
+Effectively that means all file data is on level 0, indirect blocks
+are on levels 1, 2, 3 4 or 5 for 1x, 2x, 3x, 4x or 5x indirect blocks,
+respectively. Inode file data is on level 6 for the inodes and 7-11
+for indirect blocks.
+
+Each segment contains objects of a single level only. As a result,
+each level requires its own seperate segment to be open for writing.
+
+Inode File
+----------
+
+All inodes are stored in a special file, the inode file. Single
+exception is the inode file's inode (master inode) which for obvious
+reasons is stored in the journal instead. Instead of data blocks, the
+leaf nodes of the inode files are inodes.
+
+Aliases
+-------
+
+Writes in LogFS are done by means of a wandering tree. A naïve
+implementation would require that for each write or a block, all
+parent blocks are written as well, since the block pointers have
+changed. Such an implementation would not be very efficient.
+
+In LogFS, the block pointer changes are cached in the journal by means
+of alias entries. Each alias consists of its logical address - inode
+number, block index, level and child number (index into block) - and
+the changed data. Any 8-byte word can be changes in this manner.
+
+Currently aliases are used for block pointers, file size, file used
+bytes and the height of an inodes indirect tree.
+
+Segment Aliases
+---------------
+
+Related to regular aliases, these are used to handle bad blocks.
+Initially, bad blocks are handled by moving the affected segment
+content to a spare segment and noting this move in the journal with a
+segment alias, a simple (to, from) tupel. GC will later empty this
+segment and the alias can be removed again. This is used on MTD only.
+
+Vim
+---
+
+By cleverly predicting the life time of data, it is possible to
+seperate long-living data from short-living data and thereby reduce
+the GC overhead later. Each type of distinc life expectency (vim) can
+have a seperate segment open for writing. Each (level, vim) tupel can
+be open just once. If an open segment with unknown vim is encountered
+at mount time, it is closed and ignored henceforth.
+
+Indirect Tree
+-------------
+
+Inodes in LogFS are similar to FFS-style filesystems with direct and
+indirect block pointers. One difference is that LogFS uses a single
+indirect pointer that can be either a 1x, 2x, etc. indirect pointer.
+A height field in the inode defines the height of the indirect tree
+and thereby the indirection of the pointer.
+
+Another difference is the addressing of indirect blocks. In LogFS,
+the first 16 pointers in the first indirect block are left empty,
+corresponding to the 16 direct pointers in the inode. In ext2 (maybe
+others as well) the first pointer in the first indirect block
+corresponds to logical block 12, skipping the 12 direct pointers.
+So where ext2 is using arithmetic to better utilize space, LogFS keeps
+arithmetic simple and uses compression to save space.
+
+Compression
+-----------
+
+Both file data and metadata can be compressed. Compression for file
+data can be enabled with chattr +c and disabled with chattr -c. Doing
+so has no effect on existing data, but new data will be stored
+accordingly. New inodes will inherit the compression flag of the
+parent directory.
+
+Metadata is always compressed. However, the space accounting ignores
+this and charges for the uncompressed size. Failing to do so could
+result in GC failures when, after moving some data, indirect blocks
+compress worse than previously. Even on a 100% full medium, GC may
+not consume any extra space, so the compression gains are lost space
+to the user.
+
+However, they are not lost space to the filesystem internals. By
+cheating the user for those bytes, the filesystem gained some slack
+space and GC will run less often and faster.
+
+Garbage Collection and Wear Leveling
+------------------------------------
+
+Garbage collection is invoked whenever the number of free segments
+falls below a threshold. The best (known) candidate is picked based
+on the least amount of valid data contained in the segment. All
+remaining valid data is copied elsewhere, thereby invalidating it.
+
+The GC code also checks for aliases and writes then back if their
+number gets too large.
+
+Wear leveling is done by occasionally picking a suboptimal segment for
+garbage collection. If a stale segments erase count is significantly
+lower than the active segments' erase counts, it will be picked. Wear
+leveling is rate limited, so it will never monopolize the device for
+more than one segment worth at a time.
+
+Values for "occasionally", "significantly lower" are compile time
+constants.
+
+Hashed directories
+------------------
+
+To satisfy efficient lookup(), directory entries are hashed and
+located based on the hash. In order to both support large directories
+and not be overly inefficient for small directories, several hash
+tables of increasing size are used. For each table, the hash value
+modulo the table size gives the table index.
+
+Tables sizes are chosen to limit the number of indirect blocks with a
+fully populated table to 0, 1, 2 or 3 respectively. So the first
+table contains 16 entries, the second 512-16, etc.
+
+The last table is special in several ways. First its size depends on
+the effective 32bit limit on telldir/seekdir cookies. Since logfs
+uses the upper half of the address space for indirect blocks, the size
+is limited to 2^31. Secondly the table contains hash buckets with 16
+entries each.
+
+Using single-entry buckets would result in birthday "attacks". At
+just 2^16 used entries, hash collisions would be likely (P >= 0.5).
+My math skills are insufficient to do the combinatorics for the 17x
+collisions necessary to overflow a bucket, but testing showed that in
+10,000 runs the lowest directory fill before a bucket overflow was
+188,057,130 entries with an average of 315,149,915 entries. So for
+directory sizes of up to a million, bucket overflows should be
+virtually impossible under normal circumstances.
+
+With carefully chosen filenames, it is obviously possible to cause an
+overflow with just 21 entries (4 higher tables + 16 entries + 1). So
+there may be a security concern if a malicious user has write access
+to a directory.
+
+Open For Discussion
+===================
+
+Device Address Space
+--------------------
+
+A device address space is used for caching. Both block devices and
+MTD provide functions to either read a single page or write a segment.
+Partial segments may be written for data integrity, but where possible
+complete segments are written for performance on simple block device
+flash media.
+
+Meta Inodes
+-----------
+
+Inodes are stored in the inode file, which is just a regular file for
+most purposes. At umount time, however, the inode file needs to
+remain open until all dirty inodes are written. So
+generic_shutdown_super() may not close this inode, but shouldn't
+complain about remaining inodes due to the inode file either. Same
+goes for mapping inode of the device address space.
+
+Currently logfs uses a hack that essentially copies part of fs/inode.c
+code over. A general solution would be preferred.
+
+Indirect block mapping
+----------------------
+
+With compression, the block device (or mapping inode) cannot be used
+to cache indirect blocks. Some other place is required. Currently
+logfs uses the top half of each inode's address space. The low 8TB
+(on 32bit) are filled with file data, the high 8TB are used for
+indirect blocks.
+
+One problem is that 16TB files created on 64bit systems actually have
+data in the top 8TB. But files >16TB would cause problems anyway, so
+only the limit has changed.
diff --git a/Documentation/filesystems/nfs/nfs41-server.txt b/Documentation/filesystems/nfs/nfs41-server.txt
index 1bd0d0c0517..6a53a84afc7 100644
--- a/Documentation/filesystems/nfs/nfs41-server.txt
+++ b/Documentation/filesystems/nfs/nfs41-server.txt
@@ -17,8 +17,7 @@ kernels must turn 4.1 on or off *before* turning support for version 4
on or off; rpc.nfsd does this correctly.)
The NFSv4 minorversion 1 (NFSv4.1) implementation in nfsd is based
-on the latest NFSv4.1 Internet Draft:
-http://tools.ietf.org/html/draft-ietf-nfsv4-minorversion1-29
+on RFC 5661.
From the many new features in NFSv4.1 the current implementation
focuses on the mandatory-to-implement NFSv4.1 Sessions, providing
@@ -44,7 +43,7 @@ interoperability problems with future clients. Known issues:
trunking, but this is a mandatory feature, and its use is
recommended to clients in a number of places. (E.g. to ensure
timely renewal in case an existing connection's retry timeouts
- have gotten too long; see section 8.3 of the draft.)
+ have gotten too long; see section 8.3 of the RFC.)
Therefore, lack of this feature may cause future clients to
fail.
- Incomplete backchannel support: incomplete backchannel gss
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index 0d07513a67a..96a44dd95e0 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -164,6 +164,7 @@ read the file /proc/PID/status:
VmExe: 68 kB
VmLib: 1412 kB
VmPTE: 20 kb
+ VmSwap: 0 kB
Threads: 1
SigQ: 0/28578
SigPnd: 0000000000000000
@@ -188,6 +189,12 @@ memory usage. Its seven fields are explained in Table 1-3. The stat file
contains details information about the process itself. Its fields are
explained in Table 1-4.
+(for SMP CONFIG users)
+For making accounting scalable, RSS related information are handled in
+asynchronous manner and the vaule may not be very precise. To see a precise
+snapshot of a moment, you can see /proc/<pid>/smaps file and scan page table.
+It's slow but very precise.
+
Table 1-2: Contents of the statm files (as of 2.6.30-rc7)
..............................................................................
Field Content
@@ -213,6 +220,7 @@ Table 1-2: Contents of the statm files (as of 2.6.30-rc7)
VmExe size of text segment
VmLib size of shared library code
VmPTE size of page table entries
+ VmSwap size of swap usage (the number of referred swapents)
Threads number of threads
SigQ number of signals queued/max. number for queue
SigPnd bitmap of pending signals for the thread
@@ -430,6 +438,7 @@ Table 1-5: Kernel info in /proc
modules List of loaded modules
mounts Mounted filesystems
net Networking info (see text)
+ pagetypeinfo Additional page allocator information (see text) (2.5)
partitions Table of partitions known to the system
pci Deprecated info of PCI bus (new way -> /proc/bus/pci/,
decoupled by lspci (2.4)
@@ -584,7 +593,7 @@ Node 0, zone DMA 0 4 5 4 4 3 ...
Node 0, zone Normal 1 0 0 1 101 8 ...
Node 0, zone HighMem 2 0 0 1 1 0 ...
-Memory fragmentation is a problem under some workloads, and buddyinfo is a
+External fragmentation is a problem under some workloads, and buddyinfo is a
useful tool for helping diagnose these problems. Buddyinfo will give you a
clue as to how big an area you can safely allocate, or why a previous
allocation failed.
@@ -594,6 +603,48 @@ available. In this case, there are 0 chunks of 2^0*PAGE_SIZE available in
ZONE_DMA, 4 chunks of 2^1*PAGE_SIZE in ZONE_DMA, 101 chunks of 2^4*PAGE_SIZE
available in ZONE_NORMAL, etc...
+More information relevant to external fragmentation can be found in
+pagetypeinfo.
+
+> cat /proc/pagetypeinfo
+Page block order: 9
+Pages per block: 512
+
+Free pages count per migrate type at order 0 1 2 3 4 5 6 7 8 9 10
+Node 0, zone DMA, type Unmovable 0 0 0 1 1 1 1 1 1 1 0
+Node 0, zone DMA, type Reclaimable 0 0 0 0 0 0 0 0 0 0 0
+Node 0, zone DMA, type Movable 1 1 2 1 2 1 1 0 1 0 2
+Node 0, zone DMA, type Reserve 0 0 0 0 0 0 0 0 0 1 0
+Node 0, zone DMA, type Isolate 0 0 0 0 0 0 0 0 0 0 0
+Node 0, zone DMA32, type Unmovable 103 54 77 1 1 1 11 8 7 1 9
+Node 0, zone DMA32, type Reclaimable 0 0 2 1 0 0 0 0 1 0 0
+Node 0, zone DMA32, type Movable 169 152 113 91 77 54 39 13 6 1 452
+Node 0, zone DMA32, type Reserve 1 2 2 2 2 0 1 1 1 1 0
+Node 0, zone DMA32, type Isolate 0 0 0 0 0 0 0 0 0 0 0
+
+Number of blocks type Unmovable Reclaimable Movable Reserve Isolate
+Node 0, zone DMA 2 0 5 1 0
+Node 0, zone DMA32 41 6 967 2 0
+
+Fragmentation avoidance in the kernel works by grouping pages of different
+migrate types into the same contiguous regions of memory called page blocks.
+A page block is typically the size of the default hugepage size e.g. 2MB on
+X86-64. By keeping pages grouped based on their ability to move, the kernel
+can reclaim pages within a page block to satisfy a high-order allocation.
+
+The pagetypinfo begins with information on the size of a page block. It
+then gives the same type of information as buddyinfo except broken down
+by migrate-type and finishes with details on how many page blocks of each
+type exist.
+
+If min_free_kbytes has been tuned correctly (recommendations made by hugeadm
+from libhugetlbfs http://sourceforge.net/projects/libhugetlbfs/), one can
+make an estimate of the likely number of huge pages that can be allocated
+at a given point in time. All the "Movable" blocks should be allocatable
+unless memory has been mlock()'d. Some of the Reclaimable blocks should
+also be allocatable although a lot of filesystem metadata may have to be
+reclaimed to achieve this.
+
..............................................................................
meminfo:
diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt
index 1866c27eec6..c2c6e9b39bb 100644
--- a/Documentation/gpio.txt
+++ b/Documentation/gpio.txt
@@ -253,6 +253,70 @@ pin setup (e.g. controlling which pin the GPIO uses, pullup/pulldown).
Also note that it's your responsibility to have stopped using a GPIO
before you free it.
+Considering in most cases GPIOs are actually configured right after they
+are claimed, three additional calls are defined:
+
+ /* request a single GPIO, with initial configuration specified by
+ * 'flags', identical to gpio_request() wrt other arguments and
+ * return value
+ */
+ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
+
+ /* request multiple GPIOs in a single call
+ */
+ int gpio_request_array(struct gpio *array, size_t num);
+
+ /* release multiple GPIOs in a single call
+ */
+ void gpio_free_array(struct gpio *array, size_t num);
+
+where 'flags' is currently defined to specify the following properties:
+
+ * GPIOF_DIR_IN - to configure direction as input
+ * GPIOF_DIR_OUT - to configure direction as output
+
+ * GPIOF_INIT_LOW - as output, set initial level to LOW
+ * GPIOF_INIT_HIGH - as output, set initial level to HIGH
+
+since GPIOF_INIT_* are only valid when configured as output, so group valid
+combinations as:
+
+ * GPIOF_IN - configure as input
+ * GPIOF_OUT_INIT_LOW - configured as output, initial level LOW
+ * GPIOF_OUT_INIT_HIGH - configured as output, initial level HIGH
+
+In the future, these flags can be extended to support more properties such
+as open-drain status.
+
+Further more, to ease the claim/release of multiple GPIOs, 'struct gpio' is
+introduced to encapsulate all three fields as:
+
+ struct gpio {
+ unsigned gpio;
+ unsigned long flags;
+ const char *label;
+ };
+
+A typical example of usage:
+
+ static struct gpio leds_gpios[] = {
+ { 32, GPIOF_OUT_INIT_HIGH, "Power LED" }, /* default to ON */
+ { 33, GPIOF_OUT_INIT_LOW, "Green LED" }, /* default to OFF */
+ { 34, GPIOF_OUT_INIT_LOW, "Red LED" }, /* default to OFF */
+ { 35, GPIOF_OUT_INIT_LOW, "Blue LED" }, /* default to OFF */
+ { ... },
+ };
+
+ err = gpio_request_one(31, GPIOF_IN, "Reset Button");
+ if (err)
+ ...
+
+ err = gpio_request_array(leds_gpios, ARRAY_SIZE(leds_gpios));
+ if (err)
+ ...
+
+ gpio_free_array(leds_gpios, ARRAY_SIZE(leds_gpios));
+
GPIOs mapped to IRQs
--------------------
diff --git a/Documentation/hwmon/adt7411 b/Documentation/hwmon/adt7411
new file mode 100644
index 00000000000..1632960f974
--- /dev/null
+++ b/Documentation/hwmon/adt7411
@@ -0,0 +1,42 @@
+Kernel driver adt7411
+=====================
+
+Supported chips:
+ * Analog Devices ADT7411
+ Prefix: 'adt7411'
+ Addresses scanned: 0x48, 0x4a, 0x4b
+ Datasheet: Publicly available at the Analog Devices website
+
+Author: Wolfram Sang (based on adt7470 by Darrick J. Wong)
+
+Description
+-----------
+
+This driver implements support for the Analog Devices ADT7411 chip. There may
+be other chips that implement this interface.
+
+The ADT7411 can use an I2C/SMBus compatible 2-wire interface or an
+SPI-compatible 4-wire interface. It provides a 10-bit analog to digital
+converter which measures 1 temperature, vdd and 8 input voltages. It has an
+internal temperature sensor, but an external one can also be connected (one
+loses 2 inputs then). There are high- and low-limit registers for all inputs.
+
+Check the datasheet for details.
+
+sysfs-Interface
+---------------
+
+in0_input - vdd voltage input
+in[1-8]_input - analog 1-8 input
+temp1_input - temperature input
+
+Besides standard interfaces, this driver adds (0 = off, 1 = on):
+
+ adc_ref_vdd - Use vdd as reference instead of 2.25 V
+ fast_sampling - Sample at 22.5 kHz instead of 1.4 kHz, but drop filters
+ no_average - Turn off averaging over 16 samples
+
+Notes
+-----
+
+SPI, external temperature sensor and limit registers are not supported yet.
diff --git a/Documentation/hwmon/adt7473 b/Documentation/hwmon/adt7473
deleted file mode 100644
index 446612bd1fb..00000000000
--- a/Documentation/hwmon/adt7473
+++ /dev/null
@@ -1,74 +0,0 @@
-Kernel driver adt7473
-======================
-
-Supported chips:
- * Analog Devices ADT7473
- Prefix: 'adt7473'
- Addresses scanned: I2C 0x2C, 0x2D, 0x2E
- Datasheet: Publicly available at the Analog Devices website
-
-Author: Darrick J. Wong
-
-This driver is depreacted, please use the adt7475 driver instead.
-
-Description
------------
-
-This driver implements support for the Analog Devices ADT7473 chip family.
-
-The ADT7473 uses the 2-wire interface compatible with the SMBUS 2.0
-specification. Using an analog to digital converter it measures three (3)
-temperatures and two (2) voltages. It has four (4) 16-bit counters for
-measuring fan speed. There are three (3) PWM outputs that can be used
-to control fan speed.
-
-A sophisticated control system for the PWM outputs is designed into the
-ADT7473 that allows fan speed to be adjusted automatically based on any of the
-three temperature sensors. Each PWM output is individually adjustable and
-programmable. Once configured, the ADT7473 will adjust the PWM outputs in
-response to the measured temperatures without further host intervention.
-This feature can also be disabled for manual control of the PWM's.
-
-Each of the measured inputs (voltage, temperature, fan speed) has
-corresponding high/low limit values. The ADT7473 will signal an ALARM if
-any measured value exceeds either limit.
-
-The ADT7473 samples all inputs continuously. The driver will not read
-the registers more often than once every other second. Further,
-configuration data is only read once per minute.
-
-Special Features
-----------------
-
-The ADT7473 have a 10-bit ADC and can therefore measure temperatures
-with 0.25 degC resolution. Temperature readings can be configured either
-for twos complement format or "Offset 64" format, wherein 63 is subtracted
-from the raw value to get the temperature value.
-
-The Analog Devices datasheet is very detailed and describes a procedure for
-determining an optimal configuration for the automatic PWM control.
-
-Configuration Notes
--------------------
-
-Besides standard interfaces driver adds the following:
-
-* PWM Control
-
-* pwm#_auto_point1_pwm and temp#_auto_point1_temp and
-* pwm#_auto_point2_pwm and temp#_auto_point2_temp -
-
-point1: Set the pwm speed at a lower temperature bound.
-point2: Set the pwm speed at a higher temperature bound.
-
-The ADT7473 will scale the pwm between the lower and higher pwm speed when
-the temperature is between the two temperature boundaries. PWM values range
-from 0 (off) to 255 (full speed). Fan speed will be set to maximum when the
-temperature sensor associated with the PWM control exceeds temp#_max.
-
-Notes
------
-
-The NVIDIA binary driver presents an ADT7473 chip via an on-card i2c bus.
-Unfortunately, they fail to set the i2c adapter class, so this driver may
-fail to find the chip until the nvidia driver is patched.
diff --git a/Documentation/hwmon/asc7621 b/Documentation/hwmon/asc7621
new file mode 100644
index 00000000000..7287be7e1f2
--- /dev/null
+++ b/Documentation/hwmon/asc7621
@@ -0,0 +1,296 @@
+Kernel driver asc7621
+==================
+
+Supported chips:
+ Andigilog aSC7621 and aSC7621a
+ Prefix: 'asc7621'
+ Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+ Datasheet: http://www.fairview5.com/linux/asc7621/asc7621.pdf
+
+Author:
+ George Joseph
+
+Description provided by Dave Pivin @ Andigilog:
+
+Andigilog has both the PECI and pre-PECI versions of the Heceta-6, as
+Intel calls them. Heceta-6e has high frequency PWM and Heceta-6p has
+added PECI and a 4th thermal zone. The Andigilog aSC7611 is the
+Heceta-6e part and aSC7621 is the Heceta-6p part. They are both in
+volume production, shipping to Intel and their subs.
+
+We have enhanced both parts relative to the governing Intel
+specification. First enhancement is temperature reading resolution. We
+have used registers below 20h for vendor-specific functions in addition
+to those in the Intel-specified vendor range.
+
+Our conversion process produces a result that is reported as two bytes.
+The fan speed control uses this finer value to produce a "step-less" fan
+PWM output. These two bytes are "read-locked" to guarantee that once a
+high or low byte is read, the other byte is locked-in until after the
+next read of any register. So to get an atomic reading, read high or low
+byte, then the very next read should be the opposite byte. Our data
+sheet says 10-bits of resolution, although you may find the lower bits
+are active, they are not necessarily reliable or useful externally. We
+chose not to mask them.
+
+We employ significant filtering that is user tunable as described in the
+data sheet. Our temperature reports and fan PWM outputs are very smooth
+when compared to the competition, in addition to the higher resolution
+temperature reports. The smoother PWM output does not require user
+intervention.
+
+We offer GPIO features on the former VID pins. These are open-drain
+outputs or inputs and may be used as general purpose I/O or as alarm
+outputs that are based on temperature limits. These are in 19h and 1Ah.
+
+We offer flexible mapping of temperature readings to thermal zones. Any
+temperature may be mapped to any zone, which has a default assignment
+that follows Intel's specs.
+
+Since there is a fan to zone assignment that allows for the "hotter" of
+a set of zones to control the PWM of an individual fan, but there is no
+indication to the user, we have added an indicator that shows which zone
+is currently controlling the PWM for a given fan. This is in register
+00h.
+
+Both remote diode temperature readings may be given an offset value such
+that the reported reading as well as the temperature used to determine
+PWM may be offset for system calibration purposes.
+
+PECI Extended configuration allows for having more than two domains per
+PECI address and also provides an enabling function for each PECI
+address. One could use our flexible zone assignment to have a zone
+assigned to up to 4 PECI addresses. This is not possible in the default
+Intel configuration. This would be useful in multi-CPU systems with
+individual fans on each that would benefit from individual fan control.
+This is in register 0Eh.
+
+The tachometer measurement system is flexible and able to adapt to many
+fan types. We can also support pulse-stretched PWM so that 3-wire fans
+may be used. These characteristics are in registers 04h to 07h.
+
+Finally, we have added a tach disable function that turns off the tach
+measurement system for individual tachs in order to save power. That is
+in register 75h.
+
+--
+aSC7621 Product Description
+
+The aSC7621 has a two wire digital interface compatible with SMBus 2.0.
+Using a 10-bit ADC, the aSC7621 measures the temperature of two remote diode
+connected transistors as well as its own die. Support for Platform
+Environmental Control Interface (PECI) is included.
+
+Using temperature information from these four zones, an automatic fan speed
+control algorithm is employed to minimize acoustic impact while achieving
+recommended CPU temperature under varying operational loads.
+
+To set fan speed, the aSC7621 has three independent pulse width modulation
+(PWM) outputs that are controlled by one, or a combination of three,
+temperature zones. Both high- and low-frequency PWM ranges are supported.
+
+The aSC7621 also includes a digital filter that can be invoked to smooth
+temperature readings for better control of fan speed and minimum acoustic
+impact.
+
+The aSC7621 has tachometer inputs to measure fan speed on up to four fans.
+Limit and status registers for all measured values are included to alert
+the system host that any measurements are outside of programmed limits
+via status registers.
+
+System voltages of VCCP, 2.5V, 3.3V, 5.0V, and 12V motherboard power are
+monitored efficiently with internal scaling resistors.
+
+Features
+- Supports PECI interface and monitors internal and remote thermal diodes
+- 2-wire, SMBus 2.0 compliant, serial interface
+- 10-bit ADC
+- Monitors VCCP, 2.5V, 3.3V, 5.0V, and 12V motherboard/processor supplies
+- Programmable autonomous fan control based on temperature readings
+- Noise filtering of temperature reading for fan speed control
+- 0.25C digital temperature sensor resolution
+- 3 PWM fan speed control outputs for 2-, 3- or 4-wire fans and up to 4 fan
+ tachometer inputs
+- Enhanced measured temperature to Temperature Zone assignment.
+- Provides high and low PWM frequency ranges
+- 3 GPIO pins for custom use
+- 24-Lead QSOP package
+
+Configuration Notes
+===================
+
+Except where noted below, the sysfs entries created by this driver follow
+the standards defined in "sysfs-interface".
+
+temp1_source
+ 0 (default) peci_legacy = 0, Remote 1 Temperature
+ peci_legacy = 1, PECI Processor Temperature 0
+ 1 Remote 1 Temperature
+ 2 Remote 2 Temperature
+ 3 Internal Temperature
+ 4 PECI Processor Temperature 0
+ 5 PECI Processor Temperature 1
+ 6 PECI Processor Temperature 2
+ 7 PECI Processor Temperature 3
+
+temp2_source
+ 0 (default) Internal Temperature
+ 1 Remote 1 Temperature
+ 2 Remote 2 Temperature
+ 3 Internal Temperature
+ 4 PECI Processor Temperature 0
+ 5 PECI Processor Temperature 1
+ 6 PECI Processor Temperature 2
+ 7 PECI Processor Temperature 3
+
+temp3_source
+ 0 (default) Remote 2 Temperature
+ 1 Remote 1 Temperature
+ 2 Remote 2 Temperature
+ 3 Internal Temperature
+ 4 PECI Processor Temperature 0
+ 5 PECI Processor Temperature 1
+ 6 PECI Processor Temperature 2
+ 7 PECI Processor Temperature 3
+
+temp4_source
+ 0 (default) peci_legacy = 0, PECI Processor Temperature 0
+ peci_legacy = 1, Remote 1 Temperature
+ 1 Remote 1 Temperature
+ 2 Remote 2 Temperature
+ 3 Internal Temperature
+ 4 PECI Processor Temperature 0
+ 5 PECI Processor Temperature 1
+ 6 PECI Processor Temperature 2
+ 7 PECI Processor Temperature 3
+
+temp[1-4]_smoothing_enable
+temp[1-4]_smoothing_time
+ Smooths spikes in temp readings caused by noise.
+ Valid values in milliseconds are:
+ 35000
+ 17600
+ 11800
+ 7000
+ 4400
+ 3000
+ 1600
+ 800
+
+temp[1-4]_crit
+ When the corresponding zone temperature reaches this value,
+ ALL pwm outputs will got to 100%.
+
+temp[5-8]_input
+temp[5-8]_enable
+ The aSC7621 can also read temperatures provided by the processor
+ via the PECI bus. Usually these are "core" temps and are relative
+ to the point where the automatic thermal control circuit starts
+ throttling. This means that these are usually negative numbers.
+
+pwm[1-3]_enable
+ 0 Fan off.
+ 1 Fan on manual control.
+ 2 Fan on automatic control and will run at the minimum pwm
+ if the temperature for the zone is below the minimum.
+ 3 Fan on automatic control but will be off if the temperature
+ for the zone is below the minimum.
+ 4-254 Ignored.
+ 255 Fan on full.
+
+pwm[1-3]_auto_channels
+ Bitmap as described in sysctl-interface with the following
+ exceptions...
+ Only the following combination of zones (and their corresponding masks)
+ are valid:
+ 1
+ 2
+ 3
+ 2,3
+ 1,2,3
+ 4
+ 1,2,3,4
+
+ Special values:
+ 0 Disabled.
+ 16 Fan on manual control.
+ 31 Fan on full.
+
+
+pwm[1-3]_invert
+ When set, inverts the meaning of pwm[1-3].
+ i.e. when pwm = 0, the fan will be on full and
+ when pwm = 255 the fan will be off.
+
+pwm[1-3]_freq
+ PWM frequency in Hz
+ Valid values in Hz are:
+
+ 10
+ 15
+ 23
+ 30 (default)
+ 38
+ 47
+ 62
+ 94
+ 23000
+ 24000
+ 25000
+ 26000
+ 27000
+ 28000
+ 29000
+ 30000
+
+ Setting any other value will be ignored.
+
+peci_enable
+ Enables or disables PECI
+
+peci_avg
+ Input filter average time.
+
+ 0 0 Sec. (no Smoothing) (default)
+ 1 0.25 Sec.
+ 2 0.5 Sec.
+ 3 1.0 Sec.
+ 4 2.0 Sec.
+ 5 4.0 Sec.
+ 6 8.0 Sec.
+ 7 0.0 Sec.
+
+peci_legacy
+
+ 0 Standard Mode (default)
+ Remote Diode 1 reading is associated with
+ Temperature Zone 1, PECI is associated with
+ Zone 4
+
+ 1 Legacy Mode
+ PECI is associated with Temperature Zone 1,
+ Remote Diode 1 is associated with Zone 4
+
+peci_diode
+ Diode filter
+
+ 0 0.25 Sec.
+ 1 1.1 Sec.
+ 2 2.4 Sec. (default)
+ 3 3.4 Sec.
+ 4 5.0 Sec.
+ 5 6.8 Sec.
+ 6 10.2 Sec.
+ 7 16.4 Sec.
+
+peci_4domain
+ Four domain enable
+
+ 0 1 or 2 Domains for enabled processors (default)
+ 1 3 or 4 Domains for enabled processors
+
+peci_domain
+ Domain
+
+ 0 Processor contains a single domain (0) (default)
+ 1 Processor contains two domains (0,1)
diff --git a/Documentation/hwmon/it87 b/Documentation/hwmon/it87
index f9ba96c0ac4..8d08bf0d38e 100644
--- a/Documentation/hwmon/it87
+++ b/Documentation/hwmon/it87
@@ -5,31 +5,23 @@ Supported chips:
* IT8705F
Prefix: 'it87'
Addresses scanned: from Super I/O config space (8 I/O ports)
- Datasheet: Publicly available at the ITE website
- http://www.ite.com.tw/product_info/file/pc/IT8705F_V.0.4.1.pdf
+ Datasheet: Once publicly available at the ITE website, but no longer
* IT8712F
Prefix: 'it8712'
Addresses scanned: from Super I/O config space (8 I/O ports)
- Datasheet: Publicly available at the ITE website
- http://www.ite.com.tw/product_info/file/pc/IT8712F_V0.9.1.pdf
- http://www.ite.com.tw/product_info/file/pc/Errata%20V0.1%20for%20IT8712F%20V0.9.1.pdf
- http://www.ite.com.tw/product_info/file/pc/IT8712F_V0.9.3.pdf
+ Datasheet: Once publicly available at the ITE website, but no longer
* IT8716F/IT8726F
Prefix: 'it8716'
Addresses scanned: from Super I/O config space (8 I/O ports)
- Datasheet: Publicly available at the ITE website
- http://www.ite.com.tw/product_info/file/pc/IT8716F_V0.3.ZIP
- http://www.ite.com.tw/product_info/file/pc/IT8726F_V0.3.pdf
+ Datasheet: Once publicly available at the ITE website, but no longer
* IT8718F
Prefix: 'it8718'
Addresses scanned: from Super I/O config space (8 I/O ports)
- Datasheet: Publicly available at the ITE website
- http://www.ite.com.tw/product_info/file/pc/IT8718F_V0.2.zip
- http://www.ite.com.tw/product_info/file/pc/IT8718F_V0%203_(for%20C%20version).zip
+ Datasheet: Once publicly available at the ITE website, but no longer
* IT8720F
Prefix: 'it8720'
Addresses scanned: from Super I/O config space (8 I/O ports)
- Datasheet: Not yet publicly available.
+ Datasheet: Not publicly available
* SiS950 [clone of IT8705F]
Prefix: 'it87'
Addresses scanned: from Super I/O config space (8 I/O ports)
@@ -136,6 +128,10 @@ registers are read whenever any data is read (unless it is less than 1.5
seconds since the last update). This means that you can easily miss
once-only alarms.
+Out-of-limit readings can also result in beeping, if the chip is properly
+wired and configured. Beeping can be enabled or disabled per sensor type
+(temperatures, voltages and fans.)
+
The IT87xx only updates its values each 1.5 seconds; reading it more often
will do no harm, but will return 'old' values.
@@ -150,11 +146,38 @@ Fan speed control
-----------------
The fan speed control features are limited to manual PWM mode. Automatic
-"Smart Guardian" mode control handling is not implemented. However
-if you want to go for "manual mode" just write 1 to pwmN_enable.
+"Smart Guardian" mode control handling is only implemented for older chips
+(see below.) However if you want to go for "manual mode" just write 1 to
+pwmN_enable.
If you are only able to control the fan speed with very small PWM values,
try lowering the PWM base frequency (pwm1_freq). Depending on the fan,
it may give you a somewhat greater control range. The same frequency is
used to drive all fan outputs, which is why pwm2_freq and pwm3_freq are
read-only.
+
+
+Automatic fan speed control (old interface)
+-------------------------------------------
+
+The driver supports the old interface to automatic fan speed control
+which is implemented by IT8705F chips up to revision F and IT8712F
+chips up to revision G.
+
+This interface implements 4 temperature vs. PWM output trip points.
+The PWM output of trip point 4 is always the maximum value (fan running
+at full speed) while the PWM output of the other 3 trip points can be
+freely chosen. The temperature of all 4 trip points can be freely chosen.
+Additionally, trip point 1 has an hysteresis temperature attached, to
+prevent fast switching between fan on and off.
+
+The chip automatically computes the PWM output value based on the input
+temperature, based on this simple rule: if the temperature value is
+between trip point N and trip point N+1 then the PWM output value is
+the one of trip point N. The automatic control mode is less flexible
+than the manual control mode, but it reacts faster, is more robust and
+doesn't use CPU cycles.
+
+Trip points must be set properly before switching to automatic fan speed
+control mode. The driver will perform basic integrity checks before
+actually switching to automatic control mode.
diff --git a/Documentation/hwmon/lm90 b/Documentation/hwmon/lm90
index 93d8e3d5515..6a03dd4bcc9 100644
--- a/Documentation/hwmon/lm90
+++ b/Documentation/hwmon/lm90
@@ -84,6 +84,10 @@ Supported chips:
Addresses scanned: I2C 0x4c
Datasheet: Publicly available at the Maxim website
http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3500
+ * Winbond/Nuvoton W83L771AWG/ASG
+ Prefix: 'w83l771'
+ Addresses scanned: I2C 0x4c
+ Datasheet: Not publicly available, can be requested from Nuvoton
Author: Jean Delvare <khali@linux-fr.org>
@@ -147,6 +151,12 @@ MAX6680 and MAX6681:
* Selectable address
* Remote sensor type selection
+W83L771AWG/ASG
+ * The AWG and ASG variants only differ in package format.
+ * Filter and alert configuration register at 0xBF
+ * Diode ideality factor configuration (remote sensor) at 0xE3
+ * Moving average (depending on conversion rate)
+
All temperature values are given in degrees Celsius. Resolution
is 1.0 degree for the local temperature, 0.125 degree for the remote
temperature, except for the MAX6657, MAX6658 and MAX6659 which have a
@@ -163,6 +173,18 @@ The lm90 driver will not update its values more frequently than every
other second; reading them more often will do no harm, but will return
'old' values.
+SMBus Alert Support
+-------------------
+
+This driver has basic support for SMBus alert. When an alert is received,
+the status register is read and the faulty temperature channel is logged.
+
+The Analog Devices chips (ADM1032 and ADT7461) do not implement the SMBus
+alert protocol properly so additional care is needed: the ALERT output is
+disabled when an alert is received, and is re-enabled only when the alarm
+is gone. Otherwise the chip would block alerts from other chips in the bus
+as long as the alarm is active.
+
PEC Support
-----------
diff --git a/Documentation/init.txt b/Documentation/init.txt
new file mode 100644
index 00000000000..535ad5e82b9
--- /dev/null
+++ b/Documentation/init.txt
@@ -0,0 +1,49 @@
+Explaining the dreaded "No init found." boot hang message
+=========================================================
+
+OK, so you've got this pretty unintuitive message (currently located
+in init/main.c) and are wondering what the H*** went wrong.
+Some high-level reasons for failure (listed roughly in order of execution)
+to load the init binary are:
+A) Unable to mount root FS
+B) init binary doesn't exist on rootfs
+C) broken console device
+D) binary exists but dependencies not available
+E) binary cannot be loaded
+
+Detailed explanations:
+0) Set "debug" kernel parameter (in bootloader config file or CONFIG_CMDLINE)
+ to get more detailed kernel messages.
+A) make sure you have the correct root FS type
+ (and root= kernel parameter points to the correct partition),
+ required drivers such as storage hardware (such as SCSI or USB!)
+ and filesystem (ext3, jffs2 etc.) are builtin (alternatively as modules,
+ to be pre-loaded by an initrd)
+C) Possibly a conflict in console= setup --> initial console unavailable.
+ E.g. some serial consoles are unreliable due to serial IRQ issues (e.g.
+ missing interrupt-based configuration).
+ Try using a different console= device or e.g. netconsole= .
+D) e.g. required library dependencies of the init binary such as
+ /lib/ld-linux.so.2 missing or broken. Use readelf -d <INIT>|grep NEEDED
+ to find out which libraries are required.
+E) make sure the binary's architecture matches your hardware.
+ E.g. i386 vs. x86_64 mismatch, or trying to load x86 on ARM hardware.
+ In case you tried loading a non-binary file here (shell script?),
+ you should make sure that the script specifies an interpreter in its shebang
+ header line (#!/...) that is fully working (including its library
+ dependencies). And before tackling scripts, better first test a simple
+ non-script binary such as /bin/sh and confirm its successful execution.
+ To find out more, add code to init/main.c to display kernel_execve()s
+ return values.
+
+Please extend this explanation whenever you find new failure causes
+(after all loading the init binary is a CRITICAL and hard transition step
+which needs to be made as painless as possible), then submit patch to LKML.
+Further TODOs:
+- Implement the various run_init_process() invocations via a struct array
+ which can then store the kernel_execve() result value and on failure
+ log it all by iterating over _all_ results (very important usability fix).
+- try to make the implementation itself more helpful in general,
+ e.g. by providing additional error messages at affected places.
+
+Andreas Mohr <andi at lisas period de>
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index d80930d58da..3bc48b0bd3a 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2834,6 +2834,12 @@ and is between 256 and 4096 characters. It is defined in the file
default x2apic cluster mode on platforms
supporting x2apic.
+ x86_mrst_timer= [X86-32,APBT]
+ Choose timer option for x86 Moorestown MID platform.
+ Two valid options are apbt timer only and lapic timer
+ plus one apbt timer for broadcast timer.
+ x86_mrst_timer=apbt_only | lapic_and_apbt
+
xd= [HW,XT] Original XT pre-IDE (RLL encoded) disks.
xd_geo= See header of drivers/block/xd.c.
diff --git a/Documentation/kobject.txt b/Documentation/kobject.txt
index c79ab996dad..bdb13817e1e 100644
--- a/Documentation/kobject.txt
+++ b/Documentation/kobject.txt
@@ -266,7 +266,7 @@ kobj_type:
struct kobj_type {
void (*release)(struct kobject *);
- struct sysfs_ops *sysfs_ops;
+ const struct sysfs_ops *sysfs_ops;
struct attribute **default_attrs;
};
diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt
index 356fd86f4ea..ab00eeddeca 100644
--- a/Documentation/power/runtime_pm.txt
+++ b/Documentation/power/runtime_pm.txt
@@ -224,6 +224,12 @@ defined in include/linux/pm.h:
RPM_SUSPENDED, which means that each device is initially regarded by the
PM core as 'suspended', regardless of its real hardware status
+ unsigned int runtime_auto;
+ - if set, indicates that the user space has allowed the device driver to
+ power manage the device at run time via the /sys/devices/.../power/control
+ interface; it may only be modified with the help of the pm_runtime_allow()
+ and pm_runtime_forbid() helper functions
+
All of the above fields are members of the 'power' member of 'struct device'.
4. Run-time PM Device Helper Functions
@@ -329,6 +335,20 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
'power.runtime_error' is set or 'power.disable_depth' is greater than
zero)
+ bool pm_runtime_suspended(struct device *dev);
+ - return true if the device's runtime PM status is 'suspended', or false
+ otherwise
+
+ void pm_runtime_allow(struct device *dev);
+ - set the power.runtime_auto flag for the device and decrease its usage
+ counter (used by the /sys/devices/.../power/control interface to
+ effectively allow the device to be power managed at run time)
+
+ void pm_runtime_forbid(struct device *dev);
+ - unset the power.runtime_auto flag for the device and increase its usage
+ counter (used by the /sys/devices/.../power/control interface to
+ effectively prevent the device from being power managed at run time)
+
It is safe to execute the following helper functions from interrupt context:
pm_request_idle()
@@ -382,6 +402,18 @@ may be desirable to suspend the device as soon as ->probe() or ->remove() has
finished, so the PM core uses pm_runtime_idle_sync() to invoke the
subsystem-level idle callback for the device at that time.
+The user space can effectively disallow the driver of the device to power manage
+it at run time by changing the value of its /sys/devices/.../power/control
+attribute to "on", which causes pm_runtime_forbid() to be called. In principle,
+this mechanism may also be used by the driver to effectively turn off the
+run-time power management of the device until the user space turns it on.
+Namely, during the initialization the driver can make sure that the run-time PM
+status of the device is 'active' and call pm_runtime_forbid(). It should be
+noted, however, that if the user space has already intentionally changed the
+value of /sys/devices/.../power/control to "auto" to allow the driver to power
+manage the device at run time, the driver may confuse it by using
+pm_runtime_forbid() this way.
+
6. Run-time PM and System Sleep
Run-time PM and system sleep (i.e., system suspend and hibernation, also known
@@ -431,3 +463,64 @@ The PM core always increments the run-time usage counter before calling the
->prepare() callback and decrements it after calling the ->complete() callback.
Hence disabling run-time PM temporarily like this will not cause any run-time
suspend callbacks to be lost.
+
+7. Generic subsystem callbacks
+
+Subsystems may wish to conserve code space by using the set of generic power
+management callbacks provided by the PM core, defined in
+driver/base/power/generic_ops.c:
+
+ int pm_generic_runtime_idle(struct device *dev);
+ - invoke the ->runtime_idle() callback provided by the driver of this
+ device, if defined, and call pm_runtime_suspend() for this device if the
+ return value is 0 or the callback is not defined
+
+ int pm_generic_runtime_suspend(struct device *dev);
+ - invoke the ->runtime_suspend() callback provided by the driver of this
+ device and return its result, or return -EINVAL if not defined
+
+ int pm_generic_runtime_resume(struct device *dev);
+ - invoke the ->runtime_resume() callback provided by the driver of this
+ device and return its result, or return -EINVAL if not defined
+
+ int pm_generic_suspend(struct device *dev);
+ - if the device has not been suspended at run time, invoke the ->suspend()
+ callback provided by its driver and return its result, or return 0 if not
+ defined
+
+ int pm_generic_resume(struct device *dev);
+ - invoke the ->resume() callback provided by the driver of this device and,
+ if successful, change the device's runtime PM status to 'active'
+
+ int pm_generic_freeze(struct device *dev);
+ - if the device has not been suspended at run time, invoke the ->freeze()
+ callback provided by its driver and return its result, or return 0 if not
+ defined
+
+ int pm_generic_thaw(struct device *dev);
+ - if the device has not been suspended at run time, invoke the ->thaw()
+ callback provided by its driver and return its result, or return 0 if not
+ defined
+
+ int pm_generic_poweroff(struct device *dev);
+ - if the device has not been suspended at run time, invoke the ->poweroff()
+ callback provided by its driver and return its result, or return 0 if not
+ defined
+
+ int pm_generic_restore(struct device *dev);
+ - invoke the ->restore() callback provided by the driver of this device and,
+ if successful, change the device's runtime PM status to 'active'
+
+These functions can be assigned to the ->runtime_idle(), ->runtime_suspend(),
+->runtime_resume(), ->suspend(), ->resume(), ->freeze(), ->thaw(), ->poweroff(),
+or ->restore() callback pointers in the subsystem-level dev_pm_ops structures.
+
+If a subsystem wishes to use all of them at the same time, it can simply assign
+the GENERIC_SUBSYS_PM_OPS macro, defined in include/linux/pm.h, to its
+dev_pm_ops structure pointer.
+
+Device drivers that wish to use the same function as a system suspend, freeze,
+poweroff and run-time suspend callback, and similarly for system resume, thaw,
+restore, and run-time resume, can achieve this with the help of the
+UNIVERSAL_DEV_PM_OPS macro defined in include/linux/pm.h (possibly setting its
+last argument to NULL).
diff --git a/Documentation/powerpc/dts-bindings/fsl/i2c.txt b/Documentation/powerpc/dts-bindings/fsl/i2c.txt
index b6d2e21474f..50da2031058 100644
--- a/Documentation/powerpc/dts-bindings/fsl/i2c.txt
+++ b/Documentation/powerpc/dts-bindings/fsl/i2c.txt
@@ -2,15 +2,14 @@
Required properties :
- - device_type : Should be "i2c"
- reg : Offset and length of the register set for the device
+ - compatible : should be "fsl,CHIP-i2c" where CHIP is the name of a
+ compatible processor, e.g. mpc8313, mpc8543, mpc8544, mpc5121,
+ mpc5200 or mpc5200b. For the mpc5121, an additional node
+ "fsl,mpc5121-i2c-ctrl" is required as shown in the example below.
Recommended properties :
- - 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
@@ -24,25 +23,40 @@ Recommended properties :
Examples :
+ /* MPC5121 based board */
+ i2c@1740 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,mpc5121-i2c", "fsl-i2c";
+ reg = <0x1740 0x20>;
+ interrupts = <11 0x8>;
+ interrupt-parent = <&ipic>;
+ clock-frequency = <100000>;
+ };
+
+ i2ccontrol@1760 {
+ compatible = "fsl,mpc5121-i2c-ctrl";
+ reg = <0x1760 0x8>;
+ };
+
+ /* MPC5200B based board */
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;
};
+ /* MPC8544 base board */
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/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 33df82e3a39..bfcbbf88c44 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -1812,7 +1812,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
Module snd-ua101
----------------
- Module for the Edirol UA-101 audio/MIDI interface.
+ Module for the Edirol UA-101/UA-1000 audio/MIDI interfaces.
This module supports multiple devices, autoprobe and hotplugging.
diff --git a/MAINTAINERS b/MAINTAINERS
index 51d8b5221dd..c8a8b1fd58b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -71,6 +71,7 @@ Descriptions of section entries:
M: Mail patches to: FullName <address@domain>
L: Mailing list that is relevant to this area
W: Web-page with status/info
+ Q: Patchwork web based patch tracking system site
T: SCM tree type and location. Type is one of: git, hg, quilt, stgit.
S: Status, one of the following:
Supported: Someone is actually paid to look after this.
@@ -182,6 +183,7 @@ M: Ron Minnich <rminnich@sandia.gov>
M: Latchesar Ionkov <lucho@ionkov.net>
L: v9fs-developer@lists.sourceforge.net
W: http://swik.net/v9fs
+Q: http://patchwork.kernel.org/project/v9fs-devel/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs.git
S: Maintained
F: Documentation/filesystems/9p.txt
@@ -238,6 +240,7 @@ ACPI
M: Len Brown <lenb@kernel.org>
L: linux-acpi@vger.kernel.org
W: http://www.lesswatts.org/projects/acpi/
+Q: http://patchwork.kernel.org/project/linux-acpi/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git
S: Supported
F: drivers/acpi/
@@ -428,7 +431,6 @@ P: Jordan Crouse
L: linux-geode@lists.infradead.org (moderated for non-subscribers)
W: http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
S: Supported
-F: arch/x86/kernel/geode_32.c
F: drivers/char/hw_random/geode-rng.c
F: drivers/crypto/geode*
F: drivers/video/geode/
@@ -966,6 +968,13 @@ W: http://www.arm.linux.org.uk/
S: Maintained
F: arch/arm/vfp/
+ASC7621 HARDWARE MONITOR DRIVER
+M: George Joseph <george.joseph@fairview5.com>
+L: lm-sensors@lm-sensors.org
+S: Maintained
+F: Documentation/hwmon/asc7621
+F: drivers/hwmon/asc7621.c
+
ASUS ACPI EXTRAS DRIVER
M: Corentin Chary <corentincj@iksaif.net>
M: Karol Kozimor <sziwan@users.sourceforge.net>
@@ -1332,6 +1341,7 @@ BTRFS FILE SYSTEM
M: Chris Mason <chris.mason@oracle.com>
L: linux-btrfs@vger.kernel.org
W: http://btrfs.wiki.kernel.org/
+Q: http://patchwork.kernel.org/project/linux-btrfs/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-unstable.git
S: Maintained
F: Documentation/filesystems/btrfs.txt
@@ -1496,6 +1506,7 @@ M: Steve French <sfrench@samba.org>
L: linux-cifs-client@lists.samba.org (moderated for non-subscribers)
L: samba-technical@lists.samba.org (moderated for non-subscribers)
W: http://linux-cifs.samba.org/
+Q: http://patchwork.ozlabs.org/project/linux-cifs-client/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git
S: Supported
F: Documentation/filesystems/cifs.txt
@@ -1782,6 +1793,7 @@ DEVICE-MAPPER (LVM)
P: Alasdair Kergon
L: dm-devel@redhat.com
W: http://sources.redhat.com/dm
+Q: http://patchwork.kernel.org/project/dm-devel/list/
S: Maintained
F: Documentation/device-mapper/
F: drivers/md/dm*
@@ -2126,6 +2138,7 @@ M: "Theodore Ts'o" <tytso@mit.edu>
M: Andreas Dilger <adilger@sun.com>
L: linux-ext4@vger.kernel.org
W: http://ext4.wiki.kernel.org
+Q: http://patchwork.ozlabs.org/project/linux-ext4/list/
S: Maintained
F: Documentation/filesystems/ext4.txt
F: fs/ext4/
@@ -2502,13 +2515,6 @@ L: linux-parisc@vger.kernel.org
S: Maintained
F: sound/parisc/harmony.*
-HAYES ESP SERIAL DRIVER
-M: "Andrew J. Robinson" <arobinso@nyx.net>
-W: http://www.nyx.net/~arobinso
-S: Maintained
-F: Documentation/serial/hayes-esp.txt
-F: drivers/char/esp.c
-
HEWLETT-PACKARD SMART2 RAID DRIVER
M: Chirag Kantharia <chirag.kantharia@hp.com>
L: iss_storagedev@hp.com
@@ -2717,6 +2723,7 @@ F: drivers/scsi/ips.*
IDE SUBSYSTEM
M: "David S. Miller" <davem@davemloft.net>
L: linux-ide@vger.kernel.org
+Q: http://patchwork.ozlabs.org/project/linux-ide/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide-2.6.git
S: Maintained
F: Documentation/ide/
@@ -2771,6 +2778,7 @@ M: Sean Hefty <sean.hefty@intel.com>
M: Hal Rosenstock <hal.rosenstock@gmail.com>
L: linux-rdma@vger.kernel.org
W: http://www.openib.org/
+Q: http://patchwork.kernel.org/project/linux-rdma/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git
S: Supported
F: Documentation/infiniband/
@@ -2790,6 +2798,7 @@ INPUT (KEYBOARD, MOUSE, JOYSTICK, TOUCHSCREEN) DRIVERS
M: Dmitry Torokhov <dmitry.torokhov@gmail.com>
M: Dmitry Torokhov <dtor@mail.ru>
L: linux-input@vger.kernel.org
+Q: http://patchwork.kernel.org/project/linux-input/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git
S: Maintained
F: drivers/input/
@@ -3046,6 +3055,13 @@ W: http://www.melware.de
S: Maintained
F: drivers/isdn/hardware/eicon/
+IT87 HARDWARE MONITORING DRIVER
+M: Jean Delvare <khali@linux-fr.org>
+L: lm-sensors@lm-sensors.org
+S: Maintained
+F: Documentation/hwmon/it87
+F: drivers/hwmon/it87.c
+
IVTV VIDEO4LINUX DRIVER
M: Andy Walls <awalls@radix.net>
L: ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
@@ -3099,6 +3115,7 @@ F: drivers/hwmon/k8temp.c
KCONFIG
M: Roman Zippel <zippel@linux-m68k.org>
L: linux-kbuild@vger.kernel.org
+Q: http://patchwork.kernel.org/project/linux-kbuild/list/
S: Maintained
F: Documentation/kbuild/kconfig-language.txt
F: scripts/kconfig/
@@ -3312,6 +3329,7 @@ M: Benjamin Herrenschmidt <benh@kernel.crashing.org>
M: Paul Mackerras <paulus@samba.org>
W: http://www.penguinppc.org/
L: linuxppc-dev@ozlabs.org
+Q: http://patchwork.ozlabs.org/project/linuxppc-dev/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git
S: Supported
F: Documentation/powerpc/
@@ -3432,6 +3450,13 @@ S: Maintained
F: Documentation/ldm.txt
F: fs/partitions/ldm.*
+LogFS
+M: Joern Engel <joern@logfs.org>
+L: logfs@logfs.org
+W: logfs.org
+S: Maintained
+F: fs/logfs/
+
LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
M: Eric Moore <Eric.Moore@lsi.com>
M: support@lsi.com
@@ -3568,6 +3593,7 @@ M: Mauro Carvalho Chehab <mchehab@infradead.org>
P: LinuxTV.org Project
L: linux-media@vger.kernel.org
W: http://linuxtv.org
+Q: http://patchwork.kernel.org/project/linux-media/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
S: Maintained
F: Documentation/dvb/
@@ -3603,8 +3629,9 @@ F: mm/memcontrol.c
MEMORY TECHNOLOGY DEVICES (MTD)
M: David Woodhouse <dwmw2@infradead.org>
-W: http://www.linux-mtd.infradead.org/
L: linux-mtd@lists.infradead.org
+W: http://www.linux-mtd.infradead.org/
+Q: http://patchwork.ozlabs.org/project/linux-mtd/list/
T: git git://git.infradead.org/mtd-2.6.git
S: Maintained
F: drivers/mtd/
@@ -3864,6 +3891,7 @@ S: Maintained
NETWORKING [WIRELESS]
M: "John W. Linville" <linville@tuxdriver.com>
L: linux-wireless@vger.kernel.org
+Q: http://patchwork.kernel.org/project/linux-wireless/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git
S: Maintained
F: net/mac80211/
@@ -3956,6 +3984,7 @@ M: Tony Lindgren <tony@atomide.com>
L: linux-omap@vger.kernel.org
W: http://www.muru.com/linux/omap/
W: http://linux.omap.com/
+Q: http://patchwork.kernel.org/project/linux-omap/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap-2.6.git
S: Maintained
F: arch/arm/*omap*/
@@ -4182,6 +4211,7 @@ M: Helge Deller <deller@gmx.de>
M: "James E.J. Bottomley" <jejb@parisc-linux.org>
L: linux-parisc@vger.kernel.org
W: http://www.parisc-linux.org/
+Q: http://patchwork.kernel.org/project/linux-parisc/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kyle/parisc-2.6.git
S: Maintained
F: arch/parisc/
@@ -4224,6 +4254,7 @@ F: Documentation/powerpc/eeh-pci-error-recovery.txt
PCI SUBSYSTEM
M: Jesse Barnes <jbarnes@virtuousgeek.org>
L: linux-pci@vger.kernel.org
+Q: http://patchwork.kernel.org/project/linux-pci/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6.git
S: Supported
F: Documentation/PCI/
@@ -4265,7 +4296,9 @@ M: Ingo Molnar <mingo@elte.hu>
S: Supported
F: kernel/perf_event.c
F: include/linux/perf_event.h
-F: arch/*/*/kernel/perf_event.c
+F: arch/*/kernel/perf_event.c
+F: arch/*/kernel/*/perf_event.c
+F: arch/*/kernel/*/*/perf_event.c
F: arch/*/include/asm/perf_event.h
F: arch/*/lib/perf_event.c
F: arch/*/kernel/perf_callchain.c
@@ -4599,6 +4632,7 @@ F: include/linux/rtc.h
REAL TIME CLOCK (RTC) SUBSYSTEM
M: Alessandro Zummo <a.zummo@towertech.it>
L: rtc-linux@googlegroups.com
+Q: http://patchwork.ozlabs.org/project/rtc-linux/list/
S: Maintained
F: Documentation/rtc.txt
F: drivers/rtc/
@@ -4966,6 +5000,7 @@ F: drivers/*/*/*s3c2410*
TI DAVINCI MACHINE SUPPORT
P: Kevin Hilman
M: davinci-linux-open-source@linux.davincidsp.com
+Q: http://patchwork.kernel.org/project/linux-davinci/list/
S: Supported
F: arch/arm/mach-davinci
@@ -5131,6 +5166,7 @@ F: include/sound/soc*
SPARC + UltraSPARC (sparc/sparc64)
M: "David S. Miller" <davem@davemloft.net>
L: sparclinux@vger.kernel.org
+Q: http://patchwork.ozlabs.org/project/sparclinux/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-next-2.6.git
S: Maintained
@@ -5146,6 +5182,7 @@ SPI SUBSYSTEM
M: David Brownell <dbrownell@users.sourceforge.net>
M: Grant Likely <grant.likely@secretlab.ca>
L: spi-devel-general@lists.sourceforge.net
+Q: http://patchwork.kernel.org/project/spi-devel-general/list/
S: Maintained
F: Documentation/spi/
F: drivers/spi/
@@ -5201,7 +5238,7 @@ F: drivers/net/starfire*
STARMODE RADIO IP (STRIP) PROTOCOL DRIVER
S: Orphan
-F: drivers/net/wireless/strip.c
+F: drivers/staging/strip/strip.c
F: include/linux/if_strip.h
STRADIS MPEG-2 DECODER DRIVER
@@ -5222,6 +5259,7 @@ SUPERH
M: Paul Mundt <lethal@linux-sh.org>
L: linux-sh@vger.kernel.org
W: http://www.linux-sh.org
+Q: http://patchwork.kernel.org/project/linux-sh/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git
S: Supported
F: Documentation/sh/
@@ -5989,7 +6027,7 @@ L: linux-wireless@vger.kernel.org
W: http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/
S: Maintained
F: Documentation/networking/wavelan.txt
-F: drivers/net/wireless/wavelan*
+F: drivers/staging/wavelan/
WD7000 SCSI DRIVER
M: Miroslav Zagorac <zaga@fly.cc.fer.hr>
@@ -6185,6 +6223,7 @@ F: drivers/serial/zs.*
THE REST
M: Linus Torvalds <torvalds@linux-foundation.org>
L: linux-kernel@vger.kernel.org
+Q: http://patchwork.kernel.org/project/LKML/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
S: Buried alive in reporters
F: *
diff --git a/Makefile b/Makefile
index 1b24895212d..08ff02da7ce 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
-SUBLEVEL = 33
-EXTRAVERSION =
+SUBLEVEL = 34
+EXTRAVERSION = -rc1
NAME = Man-Eating Seals of Antiquity
# *DOCUMENTATION*
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index 62619f25132..53c213f70fc 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -361,7 +361,7 @@ osf_procfs_mount(char *dirname, struct procfs_args __user *args, int flags)
SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, char __user *, path,
int, flag, void __user *, data)
{
- int retval = -EINVAL;
+ int retval;
char *name;
name = getname(path);
@@ -379,6 +379,7 @@ SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, char __user *, path,
retval = osf_procfs_mount(name, data, flag);
break;
default:
+ retval = -EINVAL;
printk("osf_mount(%ld, %x)\n", typenr, flag);
}
putname(name);
diff --git a/arch/arm/mach-ep93xx/include/mach/ts72xx.h b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
index 3bd934e9a7f..93107d88ff3 100644
--- a/arch/arm/mach-ep93xx/include/mach/ts72xx.h
+++ b/arch/arm/mach-ep93xx/include/mach/ts72xx.h
@@ -65,6 +65,8 @@
#define TS72XX_RTC_DATA_PHYS_BASE 0x11700000
#define TS72XX_RTC_DATA_SIZE 0x00001000
+#define TS72XX_WDT_CONTROL_PHYS_BASE 0x23800000
+#define TS72XX_WDT_FEED_PHYS_BASE 0x23c00000
#ifndef __ASSEMBLY__
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index 259f7822ba5..fac1ec7a60f 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -166,6 +166,26 @@ static struct platform_device ts72xx_rtc_device = {
.num_resources = 0,
};
+static struct resource ts72xx_wdt_resources[] = {
+ {
+ .start = TS72XX_WDT_CONTROL_PHYS_BASE,
+ .end = TS72XX_WDT_CONTROL_PHYS_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = TS72XX_WDT_FEED_PHYS_BASE,
+ .end = TS72XX_WDT_FEED_PHYS_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device ts72xx_wdt_device = {
+ .name = "ts72xx-wdt",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(ts72xx_wdt_resources),
+ .resource = ts72xx_wdt_resources,
+};
+
static struct ep93xx_eth_data ts72xx_eth_data = {
.phy_id = 1,
};
@@ -175,6 +195,7 @@ static void __init ts72xx_init_machine(void)
ep93xx_init_devices();
ts72xx_register_flash();
platform_device_register(&ts72xx_rtc_device);
+ platform_device_register(&ts72xx_wdt_device);
ep93xx_register_eth(&ts72xx_eth_data, 1);
}
diff --git a/arch/arm/mach-pxa/corgi_ssp.c b/arch/arm/mach-pxa/corgi_ssp.c
index a5ee70735e0..1d9bc118ee3 100644
--- a/arch/arm/mach-pxa/corgi_ssp.c
+++ b/arch/arm/mach-pxa/corgi_ssp.c
@@ -204,7 +204,7 @@ void __init corgi_ssp_set_machinfo(struct corgissp_machinfo *machinfo)
ssp_machinfo = machinfo;
}
-static int __init corgi_ssp_probe(struct platform_device *dev)
+static int __devinit corgi_ssp_probe(struct platform_device *dev)
{
int ret;
diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c
index 67229a1ef55..463d874bb86 100644
--- a/arch/arm/mach-pxa/sharpsl_pm.c
+++ b/arch/arm/mach-pxa/sharpsl_pm.c
@@ -900,7 +900,7 @@ static struct platform_suspend_ops sharpsl_pm_ops = {
};
#endif
-static int __init sharpsl_pm_probe(struct platform_device *pdev)
+static int __devinit sharpsl_pm_probe(struct platform_device *pdev)
{
int ret;
diff --git a/arch/arm/mach-s3c2410/h1940-bluetooth.c b/arch/arm/mach-s3c2410/h1940-bluetooth.c
index b7d1f8d27bc..a3f3c7b1ca3 100644
--- a/arch/arm/mach-s3c2410/h1940-bluetooth.c
+++ b/arch/arm/mach-s3c2410/h1940-bluetooth.c
@@ -56,7 +56,7 @@ static const struct rfkill_ops h1940bt_rfkill_ops = {
.set_block = h1940bt_set_block,
};
-static int __init h1940bt_probe(struct platform_device *pdev)
+static int __devinit h1940bt_probe(struct platform_device *pdev)
{
struct rfkill *rfk;
int ret = 0;
diff --git a/arch/arm/mach-sa1100/jornada720_ssp.c b/arch/arm/mach-sa1100/jornada720_ssp.c
index 506a5e5a9ad..9b6dee5d16d 100644
--- a/arch/arm/mach-sa1100/jornada720_ssp.c
+++ b/arch/arm/mach-sa1100/jornada720_ssp.c
@@ -130,7 +130,7 @@ void jornada_ssp_end(void)
};
EXPORT_SYMBOL(jornada_ssp_end);
-static int __init jornada_ssp_probe(struct platform_device *dev)
+static int __devinit jornada_ssp_probe(struct platform_device *dev)
{
int ret;
diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 7adac388a77..059eac6abda 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -20,6 +20,12 @@ config RWSEM_GENERIC_SPINLOCK
config RWSEM_XCHGADD_ALGORITHM
bool
+config GENERIC_TIME
+ def_bool y
+
+config ARCH_USES_GETTIMEOFFSET
+ def_bool y
+
config GENERIC_IOMAP
bool
default y
diff --git a/arch/cris/arch-v32/drivers/cryptocop.c b/arch/cris/arch-v32/drivers/cryptocop.c
index fd529a0ec75..b70fb34939d 100644
--- a/arch/cris/arch-v32/drivers/cryptocop.c
+++ b/arch/cris/arch-v32/drivers/cryptocop.c
@@ -628,9 +628,9 @@ static int create_output_descriptors(struct cryptocop_operation *operation, int
cdesc->dma_descr->buf = (char*)virt_to_phys(operation->tfrm_op.indata[*iniov_ix].iov_base + *iniov_offset);
cdesc->dma_descr->after = cdesc->dma_descr->buf + dlength;
+ assert(desc_len >= dlength);
desc_len -= dlength;
*iniov_offset += dlength;
- assert(desc_len >= 0);
if (*iniov_offset >= operation->tfrm_op.indata[*iniov_ix].iov_len) {
*iniov_offset = 0;
++(*iniov_ix);
diff --git a/arch/cris/arch-v32/mach-fs/arbiter.c b/arch/cris/arch-v32/mach-fs/arbiter.c
index 84d31bd7b69..82ef293c4c8 100644
--- a/arch/cris/arch-v32/mach-fs/arbiter.c
+++ b/arch/cris/arch-v32/mach-fs/arbiter.c
@@ -332,7 +332,7 @@ int crisv32_arbiter_unwatch(int id)
if (id == 0)
intr_mask.bp0 = regk_marb_no;
else if (id == 1)
- intr_mask.bp2 = regk_marb_no;
+ intr_mask.bp1 = regk_marb_no;
else if (id == 2)
intr_mask.bp2 = regk_marb_no;
else if (id == 3)
diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c
index 074fe7dea96..a05dd31f3ef 100644
--- a/arch/cris/kernel/time.c
+++ b/arch/cris/kernel/time.c
@@ -42,75 +42,11 @@ unsigned long loops_per_usec;
extern unsigned long do_slow_gettimeoffset(void);
static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
-/*
- * This version of gettimeofday has near microsecond resolution.
- *
- * Note: Division is quite slow on CRIS and do_gettimeofday is called
- * rather often. Maybe we should do some kind of approximation here
- * (a naive approximation would be to divide by 1024).
- */
-void do_gettimeofday(struct timeval *tv)
-{
- unsigned long flags;
- signed long usec, sec;
- local_irq_save(flags);
- usec = do_gettimeoffset();
-
- /*
- * If time_adjust is negative then NTP is slowing the clock
- * so make sure not to go into next possible interval.
- * Better to lose some accuracy than have time go backwards..
- */
- if (unlikely(time_adjust < 0) && usec > tickadj)
- usec = tickadj;
-
- sec = xtime.tv_sec;
- usec += xtime.tv_nsec / 1000;
- local_irq_restore(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)
+u32 arch_gettimeoffset(void)
{
- 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 -= do_gettimeoffset() * 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;
+ return do_gettimeoffset() * 1000;
}
-EXPORT_SYMBOL(do_settimeofday);
-
-
/*
* BUG: This routine does not handle hour overflow properly; it just
* sets the minutes. Usually you'll only notice that after reboot!
diff --git a/arch/frv/include/asm/pci.h b/arch/frv/include/asm/pci.h
index 492b5c4dfed..8c7260a3cd4 100644
--- a/arch/frv/include/asm/pci.h
+++ b/arch/frv/include/asm/pci.h
@@ -68,41 +68,4 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
#define PCIBIOS_MIN_IO 0x100
#define PCIBIOS_MIN_MEM 0x00010000
-/* Make physical memory consistent for a single
- * streaming mode DMA translation after a transfer.
- *
- * If you perform a pci_map_single() but wish to interrogate the
- * buffer using the cpu, yet do not wish to teardown the PCI dma
- * mapping, you must call this function before doing so. At the
- * next point you give the PCI dma address back to the card, the
- * device again owns the buffer.
- */
-static inline void pci_dma_sync_single(struct pci_dev *hwdev,
- dma_addr_t dma_handle,
- size_t size, int direction)
-{
- BUG_ON(direction == PCI_DMA_NONE);
-
- frv_cache_wback_inv((unsigned long)bus_to_virt(dma_handle),
- (unsigned long)bus_to_virt(dma_handle) + size);
-}
-
-/* Make physical memory consistent for a set of streaming
- * mode DMA translations after a transfer.
- *
- * The same as pci_dma_sync_single but for a scatter-gather list,
- * same rules and usage.
- */
-static inline void pci_dma_sync_sg(struct pci_dev *hwdev,
- struct scatterlist *sg,
- int nelems, int direction)
-{
- int i;
- BUG_ON(direction == PCI_DMA_NONE);
-
- for (i = 0; i < nelems; i++)
- frv_cache_wback_inv(sg_dma_address(&sg[i]),
- sg_dma_address(&sg[i])+sg_dma_len(&sg[i]));
-}
-
#endif /* _ASM_FRV_PCI_H */
diff --git a/arch/ia64/include/asm/elf.h b/arch/ia64/include/asm/elf.h
index 4c41656ede8..b5298eb09ad 100644
--- a/arch/ia64/include/asm/elf.h
+++ b/arch/ia64/include/asm/elf.h
@@ -219,54 +219,6 @@ do { \
NEW_AUX_ENT(AT_SYSINFO_EHDR, (unsigned long) GATE_EHDR); \
} while (0)
-
-/*
- * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
- * extra segments containing the gate DSO contents. Dumping its
- * contents makes post-mortem fully interpretable later without matching up
- * the same kernel and hardware config to see what PC values meant.
- * Dumping its extra ELF program headers includes all the other information
- * a debugger needs to easily find how the gate DSO was being used.
- */
-#define ELF_CORE_EXTRA_PHDRS (GATE_EHDR->e_phnum)
-#define ELF_CORE_WRITE_EXTRA_PHDRS \
-do { \
- const struct elf_phdr *const gate_phdrs = \
- (const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff); \
- int i; \
- Elf64_Off ofs = 0; \
- for (i = 0; i < GATE_EHDR->e_phnum; ++i) { \
- struct elf_phdr phdr = gate_phdrs[i]; \
- if (phdr.p_type == PT_LOAD) { \
- phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); \
- phdr.p_filesz = phdr.p_memsz; \
- if (ofs == 0) { \
- ofs = phdr.p_offset = offset; \
- offset += phdr.p_filesz; \
- } \
- else \
- phdr.p_offset = ofs; \
- } \
- else \
- phdr.p_offset += ofs; \
- phdr.p_paddr = 0; /* match other core phdrs */ \
- DUMP_WRITE(&phdr, sizeof(phdr)); \
- } \
-} while (0)
-#define ELF_CORE_WRITE_EXTRA_DATA \
-do { \
- const struct elf_phdr *const gate_phdrs = \
- (const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff); \
- int i; \
- for (i = 0; i < GATE_EHDR->e_phnum; ++i) { \
- if (gate_phdrs[i].p_type == PT_LOAD) { \
- DUMP_WRITE((void *) gate_phdrs[i].p_vaddr, \
- PAGE_ALIGN(gate_phdrs[i].p_memsz)); \
- break; \
- } \
- } \
-} while (0)
-
/*
* format for entries in the Global Offset Table
*/
diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile
index 4138282aefa..db10b1e378b 100644
--- a/arch/ia64/kernel/Makefile
+++ b/arch/ia64/kernel/Makefile
@@ -45,6 +45,8 @@ endif
obj-$(CONFIG_DMAR) += pci-dma.o
obj-$(CONFIG_SWIOTLB) += pci-swiotlb.o
+obj-$(CONFIG_BINFMT_ELF) += elfcore.o
+
# fp_emulate() expects f2-f5,f16-f31 to contain the user-level state.
CFLAGS_traps.o += -mfixed-range=f2-f5,f16-f31
diff --git a/arch/ia64/kernel/elfcore.c b/arch/ia64/kernel/elfcore.c
new file mode 100644
index 00000000000..bac1639bc32
--- /dev/null
+++ b/arch/ia64/kernel/elfcore.c
@@ -0,0 +1,80 @@
+#include <linux/elf.h>
+#include <linux/coredump.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+
+#include <asm/elf.h>
+
+
+Elf64_Half elf_core_extra_phdrs(void)
+{
+ return GATE_EHDR->e_phnum;
+}
+
+int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
+ unsigned long limit)
+{
+ const struct elf_phdr *const gate_phdrs =
+ (const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);
+ int i;
+ Elf64_Off ofs = 0;
+
+ for (i = 0; i < GATE_EHDR->e_phnum; ++i) {
+ struct elf_phdr phdr = gate_phdrs[i];
+
+ if (phdr.p_type == PT_LOAD) {
+ phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz);
+ phdr.p_filesz = phdr.p_memsz;
+ if (ofs == 0) {
+ ofs = phdr.p_offset = offset;
+ offset += phdr.p_filesz;
+ } else {
+ phdr.p_offset = ofs;
+ }
+ } else {
+ phdr.p_offset += ofs;
+ }
+ phdr.p_paddr = 0; /* match other core phdrs */
+ *size += sizeof(phdr);
+ if (*size > limit || !dump_write(file, &phdr, sizeof(phdr)))
+ return 0;
+ }
+ return 1;
+}
+
+int elf_core_write_extra_data(struct file *file, size_t *size,
+ unsigned long limit)
+{
+ const struct elf_phdr *const gate_phdrs =
+ (const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);
+ int i;
+
+ for (i = 0; i < GATE_EHDR->e_phnum; ++i) {
+ if (gate_phdrs[i].p_type == PT_LOAD) {
+ void *addr = (void *)gate_phdrs[i].p_vaddr;
+ size_t memsz = PAGE_ALIGN(gate_phdrs[i].p_memsz);
+
+ *size += memsz;
+ if (*size > limit || !dump_write(file, addr, memsz))
+ return 0;
+ break;
+ }
+ }
+ return 1;
+}
+
+size_t elf_core_extra_data_size(void)
+{
+ const struct elf_phdr *const gate_phdrs =
+ (const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff);
+ int i;
+ size_t size = 0;
+
+ for (i = 0; i < GATE_EHDR->e_phnum; ++i) {
+ if (gate_phdrs[i].p_type == PT_LOAD) {
+ size += PAGE_ALIGN(gate_phdrs[i].p_memsz);
+ break;
+ }
+ }
+ return size;
+}
diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
index b81e46b1629..703062c44fb 100644
--- a/arch/ia64/kernel/perfmon.c
+++ b/arch/ia64/kernel/perfmon.c
@@ -2315,6 +2315,7 @@ pfm_smpl_buffer_alloc(struct task_struct *task, struct file *filp, pfm_context_t
DPRINT(("Cannot allocate vma\n"));
goto error_kmem;
}
+ INIT_LIST_HEAD(&vma->anon_vma_chain);
/*
* partially initialize the vma for the sampling buffer
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index 8f060352e12..b3a5818088d 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -282,7 +282,7 @@ static ssize_t cache_show(struct kobject * kobj, struct attribute * attr, char *
return ret;
}
-static struct sysfs_ops cache_sysfs_ops = {
+static const struct sysfs_ops cache_sysfs_ops = {
.show = cache_show
};
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
index ca3335ea56c..ed41759efca 100644
--- a/arch/ia64/mm/init.c
+++ b/arch/ia64/mm/init.c
@@ -117,6 +117,7 @@ ia64_init_addr_space (void)
*/
vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
if (vma) {
+ INIT_LIST_HEAD(&vma->anon_vma_chain);
vma->vm_mm = current->mm;
vma->vm_start = current->thread.rbs_bot & PAGE_MASK;
vma->vm_end = vma->vm_start + PAGE_SIZE;
@@ -135,6 +136,7 @@ ia64_init_addr_space (void)
if (!(current->personality & MMAP_PAGE_ZERO)) {
vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);
if (vma) {
+ INIT_LIST_HEAD(&vma->anon_vma_chain);
vma->vm_mm = current->mm;
vma->vm_end = PAGE_SIZE;
vma->vm_page_prot = __pgprot(pgprot_val(PAGE_READONLY) | _PAGE_MA_NAT);
diff --git a/arch/mips/txx9/generic/7segled.c b/arch/mips/txx9/generic/7segled.c
index 727ab21b661..7f8416f8622 100644
--- a/arch/mips/txx9/generic/7segled.c
+++ b/arch/mips/txx9/generic/7segled.c
@@ -58,13 +58,16 @@ static ssize_t raw_store(struct sys_device *dev,
static SYSDEV_ATTR(ascii, 0200, NULL, ascii_store);
static SYSDEV_ATTR(raw, 0200, NULL, raw_store);
-static ssize_t map_seg7_show(struct sysdev_class *class, char *buf)
+static ssize_t map_seg7_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
memcpy(buf, &txx9_seg7map, sizeof(txx9_seg7map));
return sizeof(txx9_seg7map);
}
static ssize_t map_seg7_store(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
const char *buf, size_t size)
{
if (size != sizeof(txx9_seg7map))
diff --git a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug
index bc989e522a0..7305ac8f7f5 100644
--- a/arch/parisc/Kconfig.debug
+++ b/arch/parisc/Kconfig.debug
@@ -12,4 +12,18 @@ config DEBUG_RODATA
portion of the kernel code won't be covered by a TLB anymore.
If in doubt, say "N".
+config DEBUG_STRICT_USER_COPY_CHECKS
+ bool "Strict copy size checks"
+ depends on DEBUG_KERNEL && !TRACE_BRANCH_PROFILING
+ ---help---
+ Enabling this option turns a certain set of sanity checks for user
+ copy operations into compile time failures.
+
+ The copy_from_user() etc checks are there to help test if there
+ are sufficient security checks on the length argument of
+ the copy operation, by having gcc prove that the argument is
+ within bounds.
+
+ If unsure, or if you run an older (pre 4.4) gcc, say N.
+
endmenu
diff --git a/arch/parisc/include/asm/param.h b/arch/parisc/include/asm/param.h
index 32e03d87785..965d4542797 100644
--- a/arch/parisc/include/asm/param.h
+++ b/arch/parisc/include/asm/param.h
@@ -1,22 +1 @@
-#ifndef _ASMPARISC_PARAM_H
-#define _ASMPARISC_PARAM_H
-
-#ifdef __KERNEL__
-#define HZ CONFIG_HZ
-#define USER_HZ 100 /* some user API use "ticks" */
-#define CLOCKS_PER_SEC (USER_HZ) /* like times() */
-#endif
-
-#ifndef HZ
-#define HZ 100
-#endif
-
-#define EXEC_PAGESIZE 4096
-
-#ifndef NOGROUP
-#define NOGROUP (-1)
-#endif
-
-#define MAXHOSTNAMELEN 64 /* max length of hostname */
-
-#endif
+#include <asm-generic/param.h>
diff --git a/arch/parisc/include/asm/system.h b/arch/parisc/include/asm/system.h
index d91357bca5b..4653c77bf9d 100644
--- a/arch/parisc/include/asm/system.h
+++ b/arch/parisc/include/asm/system.h
@@ -160,7 +160,7 @@ static inline void set_eiem(unsigned long val)
ldcd). */
#define __PA_LDCW_ALIGNMENT 4
-#define __ldcw_align(a) ((volatile unsigned int *)a)
+#define __ldcw_align(a) (&(a)->slock)
#define __LDCW "ldcw,co"
#endif /*!CONFIG_PA20*/
diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h
index 7cf799d70b4..ff4cf9dab8d 100644
--- a/arch/parisc/include/asm/uaccess.h
+++ b/arch/parisc/include/asm/uaccess.h
@@ -7,6 +7,7 @@
#include <asm/page.h>
#include <asm/system.h>
#include <asm/cache.h>
+#include <asm/errno.h>
#include <asm-generic/uaccess-unaligned.h>
#define VERIFY_READ 0
@@ -234,13 +235,35 @@ extern long lstrnlen_user(const char __user *,long);
unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len);
#define __copy_to_user copy_to_user
-unsigned long copy_from_user(void *dst, const void __user *src, unsigned long len);
-#define __copy_from_user copy_from_user
+unsigned long __copy_from_user(void *dst, const void __user *src, unsigned long len);
unsigned long copy_in_user(void __user *dst, const void __user *src, unsigned long len);
#define __copy_in_user copy_in_user
#define __copy_to_user_inatomic __copy_to_user
#define __copy_from_user_inatomic __copy_from_user
+extern void copy_from_user_overflow(void)
+#ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS
+ __compiletime_error("copy_from_user() buffer size is not provably correct")
+#else
+ __compiletime_warning("copy_from_user() buffer size is not provably correct")
+#endif
+;
+
+static inline unsigned long __must_check copy_from_user(void *to,
+ const void __user *from,
+ unsigned long n)
+{
+ int sz = __compiletime_object_size(to);
+ int ret = -EFAULT;
+
+ if (likely(sz == -1 || !__builtin_constant_p(n) || sz >= n))
+ ret = __copy_from_user(to, from, n);
+ else
+ copy_from_user_overflow();
+
+ return ret;
+}
+
struct pt_regs;
int fixup_exception(struct pt_regs *regs);
diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h
index cda158318c6..1ce7d2851d9 100644
--- a/arch/parisc/include/asm/unistd.h
+++ b/arch/parisc/include/asm/unistd.h
@@ -811,8 +811,10 @@
#define __NR_pwritev (__NR_Linux + 316)
#define __NR_rt_tgsigqueueinfo (__NR_Linux + 317)
#define __NR_perf_event_open (__NR_Linux + 318)
+#define __NR_recvmmsg (__NR_Linux + 319)
+#define __NR_accept4 (__NR_Linux + 320)
-#define __NR_Linux_syscalls (__NR_perf_event_open + 1)
+#define __NR_Linux_syscalls (__NR_accept4 + 1)
#define __IGNORE_select /* newselect */
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c
index 1054baa2fc6..d054f3da3ff 100644
--- a/arch/parisc/kernel/cache.c
+++ b/arch/parisc/kernel/cache.c
@@ -171,14 +171,14 @@ parisc_cache_init(void)
cache_info.ic_conf.cc_cst,
cache_info.ic_conf.cc_hv);
- printk("D-TLB conf: sh %d page %d cst %d aid %d pad1 %d \n",
+ printk("D-TLB conf: sh %d page %d cst %d aid %d pad1 %d\n",
cache_info.dt_conf.tc_sh,
cache_info.dt_conf.tc_page,
cache_info.dt_conf.tc_cst,
cache_info.dt_conf.tc_aid,
cache_info.dt_conf.tc_pad1);
- printk("I-TLB conf: sh %d page %d cst %d aid %d pad1 %d \n",
+ printk("I-TLB conf: sh %d page %d cst %d aid %d pad1 %d\n",
cache_info.it_conf.tc_sh,
cache_info.it_conf.tc_page,
cache_info.it_conf.tc_cst,
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 01c4fcf8f48..de5f6dab48b 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -417,6 +417,8 @@
ENTRY_COMP(pwritev)
ENTRY_COMP(rt_tgsigqueueinfo)
ENTRY_SAME(perf_event_open)
+ ENTRY_COMP(recvmmsg)
+ ENTRY_SAME(accept4) /* 320 */
/* Nothing yet */
diff --git a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c
index a79c6f9e7e2..05511ccb61d 100644
--- a/arch/parisc/kernel/time.c
+++ b/arch/parisc/kernel/time.c
@@ -250,9 +250,21 @@ static int __init rtc_init(void)
}
module_init(rtc_init);
-void __init time_init(void)
+void read_persistent_clock(struct timespec *ts)
{
static struct pdc_tod tod_data;
+ if (pdc_tod_read(&tod_data) == 0) {
+ ts->tv_sec = tod_data.tod_sec;
+ ts->tv_nsec = tod_data.tod_usec * 1000;
+ } else {
+ printk(KERN_ERR "Error reading tod clock\n");
+ ts->tv_sec = 0;
+ ts->tv_nsec = 0;
+ }
+}
+
+void __init time_init(void)
+{
unsigned long current_cr16_khz;
clocktick = (100 * PAGE0->mem_10msec) / HZ;
@@ -264,19 +276,4 @@ void __init time_init(void)
clocksource_cr16.mult = clocksource_khz2mult(current_cr16_khz,
clocksource_cr16.shift);
clocksource_register(&clocksource_cr16);
-
- if (pdc_tod_read(&tod_data) == 0) {
- unsigned long flags;
-
- write_seqlock_irqsave(&xtime_lock, flags);
- xtime.tv_sec = tod_data.tod_sec;
- xtime.tv_nsec = tod_data.tod_usec * 1000;
- set_normalized_timespec(&wall_to_monotonic,
- -xtime.tv_sec, -xtime.tv_nsec);
- write_sequnlock_irqrestore(&xtime_lock, flags);
- } else {
- printk(KERN_ERR "Error reading tod clock\n");
- xtime.tv_sec = 0;
- xtime.tv_nsec = 0;
- }
}
diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c
index e6f4b7a4b7e..92d977bb5ea 100644
--- a/arch/parisc/kernel/unaligned.c
+++ b/arch/parisc/kernel/unaligned.c
@@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/signal.h>
+#include <linux/ratelimit.h>
#include <asm/uaccess.h>
/* #define DEBUG_UNALIGNED 1 */
@@ -446,8 +447,7 @@ static int emulate_std(struct pt_regs *regs, int frreg, int flop)
void handle_unaligned(struct pt_regs *regs)
{
- static unsigned long unaligned_count = 0;
- static unsigned long last_time = 0;
+ static DEFINE_RATELIMIT_STATE(ratelimit, 5 * HZ, 5);
unsigned long newbase = R1(regs->iir)?regs->gr[R1(regs->iir)]:0;
int modify = 0;
int ret = ERR_NOTHANDLED;
@@ -460,14 +460,8 @@ void handle_unaligned(struct pt_regs *regs)
goto force_sigbus;
}
- if (unaligned_count > 5 &&
- time_after(jiffies, last_time + 5 * HZ)) {
- unaligned_count = 0;
- last_time = jiffies;
- }
-
- if (!(current->thread.flags & PARISC_UAC_NOPRINT)
- && ++unaligned_count < 5) {
+ if (!(current->thread.flags & PARISC_UAC_NOPRINT) &&
+ __ratelimit(&ratelimit)) {
char buf[256];
sprintf(buf, "%s(%d): unaligned access to 0x" RFMT " at ip=0x" RFMT "\n",
current->comm, task_pid_nr(current), regs->ior, regs->iaoq[0]);
diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c
index abf41f4632a..1dbca5c31b3 100644
--- a/arch/parisc/lib/memcpy.c
+++ b/arch/parisc/lib/memcpy.c
@@ -475,7 +475,8 @@ unsigned long copy_to_user(void __user *dst, const void *src, unsigned long len)
return pa_memcpy((void __force *)dst, src, len);
}
-unsigned long copy_from_user(void *dst, const void __user *src, unsigned long len)
+EXPORT_SYMBOL(__copy_from_user);
+unsigned long __copy_from_user(void *dst, const void __user *src, unsigned long len)
{
mtsp(get_user_space(), 1);
mtsp(get_kernel_space(), 2);
diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c
index bb37b1d19a5..01fe9ce2837 100644
--- a/arch/powerpc/kernel/cacheinfo.c
+++ b/arch/powerpc/kernel/cacheinfo.c
@@ -642,7 +642,7 @@ static struct kobj_attribute *cache_index_opt_attrs[] = {
&cache_assoc_attr,
};
-static struct sysfs_ops cache_index_ops = {
+static const struct sysfs_ops cache_index_ops = {
.show = cache_index_show,
};
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index b037d95eead..64c00227b99 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -451,7 +451,7 @@ static int __cpuinit numa_setup_cpu(unsigned long lcpu)
nid = of_node_to_nid_single(cpu);
if (nid < 0 || !node_online(nid))
- nid = any_online_node(NODE_MASK_ALL);
+ nid = first_online_node;
out:
map_cpu_to_node(lcpu, nid);
@@ -1114,7 +1114,7 @@ int hot_add_scn_to_nid(unsigned long scn_addr)
int nid, found = 0;
if (!numa_enabled || (min_common_depth < 0))
- return any_online_node(NODE_MASK_ALL);
+ return first_online_node;
memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
if (memory) {
@@ -1125,7 +1125,7 @@ int hot_add_scn_to_nid(unsigned long scn_addr)
}
if (nid < 0 || !node_online(nid))
- nid = any_online_node(NODE_MASK_ALL);
+ nid = first_online_node;
if (NODE_DATA(nid)->node_spanned_pages)
return nid;
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
index 6f8ebe1085b..072b948b2e2 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
@@ -553,7 +553,7 @@ static ssize_t mpc52xx_wdt_write(struct file *file, const char __user *data,
return 0;
}
-static struct watchdog_info mpc5200_wdt_info = {
+static const struct watchdog_info mpc5200_wdt_info = {
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
.identity = WDT_IDENTITY,
};
diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h
index c666bfe5e98..9b04b1102bb 100644
--- a/arch/s390/include/asm/qdio.h
+++ b/arch/s390/include/asm/qdio.h
@@ -321,11 +321,6 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
#define QDIO_ERROR_ACTIVATE_CHECK_CONDITION 0x40
#define QDIO_ERROR_SLSB_STATE 0x80
-/* for qdio_initialize */
-#define QDIO_INBOUND_0COPY_SBALS 0x01
-#define QDIO_OUTBOUND_0COPY_SBALS 0x02
-#define QDIO_USE_OUTBOUND_PCIS 0x04
-
/* for qdio_cleanup */
#define QDIO_FLAG_CLEANUP_USING_CLEAR 0x01
#define QDIO_FLAG_CLEANUP_USING_HALT 0x02
@@ -344,7 +339,6 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
* @input_handler: handler to be called for input queues
* @output_handler: handler to be called for output queues
* @int_parm: interruption parameter
- * @flags: initialization flags
* @input_sbal_addr_array: address of no_input_qs * 128 pointers
* @output_sbal_addr_array: address of no_output_qs * 128 pointers
*/
@@ -361,7 +355,6 @@ struct qdio_initialize {
qdio_handler_t *input_handler;
qdio_handler_t *output_handler;
unsigned long int_parm;
- unsigned long flags;
void **input_sbal_addr_array;
void **output_sbal_addr_array;
};
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 8b10127c00a..29f65bce55e 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -1020,7 +1020,9 @@ out:
return rc;
}
-static ssize_t __ref rescan_store(struct sysdev_class *class, const char *buf,
+static ssize_t __ref rescan_store(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ const char *buf,
size_t count)
{
int rc;
@@ -1031,7 +1033,9 @@ static ssize_t __ref rescan_store(struct sysdev_class *class, const char *buf,
static SYSDEV_CLASS_ATTR(rescan, 0200, NULL, rescan_store);
#endif /* CONFIG_HOTPLUG_CPU */
-static ssize_t dispatching_show(struct sysdev_class *class, char *buf)
+static ssize_t dispatching_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
ssize_t count;
@@ -1041,7 +1045,9 @@ static ssize_t dispatching_show(struct sysdev_class *class, char *buf)
return count;
}
-static ssize_t dispatching_store(struct sysdev_class *dev, const char *buf,
+static ssize_t dispatching_store(struct sysdev_class *dev,
+ struct sysdev_class_attribute *attr,
+ const char *buf,
size_t count)
{
int val, rc;
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index a8f93f1705a..aa2483e460f 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -73,15 +73,15 @@ unsigned long long monotonic_clock(void)
}
EXPORT_SYMBOL(monotonic_clock);
-void tod_to_timeval(__u64 todval, struct timespec *xtime)
+void tod_to_timeval(__u64 todval, struct timespec *xt)
{
unsigned long long sec;
sec = todval >> 12;
do_div(sec, 1000000);
- xtime->tv_sec = sec;
+ xt->tv_sec = sec;
todval -= (sec * 1000000) << 12;
- xtime->tv_nsec = ((todval * 1000) >> 12);
+ xt->tv_nsec = ((todval * 1000) >> 12);
}
EXPORT_SYMBOL(tod_to_timeval);
@@ -216,8 +216,8 @@ void update_vsyscall(struct timespec *wall_time, struct clocksource *clock,
++vdso_data->tb_update_count;
smp_wmb();
vdso_data->xtime_tod_stamp = clock->cycle_last;
- vdso_data->xtime_clock_sec = xtime.tv_sec;
- vdso_data->xtime_clock_nsec = xtime.tv_nsec;
+ vdso_data->xtime_clock_sec = wall_time->tv_sec;
+ vdso_data->xtime_clock_nsec = wall_time->tv_nsec;
vdso_data->wtom_clock_sec = wall_to_monotonic.tv_sec;
vdso_data->wtom_clock_nsec = wall_to_monotonic.tv_nsec;
smp_wmb();
@@ -1116,14 +1116,18 @@ static struct sys_device etr_port1_dev = {
/*
* ETR class attributes
*/
-static ssize_t etr_stepping_port_show(struct sysdev_class *class, char *buf)
+static ssize_t etr_stepping_port_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
return sprintf(buf, "%i\n", etr_port0.esw.p);
}
static SYSDEV_CLASS_ATTR(stepping_port, 0400, etr_stepping_port_show, NULL);
-static ssize_t etr_stepping_mode_show(struct sysdev_class *class, char *buf)
+static ssize_t etr_stepping_mode_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
char *mode_str;
@@ -1584,7 +1588,9 @@ static struct sysdev_class stp_sysclass = {
.name = "stp",
};
-static ssize_t stp_ctn_id_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_ctn_id_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
if (!stp_online)
return -ENODATA;
@@ -1594,7 +1600,9 @@ static ssize_t stp_ctn_id_show(struct sysdev_class *class, char *buf)
static SYSDEV_CLASS_ATTR(ctn_id, 0400, stp_ctn_id_show, NULL);
-static ssize_t stp_ctn_type_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_ctn_type_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
if (!stp_online)
return -ENODATA;
@@ -1603,7 +1611,9 @@ static ssize_t stp_ctn_type_show(struct sysdev_class *class, char *buf)
static SYSDEV_CLASS_ATTR(ctn_type, 0400, stp_ctn_type_show, NULL);
-static ssize_t stp_dst_offset_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_dst_offset_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
if (!stp_online || !(stp_info.vbits & 0x2000))
return -ENODATA;
@@ -1612,7 +1622,9 @@ static ssize_t stp_dst_offset_show(struct sysdev_class *class, char *buf)
static SYSDEV_CLASS_ATTR(dst_offset, 0400, stp_dst_offset_show, NULL);
-static ssize_t stp_leap_seconds_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_leap_seconds_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
if (!stp_online || !(stp_info.vbits & 0x8000))
return -ENODATA;
@@ -1621,7 +1633,9 @@ static ssize_t stp_leap_seconds_show(struct sysdev_class *class, char *buf)
static SYSDEV_CLASS_ATTR(leap_seconds, 0400, stp_leap_seconds_show, NULL);
-static ssize_t stp_stratum_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_stratum_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
if (!stp_online)
return -ENODATA;
@@ -1630,7 +1644,9 @@ static ssize_t stp_stratum_show(struct sysdev_class *class, char *buf)
static SYSDEV_CLASS_ATTR(stratum, 0400, stp_stratum_show, NULL);
-static ssize_t stp_time_offset_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_time_offset_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
if (!stp_online || !(stp_info.vbits & 0x0800))
return -ENODATA;
@@ -1639,7 +1655,9 @@ static ssize_t stp_time_offset_show(struct sysdev_class *class, char *buf)
static SYSDEV_CLASS_ATTR(time_offset, 0400, stp_time_offset_show, NULL);
-static ssize_t stp_time_zone_offset_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_time_zone_offset_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
if (!stp_online || !(stp_info.vbits & 0x4000))
return -ENODATA;
@@ -1649,7 +1667,9 @@ static ssize_t stp_time_zone_offset_show(struct sysdev_class *class, char *buf)
static SYSDEV_CLASS_ATTR(time_zone_offset, 0400,
stp_time_zone_offset_show, NULL);
-static ssize_t stp_timing_mode_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_timing_mode_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
if (!stp_online)
return -ENODATA;
@@ -1658,7 +1678,9 @@ static ssize_t stp_timing_mode_show(struct sysdev_class *class, char *buf)
static SYSDEV_CLASS_ATTR(timing_mode, 0400, stp_timing_mode_show, NULL);
-static ssize_t stp_timing_state_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_timing_state_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
if (!stp_online)
return -ENODATA;
@@ -1667,12 +1689,15 @@ static ssize_t stp_timing_state_show(struct sysdev_class *class, char *buf)
static SYSDEV_CLASS_ATTR(timing_state, 0400, stp_timing_state_show, NULL);
-static ssize_t stp_online_show(struct sysdev_class *class, char *buf)
+static ssize_t stp_online_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
return sprintf(buf, "%i\n", stp_online);
}
static ssize_t stp_online_store(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
const char *buf, size_t count)
{
unsigned int value;
diff --git a/arch/s390/lib/Makefile b/arch/s390/lib/Makefile
index cd54a1c352a..761ab8b56af 100644
--- a/arch/s390/lib/Makefile
+++ b/arch/s390/lib/Makefile
@@ -2,7 +2,8 @@
# Makefile for s390-specific library files..
#
-lib-y += delay.o string.o uaccess_std.o uaccess_pt.o usercopy.o
+lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
+obj-y += usercopy.o
obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o
lib-$(CONFIG_64BIT) += uaccess_mvcos.o
lib-$(CONFIG_SMP) += spinlock.o
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index 76a3637b88e..f16bd04e39e 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -374,7 +374,7 @@ static struct ctl_table cmm_dir_table[] = {
#ifdef CONFIG_CMM_IUCV
#define SMSG_PREFIX "CMM"
static void
-cmm_smsg_target(char *from, char *msg)
+cmm_smsg_target(const char *from, char *msg)
{
long nr, seconds;
diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c
index be300aaca6f..7da0fc94a01 100644
--- a/arch/sh/boards/mach-migor/setup.c
+++ b/arch/sh/boards/mach-migor/setup.c
@@ -419,6 +419,9 @@ static struct i2c_board_info migor_i2c_devices[] = {
I2C_BOARD_INFO("migor_ts", 0x51),
.irq = 38, /* IRQ6 */
},
+ {
+ I2C_BOARD_INFO("wm8978", 0x1a),
+ },
};
static struct i2c_board_info migor_i2c_camera[] = {
@@ -619,6 +622,19 @@ static int __init migor_devices_setup(void)
platform_resource_setup_memory(&migor_ceu_device, "ceu", 4 << 20);
+ /* SIU: Port B */
+ gpio_request(GPIO_FN_SIUBOLR, NULL);
+ gpio_request(GPIO_FN_SIUBOBT, NULL);
+ gpio_request(GPIO_FN_SIUBISLD, NULL);
+ gpio_request(GPIO_FN_SIUBOSLD, NULL);
+ gpio_request(GPIO_FN_SIUMCKB, NULL);
+
+ /*
+ * The original driver sets SIUB OLR/OBT, ILR/IBT, and SIUA OLR/OBT to
+ * output. Need only SIUB, set to output for master mode (table 34.2)
+ */
+ __raw_writew(__raw_readw(PORT_MSELCRA) | 1, PORT_MSELCRA);
+
i2c_register_board_info(0, migor_i2c_devices,
ARRAY_SIZE(migor_i2c_devices));
diff --git a/arch/sh/boot/compressed/cache.c b/arch/sh/boot/compressed/cache.c
index e27fc74f228..d0b77b68a4d 100644
--- a/arch/sh/boot/compressed/cache.c
+++ b/arch/sh/boot/compressed/cache.c
@@ -5,7 +5,7 @@ int cache_control(unsigned int command)
for (i = 0; i < (32 * 1024); i += 32) {
(void)*p;
- p += (32 / sizeof (int));
+ p += (32 / sizeof(int));
}
return 0;
diff --git a/arch/sh/include/asm/cacheflush.h b/arch/sh/include/asm/cacheflush.h
index da3ebec921a..1f4e562c5e8 100644
--- a/arch/sh/include/asm/cacheflush.h
+++ b/arch/sh/include/asm/cacheflush.h
@@ -86,8 +86,8 @@ extern void copy_from_user_page(struct vm_area_struct *vma,
struct page *page, unsigned long vaddr, void *dst, const void *src,
unsigned long len);
-#define flush_cache_vmap(start, end) flush_cache_all()
-#define flush_cache_vunmap(start, end) flush_cache_all()
+#define flush_cache_vmap(start, end) local_flush_cache_all(NULL)
+#define flush_cache_vunmap(start, end) local_flush_cache_all(NULL)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
#define flush_dcache_mmap_unlock(mapping) do { } while (0)
diff --git a/arch/sh/include/asm/dma-register.h b/arch/sh/include/asm/dma-register.h
new file mode 100644
index 00000000000..51cd78feacf
--- /dev/null
+++ b/arch/sh/include/asm/dma-register.h
@@ -0,0 +1,51 @@
+/*
+ * Common header for the legacy SH DMA driver and the new dmaengine driver
+ *
+ * extracted from arch/sh/include/asm/dma-sh.h:
+ *
+ * Copyright (C) 2000 Takashi YOSHII
+ * Copyright (C) 2003 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.
+ */
+#ifndef DMA_REGISTER_H
+#define DMA_REGISTER_H
+
+/* DMA register */
+#define SAR 0x00
+#define DAR 0x04
+#define TCR 0x08
+#define CHCR 0x0C
+#define DMAOR 0x40
+
+/* DMAOR definitions */
+#define DMAOR_AE 0x00000004
+#define DMAOR_NMIF 0x00000002
+#define DMAOR_DME 0x00000001
+
+/* Definitions for the SuperH DMAC */
+#define REQ_L 0x00000000
+#define REQ_E 0x00080000
+#define RACK_H 0x00000000
+#define RACK_L 0x00040000
+#define ACK_R 0x00000000
+#define ACK_W 0x00020000
+#define ACK_H 0x00000000
+#define ACK_L 0x00010000
+#define DM_INC 0x00004000
+#define DM_DEC 0x00008000
+#define DM_FIX 0x0000c000
+#define SM_INC 0x00001000
+#define SM_DEC 0x00002000
+#define SM_FIX 0x00003000
+#define RS_IN 0x00000200
+#define RS_OUT 0x00000300
+#define TS_BLK 0x00000040
+#define TM_BUR 0x00000020
+#define CHCR_DE 0x00000001
+#define CHCR_TE 0x00000002
+#define CHCR_IE 0x00000004
+
+#endif
diff --git a/arch/sh/include/asm/dma-sh.h b/arch/sh/include/asm/dma-sh.h
index e934a2e6665..f3acb8e34c6 100644
--- a/arch/sh/include/asm/dma-sh.h
+++ b/arch/sh/include/asm/dma-sh.h
@@ -11,7 +11,8 @@
#ifndef __DMA_SH_H
#define __DMA_SH_H
-#include <asm/dma.h>
+#include <asm/dma-register.h>
+#include <cpu/dma-register.h>
#include <cpu/dma.h>
/* DMAOR contorl: The DMAOR access size is different by CPU.*/
@@ -53,34 +54,6 @@ static int dmte_irq_map[] __maybe_unused = {
#endif
};
-/* Definitions for the SuperH DMAC */
-#define REQ_L 0x00000000
-#define REQ_E 0x00080000
-#define RACK_H 0x00000000
-#define RACK_L 0x00040000
-#define ACK_R 0x00000000
-#define ACK_W 0x00020000
-#define ACK_H 0x00000000
-#define ACK_L 0x00010000
-#define DM_INC 0x00004000
-#define DM_DEC 0x00008000
-#define DM_FIX 0x0000c000
-#define SM_INC 0x00001000
-#define SM_DEC 0x00002000
-#define SM_FIX 0x00003000
-#define RS_IN 0x00000200
-#define RS_OUT 0x00000300
-#define TS_BLK 0x00000040
-#define TM_BUR 0x00000020
-#define CHCR_DE 0x00000001
-#define CHCR_TE 0x00000002
-#define CHCR_IE 0x00000004
-
-/* DMAOR definitions */
-#define DMAOR_AE 0x00000004
-#define DMAOR_NMIF 0x00000002
-#define DMAOR_DME 0x00000001
-
/*
* Define the default configuration for dual address memory-memory transfer.
* The 0x400 value represents auto-request, external->external.
@@ -111,61 +84,4 @@ static u32 dma_base_addr[] __maybe_unused = {
#endif
};
-/* DMA register */
-#define SAR 0x00
-#define DAR 0x04
-#define TCR 0x08
-#define CHCR 0x0C
-#define DMAOR 0x40
-
-/*
- * for dma engine
- *
- * SuperH DMA mode
- */
-#define SHDMA_MIX_IRQ (1 << 1)
-#define SHDMA_DMAOR1 (1 << 2)
-#define SHDMA_DMAE1 (1 << 3)
-
-enum sh_dmae_slave_chan_id {
- SHDMA_SLAVE_SCIF0_TX,
- SHDMA_SLAVE_SCIF0_RX,
- SHDMA_SLAVE_SCIF1_TX,
- SHDMA_SLAVE_SCIF1_RX,
- SHDMA_SLAVE_SCIF2_TX,
- SHDMA_SLAVE_SCIF2_RX,
- SHDMA_SLAVE_SCIF3_TX,
- SHDMA_SLAVE_SCIF3_RX,
- SHDMA_SLAVE_SCIF4_TX,
- SHDMA_SLAVE_SCIF4_RX,
- SHDMA_SLAVE_SCIF5_TX,
- SHDMA_SLAVE_SCIF5_RX,
- SHDMA_SLAVE_SIUA_TX,
- SHDMA_SLAVE_SIUA_RX,
- SHDMA_SLAVE_SIUB_TX,
- SHDMA_SLAVE_SIUB_RX,
- SHDMA_SLAVE_NUMBER, /* Must stay last */
-};
-
-struct sh_dmae_slave_config {
- enum sh_dmae_slave_chan_id slave_id;
- dma_addr_t addr;
- u32 chcr;
- char mid_rid;
-};
-
-struct sh_dmae_pdata {
- unsigned int mode;
- struct sh_dmae_slave_config *config;
- int config_num;
-};
-
-struct device;
-
-struct sh_dmae_slave {
- enum sh_dmae_slave_chan_id slave_id; /* Set by the platform */
- struct device *dma_dev; /* Set by the platform */
- struct sh_dmae_slave_config *config; /* Set by the driver */
-};
-
#endif /* __DMA_SH_H */
diff --git a/arch/sh/include/asm/dmaengine.h b/arch/sh/include/asm/dmaengine.h
new file mode 100644
index 00000000000..bf2f30cf0a2
--- /dev/null
+++ b/arch/sh/include/asm/dmaengine.h
@@ -0,0 +1,93 @@
+/*
+ * Header for the new SH dmaengine driver
+ *
+ * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef ASM_DMAENGINE_H
+#define ASM_DMAENGINE_H
+
+#include <linux/dmaengine.h>
+#include <linux/list.h>
+
+#include <asm/dma-register.h>
+
+#define SH_DMAC_MAX_CHANNELS 6
+
+enum sh_dmae_slave_chan_id {
+ SHDMA_SLAVE_SCIF0_TX,
+ SHDMA_SLAVE_SCIF0_RX,
+ SHDMA_SLAVE_SCIF1_TX,
+ SHDMA_SLAVE_SCIF1_RX,
+ SHDMA_SLAVE_SCIF2_TX,
+ SHDMA_SLAVE_SCIF2_RX,
+ SHDMA_SLAVE_SCIF3_TX,
+ SHDMA_SLAVE_SCIF3_RX,
+ SHDMA_SLAVE_SCIF4_TX,
+ SHDMA_SLAVE_SCIF4_RX,
+ SHDMA_SLAVE_SCIF5_TX,
+ SHDMA_SLAVE_SCIF5_RX,
+ SHDMA_SLAVE_SIUA_TX,
+ SHDMA_SLAVE_SIUA_RX,
+ SHDMA_SLAVE_SIUB_TX,
+ SHDMA_SLAVE_SIUB_RX,
+ SHDMA_SLAVE_NUMBER, /* Must stay last */
+};
+
+struct sh_dmae_slave_config {
+ enum sh_dmae_slave_chan_id slave_id;
+ dma_addr_t addr;
+ u32 chcr;
+ char mid_rid;
+};
+
+struct sh_dmae_channel {
+ unsigned int offset;
+ unsigned int dmars;
+ unsigned int dmars_bit;
+};
+
+struct sh_dmae_pdata {
+ struct sh_dmae_slave_config *slave;
+ int slave_num;
+ struct sh_dmae_channel *channel;
+ int channel_num;
+ unsigned int ts_low_shift;
+ unsigned int ts_low_mask;
+ unsigned int ts_high_shift;
+ unsigned int ts_high_mask;
+ unsigned int *ts_shift;
+ int ts_shift_num;
+ u16 dmaor_init;
+};
+
+struct device;
+
+/* Used by slave DMA clients to request DMA to/from a specific peripheral */
+struct sh_dmae_slave {
+ enum sh_dmae_slave_chan_id slave_id; /* Set by the platform */
+ struct device *dma_dev; /* Set by the platform */
+ struct sh_dmae_slave_config *config; /* Set by the driver */
+};
+
+struct sh_dmae_regs {
+ u32 sar; /* SAR / source address */
+ u32 dar; /* DAR / destination address */
+ u32 tcr; /* TCR / transfer count */
+};
+
+struct sh_desc {
+ struct sh_dmae_regs hw;
+ struct list_head node;
+ struct dma_async_tx_descriptor async_tx;
+ enum dma_data_direction direction;
+ dma_cookie_t cookie;
+ size_t partial;
+ int chunks;
+ int mark;
+};
+
+#endif
diff --git a/arch/sh/include/asm/io.h b/arch/sh/include/asm/io.h
index 7dab7b23a5e..f689554e17c 100644
--- a/arch/sh/include/asm/io.h
+++ b/arch/sh/include/asm/io.h
@@ -291,21 +291,21 @@ unsigned long long poke_real_address_q(unsigned long long addr,
* doesn't exist, so everything must go through page tables.
*/
#ifdef CONFIG_MMU
-void __iomem *__ioremap_caller(unsigned long offset, unsigned long size,
+void __iomem *__ioremap_caller(phys_addr_t offset, unsigned long size,
pgprot_t prot, void *caller);
void __iounmap(void __iomem *addr);
static inline void __iomem *
-__ioremap(unsigned long offset, unsigned long size, pgprot_t prot)
+__ioremap(phys_addr_t offset, unsigned long size, pgprot_t prot)
{
return __ioremap_caller(offset, size, prot, __builtin_return_address(0));
}
static inline void __iomem *
-__ioremap_29bit(unsigned long offset, unsigned long size, pgprot_t prot)
+__ioremap_29bit(phys_addr_t offset, unsigned long size, pgprot_t prot)
{
#ifdef CONFIG_29BIT
- unsigned long last_addr = offset + size - 1;
+ phys_addr_t last_addr = offset + size - 1;
/*
* For P1 and P2 space this is trivial, as everything is already
@@ -329,7 +329,7 @@ __ioremap_29bit(unsigned long offset, unsigned long size, pgprot_t prot)
}
static inline void __iomem *
-__ioremap_mode(unsigned long offset, unsigned long size, pgprot_t prot)
+__ioremap_mode(phys_addr_t offset, unsigned long size, pgprot_t prot)
{
void __iomem *ret;
@@ -349,35 +349,32 @@ __ioremap_mode(unsigned long offset, unsigned long size, pgprot_t prot)
#define __iounmap(addr) do { } while (0)
#endif /* CONFIG_MMU */
-static inline void __iomem *
-ioremap(unsigned long offset, unsigned long size)
+static inline void __iomem *ioremap(phys_addr_t offset, unsigned long size)
{
return __ioremap_mode(offset, size, PAGE_KERNEL_NOCACHE);
}
static inline void __iomem *
-ioremap_cache(unsigned long offset, unsigned long size)
+ioremap_cache(phys_addr_t offset, unsigned long size)
{
return __ioremap_mode(offset, size, PAGE_KERNEL);
}
#ifdef CONFIG_HAVE_IOREMAP_PROT
static inline void __iomem *
-ioremap_prot(resource_size_t offset, unsigned long size, unsigned long flags)
+ioremap_prot(phys_addr_t offset, unsigned long size, unsigned long flags)
{
return __ioremap_mode(offset, size, __pgprot(flags));
}
#endif
#ifdef CONFIG_IOREMAP_FIXED
-extern void __iomem *ioremap_fixed(resource_size_t, unsigned long,
- unsigned long, pgprot_t);
+extern void __iomem *ioremap_fixed(phys_addr_t, unsigned long, pgprot_t);
extern int iounmap_fixed(void __iomem *);
extern void ioremap_fixed_init(void);
#else
static inline void __iomem *
-ioremap_fixed(resource_size_t phys_addr, unsigned long offset,
- unsigned long size, pgprot_t prot)
+ioremap_fixed(phys_addr_t phys_addr, unsigned long size, pgprot_t prot)
{
BUG();
return NULL;
diff --git a/arch/sh/include/asm/mmu.h b/arch/sh/include/asm/mmu.h
index 15a05b615ba..19fe84550b4 100644
--- a/arch/sh/include/asm/mmu.h
+++ b/arch/sh/include/asm/mmu.h
@@ -55,19 +55,29 @@ typedef struct {
#ifdef CONFIG_PMB
/* arch/sh/mm/pmb.c */
-long pmb_remap(unsigned long virt, unsigned long phys,
- unsigned long size, pgprot_t prot);
-void pmb_unmap(unsigned long addr);
-void pmb_init(void);
bool __in_29bit_mode(void);
+
+void pmb_init(void);
+int pmb_bolt_mapping(unsigned long virt, phys_addr_t phys,
+ unsigned long size, pgprot_t prot);
+void __iomem *pmb_remap_caller(phys_addr_t phys, unsigned long size,
+ pgprot_t prot, void *caller);
+int pmb_unmap(void __iomem *addr);
+
#else
-static inline long pmb_remap(unsigned long virt, unsigned long phys,
- unsigned long size, pgprot_t prot)
+
+static inline void __iomem *
+pmb_remap_caller(phys_addr_t phys, unsigned long size,
+ pgprot_t prot, void *caller)
+{
+ return NULL;
+}
+
+static inline int pmb_unmap(void __iomem *addr)
{
return -EINVAL;
}
-#define pmb_unmap(addr) do { } while (0)
#define pmb_init(addr) do { } while (0)
#ifdef CONFIG_29BIT
@@ -77,6 +87,13 @@ static inline long pmb_remap(unsigned long virt, unsigned long phys,
#endif
#endif /* CONFIG_PMB */
+
+static inline void __iomem *
+pmb_remap(phys_addr_t phys, unsigned long size, pgprot_t prot)
+{
+ return pmb_remap_caller(phys, size, prot, __builtin_return_address(0));
+}
+
#endif /* __ASSEMBLY__ */
#endif /* __MMU_H */
diff --git a/arch/sh/include/asm/siu.h b/arch/sh/include/asm/siu.h
index 57565a3b551..f1b1e6944a5 100644
--- a/arch/sh/include/asm/siu.h
+++ b/arch/sh/include/asm/siu.h
@@ -11,7 +11,7 @@
#ifndef ASM_SIU_H
#define ASM_SIU_H
-#include <asm/dma-sh.h>
+#include <asm/dmaengine.h>
struct device;
diff --git a/arch/sh/include/asm/topology.h b/arch/sh/include/asm/topology.h
index 37cdadd975a..88e734069fa 100644
--- a/arch/sh/include/asm/topology.h
+++ b/arch/sh/include/asm/topology.h
@@ -35,7 +35,7 @@
#define pcibus_to_node(bus) ((void)(bus), -1)
#define cpumask_of_pcibus(bus) (pcibus_to_node(bus) == -1 ? \
- CPU_MASK_ALL_PTR : \
+ cpu_all_mask : \
cpumask_of_node(pcibus_to_node(bus)))
#endif
diff --git a/arch/sh/include/cpu-sh3/cpu/dma-register.h b/arch/sh/include/cpu-sh3/cpu/dma-register.h
new file mode 100644
index 00000000000..2349e488c9a
--- /dev/null
+++ b/arch/sh/include/cpu-sh3/cpu/dma-register.h
@@ -0,0 +1,41 @@
+/*
+ * SH3 CPU-specific DMA definitions, used by both DMA drivers
+ *
+ * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef CPU_DMA_REGISTER_H
+#define CPU_DMA_REGISTER_H
+
+#define CHCR_TS_LOW_MASK 0x18
+#define CHCR_TS_LOW_SHIFT 3
+#define CHCR_TS_HIGH_MASK 0
+#define CHCR_TS_HIGH_SHIFT 0
+
+#define DMAOR_INIT DMAOR_DME
+
+/*
+ * The SuperH DMAC supports a number of transmit sizes, we list them here,
+ * with their respective values as they appear in the CHCR registers.
+ */
+enum {
+ XMIT_SZ_8BIT,
+ XMIT_SZ_16BIT,
+ XMIT_SZ_32BIT,
+ XMIT_SZ_128BIT,
+};
+
+/* log2(size / 8) - used to calculate number of transfers */
+#define TS_SHIFT { \
+ [XMIT_SZ_8BIT] = 0, \
+ [XMIT_SZ_16BIT] = 1, \
+ [XMIT_SZ_32BIT] = 2, \
+ [XMIT_SZ_128BIT] = 4, \
+}
+
+#define TS_INDEX2VAL(i) (((i) & 3) << CHCR_TS_LOW_SHIFT)
+
+#endif
diff --git a/arch/sh/include/cpu-sh3/cpu/dma.h b/arch/sh/include/cpu-sh3/cpu/dma.h
index 207811a7a65..24e28b91c9d 100644
--- a/arch/sh/include/cpu-sh3/cpu/dma.h
+++ b/arch/sh/include/cpu-sh3/cpu/dma.h
@@ -20,31 +20,4 @@
#define TS_32 0x00000010
#define TS_128 0x00000018
-#define CHCR_TS_LOW_MASK 0x18
-#define CHCR_TS_LOW_SHIFT 3
-#define CHCR_TS_HIGH_MASK 0
-#define CHCR_TS_HIGH_SHIFT 0
-
-#define DMAOR_INIT DMAOR_DME
-
-/*
- * The SuperH DMAC supports a number of transmit sizes, we list them here,
- * with their respective values as they appear in the CHCR registers.
- */
-enum {
- XMIT_SZ_8BIT,
- XMIT_SZ_16BIT,
- XMIT_SZ_32BIT,
- XMIT_SZ_128BIT,
-};
-
-#define TS_SHIFT { \
- [XMIT_SZ_8BIT] = 0, \
- [XMIT_SZ_16BIT] = 1, \
- [XMIT_SZ_32BIT] = 2, \
- [XMIT_SZ_128BIT] = 4, \
-}
-
-#define TS_INDEX2VAL(i) (((i) & 3) << CHCR_TS_LOW_SHIFT)
-
#endif /* __ASM_CPU_SH3_DMA_H */
diff --git a/arch/sh/include/cpu-sh4/cpu/dma-register.h b/arch/sh/include/cpu-sh4/cpu/dma-register.h
new file mode 100644
index 00000000000..55f9fec082d
--- /dev/null
+++ b/arch/sh/include/cpu-sh4/cpu/dma-register.h
@@ -0,0 +1,112 @@
+/*
+ * SH4 CPU-specific DMA definitions, used by both DMA drivers
+ *
+ * Copyright (C) 2010 Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef CPU_DMA_REGISTER_H
+#define CPU_DMA_REGISTER_H
+
+/* SH7751/7760/7780 DMA IRQ sources */
+
+#ifdef CONFIG_CPU_SH4A
+
+#define DMAOR_INIT DMAOR_DME
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7343) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7730)
+#define CHCR_TS_LOW_MASK 0x00000018
+#define CHCR_TS_LOW_SHIFT 3
+#define CHCR_TS_HIGH_MASK 0
+#define CHCR_TS_HIGH_SHIFT 0
+#elif defined(CONFIG_CPU_SUBTYPE_SH7722) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7724)
+#define CHCR_TS_LOW_MASK 0x00000018
+#define CHCR_TS_LOW_SHIFT 3
+#define CHCR_TS_HIGH_MASK 0x00300000
+#define CHCR_TS_HIGH_SHIFT (20 - 2) /* 2 bits for shifted low TS */
+#elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \
+ defined(CONFIG_CPU_SUBTYPE_SH7764)
+#define CHCR_TS_LOW_MASK 0x00000018
+#define CHCR_TS_LOW_SHIFT 3
+#define CHCR_TS_HIGH_MASK 0
+#define CHCR_TS_HIGH_SHIFT 0
+#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
+#define CHCR_TS_LOW_MASK 0x00000018
+#define CHCR_TS_LOW_SHIFT 3
+#define CHCR_TS_HIGH_MASK 0
+#define CHCR_TS_HIGH_SHIFT 0
+#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
+#define CHCR_TS_LOW_MASK 0x00000018
+#define CHCR_TS_LOW_SHIFT 3
+#define CHCR_TS_HIGH_MASK 0
+#define CHCR_TS_HIGH_SHIFT 0
+#else /* SH7785 */
+#define CHCR_TS_LOW_MASK 0x00000018
+#define CHCR_TS_LOW_SHIFT 3
+#define CHCR_TS_HIGH_MASK 0
+#define CHCR_TS_HIGH_SHIFT 0
+#endif
+
+/* Transmit sizes and respective CHCR register values */
+enum {
+ XMIT_SZ_8BIT = 0,
+ XMIT_SZ_16BIT = 1,
+ XMIT_SZ_32BIT = 2,
+ XMIT_SZ_64BIT = 7,
+ XMIT_SZ_128BIT = 3,
+ XMIT_SZ_256BIT = 4,
+ XMIT_SZ_128BIT_BLK = 0xb,
+ XMIT_SZ_256BIT_BLK = 0xc,
+};
+
+/* log2(size / 8) - used to calculate number of transfers */
+#define TS_SHIFT { \
+ [XMIT_SZ_8BIT] = 0, \
+ [XMIT_SZ_16BIT] = 1, \
+ [XMIT_SZ_32BIT] = 2, \
+ [XMIT_SZ_64BIT] = 3, \
+ [XMIT_SZ_128BIT] = 4, \
+ [XMIT_SZ_256BIT] = 5, \
+ [XMIT_SZ_128BIT_BLK] = 4, \
+ [XMIT_SZ_256BIT_BLK] = 5, \
+}
+
+#define TS_INDEX2VAL(i) ((((i) & 3) << CHCR_TS_LOW_SHIFT) | \
+ ((((i) >> 2) & 3) << CHCR_TS_HIGH_SHIFT))
+
+#else /* CONFIG_CPU_SH4A */
+
+#define DMAOR_INIT (0x8000 | DMAOR_DME)
+
+#define CHCR_TS_LOW_MASK 0x70
+#define CHCR_TS_LOW_SHIFT 4
+#define CHCR_TS_HIGH_MASK 0
+#define CHCR_TS_HIGH_SHIFT 0
+
+/* Transmit sizes and respective CHCR register values */
+enum {
+ XMIT_SZ_8BIT = 1,
+ XMIT_SZ_16BIT = 2,
+ XMIT_SZ_32BIT = 3,
+ XMIT_SZ_64BIT = 0,
+ XMIT_SZ_256BIT = 4,
+};
+
+/* log2(size / 8) - used to calculate number of transfers */
+#define TS_SHIFT { \
+ [XMIT_SZ_8BIT] = 0, \
+ [XMIT_SZ_16BIT] = 1, \
+ [XMIT_SZ_32BIT] = 2, \
+ [XMIT_SZ_64BIT] = 3, \
+ [XMIT_SZ_256BIT] = 5, \
+}
+
+#define TS_INDEX2VAL(i) (((i) & 7) << CHCR_TS_LOW_SHIFT)
+
+#endif /* CONFIG_CPU_SH4A */
+
+#endif
diff --git a/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h b/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h
index e734ea47d8a..9647e681fd2 100644
--- a/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h
+++ b/arch/sh/include/cpu-sh4/cpu/dma-sh4a.h
@@ -8,20 +8,12 @@
#define DMAE0_IRQ 78 /* DMA Error IRQ*/
#define SH_DMAC_BASE0 0xFE008020
#define SH_DMARS_BASE0 0xFE009000
-#define CHCR_TS_LOW_MASK 0x00000018
-#define CHCR_TS_LOW_SHIFT 3
-#define CHCR_TS_HIGH_MASK 0
-#define CHCR_TS_HIGH_SHIFT 0
#elif defined(CONFIG_CPU_SUBTYPE_SH7722)
#define DMTE0_IRQ 48
#define DMTE4_IRQ 76
#define DMAE0_IRQ 78 /* DMA Error IRQ*/
#define SH_DMAC_BASE0 0xFE008020
#define SH_DMARS_BASE0 0xFE009000
-#define CHCR_TS_LOW_MASK 0x00000018
-#define CHCR_TS_LOW_SHIFT 3
-#define CHCR_TS_HIGH_MASK 0x00300000
-#define CHCR_TS_HIGH_SHIFT 20
#elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \
defined(CONFIG_CPU_SUBTYPE_SH7764)
#define DMTE0_IRQ 34
@@ -29,10 +21,6 @@
#define DMAE0_IRQ 38
#define SH_DMAC_BASE0 0xFF608020
#define SH_DMARS_BASE0 0xFF609000
-#define CHCR_TS_LOW_MASK 0x00000018
-#define CHCR_TS_LOW_SHIFT 3
-#define CHCR_TS_HIGH_MASK 0
-#define CHCR_TS_HIGH_SHIFT 0
#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
#define DMTE0_IRQ 48 /* DMAC0A*/
#define DMTE4_IRQ 76 /* DMAC0B */
@@ -46,10 +34,6 @@
#define SH_DMAC_BASE0 0xFE008020
#define SH_DMAC_BASE1 0xFDC08020
#define SH_DMARS_BASE0 0xFDC09000
-#define CHCR_TS_LOW_MASK 0x00000018
-#define CHCR_TS_LOW_SHIFT 3
-#define CHCR_TS_HIGH_MASK 0
-#define CHCR_TS_HIGH_SHIFT 0
#elif defined(CONFIG_CPU_SUBTYPE_SH7724)
#define DMTE0_IRQ 48 /* DMAC0A*/
#define DMTE4_IRQ 76 /* DMAC0B */
@@ -64,10 +48,6 @@
#define SH_DMAC_BASE1 0xFDC08020
#define SH_DMARS_BASE0 0xFE009000
#define SH_DMARS_BASE1 0xFDC09000
-#define CHCR_TS_LOW_MASK 0x00000018
-#define CHCR_TS_LOW_SHIFT 3
-#define CHCR_TS_HIGH_MASK 0x00600000
-#define CHCR_TS_HIGH_SHIFT 21
#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
#define DMTE0_IRQ 34
#define DMTE4_IRQ 44
@@ -80,10 +60,6 @@
#define SH_DMAC_BASE0 0xFC808020
#define SH_DMAC_BASE1 0xFC818020
#define SH_DMARS_BASE0 0xFC809000
-#define CHCR_TS_LOW_MASK 0x00000018
-#define CHCR_TS_LOW_SHIFT 3
-#define CHCR_TS_HIGH_MASK 0
-#define CHCR_TS_HIGH_SHIFT 0
#else /* SH7785 */
#define DMTE0_IRQ 33
#define DMTE4_IRQ 37
@@ -97,10 +73,6 @@
#define SH_DMAC_BASE0 0xFC808020
#define SH_DMAC_BASE1 0xFCC08020
#define SH_DMARS_BASE0 0xFC809000
-#define CHCR_TS_LOW_MASK 0x00000018
-#define CHCR_TS_LOW_SHIFT 3
-#define CHCR_TS_HIGH_MASK 0
-#define CHCR_TS_HIGH_SHIFT 0
#endif
#define REQ_HE 0x000000C0
@@ -108,38 +80,4 @@
#define REQ_LE 0x00000040
#define TM_BURST 0x00000020
-/*
- * The SuperH DMAC supports a number of transmit sizes, we list them here,
- * with their respective values as they appear in the CHCR registers.
- *
- * Defaults to a 64-bit transfer size.
- */
-enum {
- XMIT_SZ_8BIT = 0,
- XMIT_SZ_16BIT = 1,
- XMIT_SZ_32BIT = 2,
- XMIT_SZ_64BIT = 7,
- XMIT_SZ_128BIT = 3,
- XMIT_SZ_256BIT = 4,
- XMIT_SZ_128BIT_BLK = 0xb,
- XMIT_SZ_256BIT_BLK = 0xc,
-};
-
-/*
- * The DMA count is defined as the number of bytes to transfer.
- */
-#define TS_SHIFT { \
- [XMIT_SZ_8BIT] = 0, \
- [XMIT_SZ_16BIT] = 1, \
- [XMIT_SZ_32BIT] = 2, \
- [XMIT_SZ_64BIT] = 3, \
- [XMIT_SZ_128BIT] = 4, \
- [XMIT_SZ_256BIT] = 5, \
- [XMIT_SZ_128BIT_BLK] = 4, \
- [XMIT_SZ_256BIT_BLK] = 5, \
-}
-
-#define TS_INDEX2VAL(i) ((((i) & 3) << CHCR_TS_LOW_SHIFT) | \
- ((((i) >> 2) & 3) << CHCR_TS_HIGH_SHIFT))
-
#endif /* __ASM_SH_CPU_SH4_DMA_SH7780_H */
diff --git a/arch/sh/include/cpu-sh4/cpu/dma.h b/arch/sh/include/cpu-sh4/cpu/dma.h
index 114a369705b..ca747e93c2e 100644
--- a/arch/sh/include/cpu-sh4/cpu/dma.h
+++ b/arch/sh/include/cpu-sh4/cpu/dma.h
@@ -5,9 +5,8 @@
#ifdef CONFIG_CPU_SH4A
-#define DMAOR_INIT (DMAOR_DME)
-
#include <cpu/dma-sh4a.h>
+
#else /* CONFIG_CPU_SH4A */
/*
* SH7750/SH7751/SH7760
@@ -17,7 +16,6 @@
#define DMTE6_IRQ 46
#define DMAE0_IRQ 38
-#define DMAOR_INIT (0x8000|DMAOR_DME)
#define SH_DMAC_BASE0 0xffa00000
#define SH_DMAC_BASE1 0xffa00070
/* Definitions for the SuperH DMAC */
@@ -27,40 +25,8 @@
#define TS_32 0x00000030
#define TS_64 0x00000000
-#define CHCR_TS_LOW_MASK 0x70
-#define CHCR_TS_LOW_SHIFT 4
-#define CHCR_TS_HIGH_MASK 0
-#define CHCR_TS_HIGH_SHIFT 0
-
#define DMAOR_COD 0x00000008
-/*
- * The SuperH DMAC supports a number of transmit sizes, we list them here,
- * with their respective values as they appear in the CHCR registers.
- *
- * Defaults to a 64-bit transfer size.
- */
-enum {
- XMIT_SZ_8BIT = 1,
- XMIT_SZ_16BIT = 2,
- XMIT_SZ_32BIT = 3,
- XMIT_SZ_64BIT = 0,
- XMIT_SZ_256BIT = 4,
-};
-
-/*
- * The DMA count is defined as the number of bytes to transfer.
- */
-#define TS_SHIFT { \
- [XMIT_SZ_8BIT] = 0, \
- [XMIT_SZ_16BIT] = 1, \
- [XMIT_SZ_32BIT] = 2, \
- [XMIT_SZ_64BIT] = 3, \
- [XMIT_SZ_256BIT] = 5, \
-}
-
-#define TS_INDEX2VAL(i) (((i) & 7) << CHCR_TS_LOW_SHIFT)
-
#endif
#endif /* __ASM_CPU_SH4_DMA_H */
diff --git a/arch/sh/include/mach-migor/mach/migor.h b/arch/sh/include/mach-migor/mach/migor.h
index cee6cb88e02..42fccf93412 100644
--- a/arch/sh/include/mach-migor/mach/migor.h
+++ b/arch/sh/include/mach-migor/mach/migor.h
@@ -1,6 +1,7 @@
#ifndef __ASM_SH_MIGOR_H
#define __ASM_SH_MIGOR_H
+#define PORT_MSELCRA 0xa4050180
#define PORT_MSELCRB 0xa4050182
#define BSC_CS4BCR 0xfec10010
#define BSC_CS6ABCR 0xfec1001c
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c
index fc065f9da6e..14726eef1ce 100644
--- a/arch/sh/kernel/cpu/sh4/sq.c
+++ b/arch/sh/kernel/cpu/sh4/sq.c
@@ -326,7 +326,7 @@ static struct attribute *sq_sysfs_attrs[] = {
NULL,
};
-static struct sysfs_ops sq_sysfs_ops = {
+static const struct sysfs_ops sq_sysfs_ops = {
.show = sq_sysfs_show,
.store = sq_sysfs_store,
};
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
index ef3f9782780..fd7e3639e84 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7722.c
@@ -7,19 +7,167 @@
* 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/mm.h>
+#include <linux/platform_device.h>
#include <linux/serial.h>
#include <linux/serial_sci.h>
-#include <linux/mm.h>
+#include <linux/sh_timer.h>
#include <linux/uio_driver.h>
#include <linux/usb/m66592.h>
-#include <linux/sh_timer.h>
+
#include <asm/clock.h>
+#include <asm/dmaengine.h>
#include <asm/mmzone.h>
-#include <asm/dma-sh.h>
+#include <asm/siu.h>
+
+#include <cpu/dma-register.h>
#include <cpu/sh7722.h>
+static struct sh_dmae_slave_config sh7722_dmae_slaves[] = {
+ {
+ .slave_id = SHDMA_SLAVE_SCIF0_TX,
+ .addr = 0xffe0000c,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x21,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF0_RX,
+ .addr = 0xffe00014,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x22,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF1_TX,
+ .addr = 0xffe1000c,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x25,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF1_RX,
+ .addr = 0xffe10014,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x26,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF2_TX,
+ .addr = 0xffe2000c,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x29,
+ }, {
+ .slave_id = SHDMA_SLAVE_SCIF2_RX,
+ .addr = 0xffe20014,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
+ .mid_rid = 0x2a,
+ }, {
+ .slave_id = SHDMA_SLAVE_SIUA_TX,
+ .addr = 0xa454c098,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0xb1,
+ }, {
+ .slave_id = SHDMA_SLAVE_SIUA_RX,
+ .addr = 0xa454c090,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0xb2,
+ }, {
+ .slave_id = SHDMA_SLAVE_SIUB_TX,
+ .addr = 0xa454c09c,
+ .chcr = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0xb5,
+ }, {
+ .slave_id = SHDMA_SLAVE_SIUB_RX,
+ .addr = 0xa454c094,
+ .chcr = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+ .mid_rid = 0xb6,
+ },
+};
+
+static struct sh_dmae_channel sh7722_dmae_channels[] = {
+ {
+ .offset = 0,
+ .dmars = 0,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x10,
+ .dmars = 0,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x20,
+ .dmars = 4,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x30,
+ .dmars = 4,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x50,
+ .dmars = 8,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x60,
+ .dmars = 8,
+ .dmars_bit = 8,
+ }
+};
+
+static unsigned int ts_shift[] = TS_SHIFT;
+
+static struct sh_dmae_pdata dma_platform_data = {
+ .slave = sh7722_dmae_slaves,
+ .slave_num = ARRAY_SIZE(sh7722_dmae_slaves),
+ .channel = sh7722_dmae_channels,
+ .channel_num = ARRAY_SIZE(sh7722_dmae_channels),
+ .ts_low_shift = CHCR_TS_LOW_SHIFT,
+ .ts_low_mask = CHCR_TS_LOW_MASK,
+ .ts_high_shift = CHCR_TS_HIGH_SHIFT,
+ .ts_high_mask = CHCR_TS_HIGH_MASK,
+ .ts_shift = ts_shift,
+ .ts_shift_num = ARRAY_SIZE(ts_shift),
+ .dmaor_init = DMAOR_INIT,
+};
+
+static struct resource sh7722_dmae_resources[] = {
+ [0] = {
+ /* Channel registers and DMAOR */
+ .start = 0xfe008020,
+ .end = 0xfe00808f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* DMARSx */
+ .start = 0xfe009000,
+ .end = 0xfe00900b,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ /* DMA error IRQ */
+ .start = 78,
+ .end = 78,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channels 0-3 */
+ .start = 48,
+ .end = 51,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channels 4-5 */
+ .start = 76,
+ .end = 77,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+struct platform_device dma_device = {
+ .name = "sh-dma-engine",
+ .id = -1,
+ .resource = sh7722_dmae_resources,
+ .num_resources = ARRAY_SIZE(sh7722_dmae_resources),
+ .dev = {
+ .platform_data = &dma_platform_data,
+ },
+ .archdata = {
+ .hwblk_id = HWBLK_DMAC,
+ },
+};
+
/* Serial */
static struct plat_sci_port scif0_platform_data = {
.mapbase = 0xffe00000,
@@ -388,15 +536,36 @@ static struct platform_device tmu2_device = {
},
};
-static struct sh_dmae_pdata dma_platform_data = {
- .mode = 0,
+static struct siu_platform siu_platform_data = {
+ .dma_dev = &dma_device.dev,
+ .dma_slave_tx_a = SHDMA_SLAVE_SIUA_TX,
+ .dma_slave_rx_a = SHDMA_SLAVE_SIUA_RX,
+ .dma_slave_tx_b = SHDMA_SLAVE_SIUB_TX,
+ .dma_slave_rx_b = SHDMA_SLAVE_SIUB_RX,
};
-static struct platform_device dma_device = {
- .name = "sh-dma-engine",
+static struct resource siu_resources[] = {
+ [0] = {
+ .start = 0xa4540000,
+ .end = 0xa454c10f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = 108,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device siu_device = {
+ .name = "sh_siu",
.id = -1,
- .dev = {
- .platform_data = &dma_platform_data,
+ .dev = {
+ .platform_data = &siu_platform_data,
+ },
+ .resource = siu_resources,
+ .num_resources = ARRAY_SIZE(siu_resources),
+ .archdata = {
+ .hwblk_id = HWBLK_SIU,
},
};
@@ -414,6 +583,7 @@ static struct platform_device *sh7722_devices[] __initdata = {
&vpu_device,
&veu_device,
&jpu_device,
+ &siu_device,
&dma_device,
};
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
index 31e3451f7e3..e7fa2a92fc1 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7724.c
@@ -21,22 +21,189 @@
#include <linux/sh_timer.h>
#include <linux/io.h>
#include <linux/notifier.h>
+
#include <asm/suspend.h>
#include <asm/clock.h>
-#include <asm/dma-sh.h>
+#include <asm/dmaengine.h>
#include <asm/mmzone.h>
+
+#include <cpu/dma-register.h>
#include <cpu/sh7724.h>
/* DMA */
-static struct sh_dmae_pdata dma_platform_data = {
- .mode = SHDMA_DMAOR1,
+static struct sh_dmae_channel sh7724_dmae0_channels[] = {
+ {
+ .offset = 0,
+ .dmars = 0,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x10,
+ .dmars = 0,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x20,
+ .dmars = 4,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x30,
+ .dmars = 4,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x50,
+ .dmars = 8,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x60,
+ .dmars = 8,
+ .dmars_bit = 8,
+ }
+};
+
+static struct sh_dmae_channel sh7724_dmae1_channels[] = {
+ {
+ .offset = 0,
+ .dmars = 0,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x10,
+ .dmars = 0,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x20,
+ .dmars = 4,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x30,
+ .dmars = 4,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x50,
+ .dmars = 8,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x60,
+ .dmars = 8,
+ .dmars_bit = 8,
+ }
+};
+
+static unsigned int ts_shift[] = TS_SHIFT;
+
+static struct sh_dmae_pdata dma0_platform_data = {
+ .channel = sh7724_dmae0_channels,
+ .channel_num = ARRAY_SIZE(sh7724_dmae0_channels),
+ .ts_low_shift = CHCR_TS_LOW_SHIFT,
+ .ts_low_mask = CHCR_TS_LOW_MASK,
+ .ts_high_shift = CHCR_TS_HIGH_SHIFT,
+ .ts_high_mask = CHCR_TS_HIGH_MASK,
+ .ts_shift = ts_shift,
+ .ts_shift_num = ARRAY_SIZE(ts_shift),
+ .dmaor_init = DMAOR_INIT,
+};
+
+static struct sh_dmae_pdata dma1_platform_data = {
+ .channel = sh7724_dmae1_channels,
+ .channel_num = ARRAY_SIZE(sh7724_dmae1_channels),
+ .ts_low_shift = CHCR_TS_LOW_SHIFT,
+ .ts_low_mask = CHCR_TS_LOW_MASK,
+ .ts_high_shift = CHCR_TS_HIGH_SHIFT,
+ .ts_high_mask = CHCR_TS_HIGH_MASK,
+ .ts_shift = ts_shift,
+ .ts_shift_num = ARRAY_SIZE(ts_shift),
+ .dmaor_init = DMAOR_INIT,
+};
+
+/* Resource order important! */
+static struct resource sh7724_dmae0_resources[] = {
+ {
+ /* Channel registers and DMAOR */
+ .start = 0xfe008020,
+ .end = 0xfe00808f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ /* DMARSx */
+ .start = 0xfe009000,
+ .end = 0xfe00900b,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ /* DMA error IRQ */
+ .start = 78,
+ .end = 78,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channels 0-3 */
+ .start = 48,
+ .end = 51,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channels 4-5 */
+ .start = 76,
+ .end = 77,
+ .flags = IORESOURCE_IRQ,
+ },
};
-static struct platform_device dma_device = {
- .name = "sh-dma-engine",
- .id = -1,
- .dev = {
- .platform_data = &dma_platform_data,
+/* Resource order important! */
+static struct resource sh7724_dmae1_resources[] = {
+ {
+ /* Channel registers and DMAOR */
+ .start = 0xfdc08020,
+ .end = 0xfdc0808f,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ /* DMARSx */
+ .start = 0xfdc09000,
+ .end = 0xfdc0900b,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ /* DMA error IRQ */
+ .start = 74,
+ .end = 74,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channels 0-3 */
+ .start = 40,
+ .end = 43,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ /* IRQ for channels 4-5 */
+ .start = 72,
+ .end = 73,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device dma0_device = {
+ .name = "sh-dma-engine",
+ .id = 0,
+ .resource = sh7724_dmae0_resources,
+ .num_resources = ARRAY_SIZE(sh7724_dmae0_resources),
+ .dev = {
+ .platform_data = &dma0_platform_data,
+ },
+ .archdata = {
+ .hwblk_id = HWBLK_DMAC0,
+ },
+};
+
+static struct platform_device dma1_device = {
+ .name = "sh-dma-engine",
+ .id = 1,
+ .resource = sh7724_dmae1_resources,
+ .num_resources = ARRAY_SIZE(sh7724_dmae1_resources),
+ .dev = {
+ .platform_data = &dma1_platform_data,
+ },
+ .archdata = {
+ .hwblk_id = HWBLK_DMAC1,
},
};
@@ -663,7 +830,8 @@ static struct platform_device *sh7724_devices[] __initdata = {
&tmu3_device,
&tmu4_device,
&tmu5_device,
- &dma_device,
+ &dma0_device,
+ &dma1_device,
&rtc_device,
&iic0_device,
&iic1_device,
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
index f8f21618d78..02e792c90de 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7780.c
@@ -13,7 +13,10 @@
#include <linux/io.h>
#include <linux/serial_sci.h>
#include <linux/sh_timer.h>
-#include <asm/dma-sh.h>
+
+#include <asm/dmaengine.h>
+
+#include <cpu/dma-register.h>
static struct plat_sci_port scif0_platform_data = {
.mapbase = 0xffe00000,
@@ -247,15 +250,131 @@ static struct platform_device rtc_device = {
.resource = rtc_resources,
};
-static struct sh_dmae_pdata dma_platform_data = {
- .mode = (SHDMA_MIX_IRQ | SHDMA_DMAOR1),
+/* DMA */
+static struct sh_dmae_channel sh7780_dmae0_channels[] = {
+ {
+ .offset = 0,
+ .dmars = 0,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x10,
+ .dmars = 0,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x20,
+ .dmars = 4,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x30,
+ .dmars = 4,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x50,
+ .dmars = 8,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x60,
+ .dmars = 8,
+ .dmars_bit = 8,
+ }
+};
+
+static struct sh_dmae_channel sh7780_dmae1_channels[] = {
+ {
+ .offset = 0,
+ }, {
+ .offset = 0x10,
+ }, {
+ .offset = 0x20,
+ }, {
+ .offset = 0x30,
+ }, {
+ .offset = 0x50,
+ }, {
+ .offset = 0x60,
+ }
+};
+
+static unsigned int ts_shift[] = TS_SHIFT;
+
+static struct sh_dmae_pdata dma0_platform_data = {
+ .channel = sh7780_dmae0_channels,
+ .channel_num = ARRAY_SIZE(sh7780_dmae0_channels),
+ .ts_low_shift = CHCR_TS_LOW_SHIFT,
+ .ts_low_mask = CHCR_TS_LOW_MASK,
+ .ts_high_shift = CHCR_TS_HIGH_SHIFT,
+ .ts_high_mask = CHCR_TS_HIGH_MASK,
+ .ts_shift = ts_shift,
+ .ts_shift_num = ARRAY_SIZE(ts_shift),
+ .dmaor_init = DMAOR_INIT,
+};
+
+static struct sh_dmae_pdata dma1_platform_data = {
+ .channel = sh7780_dmae1_channels,
+ .channel_num = ARRAY_SIZE(sh7780_dmae1_channels),
+ .ts_low_shift = CHCR_TS_LOW_SHIFT,
+ .ts_low_mask = CHCR_TS_LOW_MASK,
+ .ts_high_shift = CHCR_TS_HIGH_SHIFT,
+ .ts_high_mask = CHCR_TS_HIGH_MASK,
+ .ts_shift = ts_shift,
+ .ts_shift_num = ARRAY_SIZE(ts_shift),
+ .dmaor_init = DMAOR_INIT,
};
-static struct platform_device dma_device = {
+static struct resource sh7780_dmae0_resources[] = {
+ [0] = {
+ /* Channel registers and DMAOR */
+ .start = 0xfc808020,
+ .end = 0xfc80808f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* DMARSx */
+ .start = 0xfc809000,
+ .end = 0xfc80900b,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ /* Real DMA error IRQ is 38, and channel IRQs are 34-37, 44-45 */
+ .start = 34,
+ .end = 34,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ },
+};
+
+static struct resource sh7780_dmae1_resources[] = {
+ [0] = {
+ /* Channel registers and DMAOR */
+ .start = 0xfc818020,
+ .end = 0xfc81808f,
+ .flags = IORESOURCE_MEM,
+ },
+ /* DMAC1 has no DMARS */
+ {
+ /* Real DMA error IRQ is 38, and channel IRQs are 46-47, 92-95 */
+ .start = 46,
+ .end = 46,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ },
+};
+
+static struct platform_device dma0_device = {
.name = "sh-dma-engine",
- .id = -1,
+ .id = 0,
+ .resource = sh7780_dmae0_resources,
+ .num_resources = ARRAY_SIZE(sh7780_dmae0_resources),
.dev = {
- .platform_data = &dma_platform_data,
+ .platform_data = &dma0_platform_data,
+ },
+};
+
+static struct platform_device dma1_device = {
+ .name = "sh-dma-engine",
+ .id = 1,
+ .resource = sh7780_dmae1_resources,
+ .num_resources = ARRAY_SIZE(sh7780_dmae1_resources),
+ .dev = {
+ .platform_data = &dma1_platform_data,
},
};
@@ -269,7 +388,8 @@ static struct platform_device *sh7780_devices[] __initdata = {
&tmu4_device,
&tmu5_device,
&rtc_device,
- &dma_device,
+ &dma0_device,
+ &dma1_device,
};
static int __init sh7780_devices_setup(void)
diff --git a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
index 23448d8c671..1fcd88b1671 100644
--- a/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
+++ b/arch/sh/kernel/cpu/sh4a/setup-sh7785.c
@@ -14,9 +14,12 @@
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/sh_timer.h>
-#include <asm/dma-sh.h>
+
+#include <asm/dmaengine.h>
#include <asm/mmzone.h>
+#include <cpu/dma-register.h>
+
static struct plat_sci_port scif0_platform_data = {
.mapbase = 0xffea0000,
.flags = UPF_BOOT_AUTOCONF,
@@ -295,15 +298,131 @@ static struct platform_device tmu5_device = {
.num_resources = ARRAY_SIZE(tmu5_resources),
};
-static struct sh_dmae_pdata dma_platform_data = {
- .mode = (SHDMA_MIX_IRQ | SHDMA_DMAOR1),
+/* DMA */
+static struct sh_dmae_channel sh7785_dmae0_channels[] = {
+ {
+ .offset = 0,
+ .dmars = 0,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x10,
+ .dmars = 0,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x20,
+ .dmars = 4,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x30,
+ .dmars = 4,
+ .dmars_bit = 8,
+ }, {
+ .offset = 0x50,
+ .dmars = 8,
+ .dmars_bit = 0,
+ }, {
+ .offset = 0x60,
+ .dmars = 8,
+ .dmars_bit = 8,
+ }
+};
+
+static struct sh_dmae_channel sh7785_dmae1_channels[] = {
+ {
+ .offset = 0,
+ }, {
+ .offset = 0x10,
+ }, {
+ .offset = 0x20,
+ }, {
+ .offset = 0x30,
+ }, {
+ .offset = 0x50,
+ }, {
+ .offset = 0x60,
+ }
+};
+
+static unsigned int ts_shift[] = TS_SHIFT;
+
+static struct sh_dmae_pdata dma0_platform_data = {
+ .channel = sh7785_dmae0_channels,
+ .channel_num = ARRAY_SIZE(sh7785_dmae0_channels),
+ .ts_low_shift = CHCR_TS_LOW_SHIFT,
+ .ts_low_mask = CHCR_TS_LOW_MASK,
+ .ts_high_shift = CHCR_TS_HIGH_SHIFT,
+ .ts_high_mask = CHCR_TS_HIGH_MASK,
+ .ts_shift = ts_shift,
+ .ts_shift_num = ARRAY_SIZE(ts_shift),
+ .dmaor_init = DMAOR_INIT,
+};
+
+static struct sh_dmae_pdata dma1_platform_data = {
+ .channel = sh7785_dmae1_channels,
+ .channel_num = ARRAY_SIZE(sh7785_dmae1_channels),
+ .ts_low_shift = CHCR_TS_LOW_SHIFT,
+ .ts_low_mask = CHCR_TS_LOW_MASK,
+ .ts_high_shift = CHCR_TS_HIGH_SHIFT,
+ .ts_high_mask = CHCR_TS_HIGH_MASK,
+ .ts_shift = ts_shift,
+ .ts_shift_num = ARRAY_SIZE(ts_shift),
+ .dmaor_init = DMAOR_INIT,
};
-static struct platform_device dma_device = {
+static struct resource sh7785_dmae0_resources[] = {
+ [0] = {
+ /* Channel registers and DMAOR */
+ .start = 0xfc808020,
+ .end = 0xfc80808f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ /* DMARSx */
+ .start = 0xfc809000,
+ .end = 0xfc80900b,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ /* Real DMA error IRQ is 39, and channel IRQs are 33-38 */
+ .start = 33,
+ .end = 33,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ },
+};
+
+static struct resource sh7785_dmae1_resources[] = {
+ [0] = {
+ /* Channel registers and DMAOR */
+ .start = 0xfcc08020,
+ .end = 0xfcc0808f,
+ .flags = IORESOURCE_MEM,
+ },
+ /* DMAC1 has no DMARS */
+ {
+ /* Real DMA error IRQ is 58, and channel IRQs are 52-57 */
+ .start = 52,
+ .end = 52,
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+ },
+};
+
+static struct platform_device dma0_device = {
.name = "sh-dma-engine",
- .id = -1,
+ .id = 0,
+ .resource = sh7785_dmae0_resources,
+ .num_resources = ARRAY_SIZE(sh7785_dmae0_resources),
.dev = {
- .platform_data = &dma_platform_data,
+ .platform_data = &dma0_platform_data,
+ },
+};
+
+static struct platform_device dma1_device = {
+ .name = "sh-dma-engine",
+ .id = 1,
+ .resource = sh7785_dmae1_resources,
+ .num_resources = ARRAY_SIZE(sh7785_dmae1_resources),
+ .dev = {
+ .platform_data = &dma1_platform_data,
},
};
@@ -320,7 +439,8 @@ static struct platform_device *sh7785_devices[] __initdata = {
&tmu3_device,
&tmu4_device,
&tmu5_device,
- &dma_device,
+ &dma0_device,
+ &dma1_device,
};
static int __init sh7785_devices_setup(void)
diff --git a/arch/sh/kernel/hw_breakpoint.c b/arch/sh/kernel/hw_breakpoint.c
index e2f1753d275..675eea7785d 100644
--- a/arch/sh/kernel/hw_breakpoint.c
+++ b/arch/sh/kernel/hw_breakpoint.c
@@ -143,26 +143,6 @@ static int arch_check_va_in_kernelspace(unsigned long va, u8 hbp_len)
return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE);
}
-/*
- * Store a breakpoint's encoded address, length, and type.
- */
-static int arch_store_info(struct perf_event *bp)
-{
- struct arch_hw_breakpoint *info = counter_arch_bp(bp);
-
- /*
- * User-space requests will always have the address field populated
- * For kernel-addresses, either the address or symbol name can be
- * specified.
- */
- if (info->name)
- info->address = (unsigned long)kallsyms_lookup_name(info->name);
- if (info->address)
- return 0;
-
- return -EINVAL;
-}
-
int arch_bp_generic_fields(int sh_len, int sh_type,
int *gen_len, int *gen_type)
{
@@ -276,10 +256,12 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp,
return ret;
}
- ret = arch_store_info(bp);
-
- if (ret < 0)
- return ret;
+ /*
+ * For kernel-addresses, either the address or symbol name can be
+ * specified.
+ */
+ if (info->name)
+ info->address = (unsigned long)kallsyms_lookup_name(info->name);
/*
* Check that the low-order bits of the address are appropriate
diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c
index 3459e70eed7..8870d6ba64b 100644
--- a/arch/sh/kernel/setup.c
+++ b/arch/sh/kernel/setup.c
@@ -443,7 +443,7 @@ void __init setup_arch(char **cmdline_p)
nodes_clear(node_online_map);
- /* Setup bootmem with available RAM */
+ pmb_init();
lmb_init();
setup_memory();
sparse_init();
@@ -452,7 +452,6 @@ void __init setup_arch(char **cmdline_p)
conswitchp = &dummy_con;
#endif
paging_init();
- pmb_init();
ioremap_fixed_init();
diff --git a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
index 953fa161331..8a0072de2bc 100644
--- a/arch/sh/kernel/time.c
+++ b/arch/sh/kernel/time.c
@@ -39,12 +39,12 @@ static int null_rtc_set_time(const time_t secs)
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
void read_persistent_clock(struct timespec *ts)
{
rtc_sh_get_time(ts);
}
+#ifdef CONFIG_GENERIC_CMOS_UPDATE
int update_persistent_clock(struct timespec now)
{
return rtc_sh_set_time(now.tv_sec);
@@ -113,9 +113,5 @@ void __init time_init(void)
hwblk_init();
clk_init();
- rtc_sh_get_time(&xtime);
- set_normalized_timespec(&wall_to_monotonic,
- -xtime.tv_sec, -xtime.tv_nsec);
-
late_time_init = sh_late_time_init;
}
diff --git a/arch/sh/lib/libgcc.h b/arch/sh/lib/libgcc.h
index 3f19d1c5d94..05909d58e2f 100644
--- a/arch/sh/lib/libgcc.h
+++ b/arch/sh/lib/libgcc.h
@@ -17,8 +17,7 @@ struct DWstruct {
#error I feel sick.
#endif
-typedef union
-{
+typedef union {
struct DWstruct s;
long long ll;
} DWunion;
diff --git a/arch/sh/mm/ioremap.c b/arch/sh/mm/ioremap.c
index c68d2d7d00a..1ab2385ecef 100644
--- a/arch/sh/mm/ioremap.c
+++ b/arch/sh/mm/ioremap.c
@@ -34,11 +34,12 @@
* caller shouldn't need to know that small detail.
*/
void __iomem * __init_refok
-__ioremap_caller(unsigned long phys_addr, unsigned long size,
+__ioremap_caller(phys_addr_t phys_addr, unsigned long size,
pgprot_t pgprot, void *caller)
{
struct vm_struct *area;
unsigned long offset, last_addr, addr, orig_addr;
+ void __iomem *mapped;
/* Don't allow wraparound or zero size */
last_addr = phys_addr + size - 1;
@@ -46,6 +47,20 @@ __ioremap_caller(unsigned long phys_addr, unsigned long size,
return NULL;
/*
+ * If we can't yet use the regular approach, go the fixmap route.
+ */
+ if (!mem_init_done)
+ return ioremap_fixed(phys_addr, size, pgprot);
+
+ /*
+ * First try to remap through the PMB.
+ * PMB entries are all pre-faulted.
+ */
+ mapped = pmb_remap_caller(phys_addr, size, pgprot, caller);
+ if (mapped && !IS_ERR(mapped))
+ return mapped;
+
+ /*
* Mappings have to be page-aligned
*/
offset = phys_addr & ~PAGE_MASK;
@@ -53,12 +68,6 @@ __ioremap_caller(unsigned long phys_addr, unsigned long size,
size = PAGE_ALIGN(last_addr+1) - phys_addr;
/*
- * If we can't yet use the regular approach, go the fixmap route.
- */
- if (!mem_init_done)
- return ioremap_fixed(phys_addr, offset, size, pgprot);
-
- /*
* Ok, go for it..
*/
area = get_vm_area_caller(size, VM_IOREMAP, caller);
@@ -67,33 +76,10 @@ __ioremap_caller(unsigned long phys_addr, unsigned long size,
area->phys_addr = phys_addr;
orig_addr = addr = (unsigned long)area->addr;
-#ifdef CONFIG_PMB
- /*
- * First try to remap through the PMB once a valid VMA has been
- * established. Smaller allocations (or the rest of the size
- * remaining after a PMB mapping due to the size not being
- * perfectly aligned on a PMB size boundary) are then mapped
- * through the UTLB using conventional page tables.
- *
- * PMB entries are all pre-faulted.
- */
- if (unlikely(phys_addr >= P1SEG)) {
- unsigned long mapped;
-
- mapped = pmb_remap(addr, phys_addr, size, pgprot);
- if (likely(mapped)) {
- addr += mapped;
- phys_addr += mapped;
- size -= mapped;
- }
+ if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) {
+ vunmap((void *)orig_addr);
+ return NULL;
}
-#endif
-
- if (likely(size))
- if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) {
- vunmap((void *)orig_addr);
- return NULL;
- }
return (void __iomem *)(offset + (char *)orig_addr);
}
@@ -133,23 +119,11 @@ void __iounmap(void __iomem *addr)
if (iounmap_fixed(addr) == 0)
return;
-#ifdef CONFIG_PMB
/*
- * Purge any PMB entries that may have been established for this
- * mapping, then proceed with conventional VMA teardown.
- *
- * XXX: Note that due to the way that remove_vm_area() does
- * matching of the resultant VMA, we aren't able to fast-forward
- * the address past the PMB space until the end of the VMA where
- * the page tables reside. As such, unmap_vm_area() will be
- * forced to linearly scan over the area until it finds the page
- * tables where PTEs that need to be unmapped actually reside,
- * which is far from optimal. Perhaps we need to use a separate
- * VMA for the PMB mappings?
- * -- PFM.
+ * If the PMB handled it, there's nothing else to do.
*/
- pmb_unmap(vaddr);
-#endif
+ if (pmb_unmap(addr) == 0)
+ return;
p = remove_vm_area((void *)(vaddr & PAGE_MASK));
if (!p) {
diff --git a/arch/sh/mm/ioremap_fixed.c b/arch/sh/mm/ioremap_fixed.c
index 0b78b1e20ef..7f682e5dafc 100644
--- a/arch/sh/mm/ioremap_fixed.c
+++ b/arch/sh/mm/ioremap_fixed.c
@@ -45,14 +45,21 @@ void __init ioremap_fixed_init(void)
}
void __init __iomem *
-ioremap_fixed(resource_size_t phys_addr, unsigned long offset,
- unsigned long size, pgprot_t prot)
+ioremap_fixed(phys_addr_t phys_addr, unsigned long size, pgprot_t prot)
{
enum fixed_addresses idx0, idx;
struct ioremap_map *map;
unsigned int nrpages;
+ unsigned long offset;
int i, slot;
+ /*
+ * Mappings have to be page-aligned
+ */
+ offset = phys_addr & ~PAGE_MASK;
+ phys_addr &= PAGE_MASK;
+ size = PAGE_ALIGN(phys_addr + size) - phys_addr;
+
slot = -1;
for (i = 0; i < FIX_N_IOREMAPS; i++) {
map = &ioremap_maps[i];
diff --git a/arch/sh/mm/numa.c b/arch/sh/mm/numa.c
index 422e9272187..961b34085e3 100644
--- a/arch/sh/mm/numa.c
+++ b/arch/sh/mm/numa.c
@@ -74,6 +74,9 @@ void __init setup_bootmem_node(int nid, unsigned long start, unsigned long end)
start_pfn = start >> PAGE_SHIFT;
end_pfn = end >> PAGE_SHIFT;
+ pmb_bolt_mapping((unsigned long)__va(start), start, end - start,
+ PAGE_KERNEL);
+
lmb_add(start, end - start);
__add_active_range(nid, start_pfn, end_pfn);
diff --git a/arch/sh/mm/pmb.c b/arch/sh/mm/pmb.c
index 198bcff5e96..a4662e2782c 100644
--- a/arch/sh/mm/pmb.c
+++ b/arch/sh/mm/pmb.c
@@ -23,7 +23,8 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/spinlock.h>
-#include <linux/rwlock.h>
+#include <linux/vmalloc.h>
+#include <asm/cacheflush.h>
#include <asm/sizes.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -52,12 +53,24 @@ struct pmb_entry {
struct pmb_entry *link;
};
+static struct {
+ unsigned long size;
+ int flag;
+} pmb_sizes[] = {
+ { .size = SZ_512M, .flag = PMB_SZ_512M, },
+ { .size = SZ_128M, .flag = PMB_SZ_128M, },
+ { .size = SZ_64M, .flag = PMB_SZ_64M, },
+ { .size = SZ_16M, .flag = PMB_SZ_16M, },
+};
+
static void pmb_unmap_entry(struct pmb_entry *, int depth);
static DEFINE_RWLOCK(pmb_rwlock);
static struct pmb_entry pmb_entry_list[NR_PMB_ENTRIES];
static DECLARE_BITMAP(pmb_map, NR_PMB_ENTRIES);
+static unsigned int pmb_iomapping_enabled;
+
static __always_inline unsigned long mk_pmb_entry(unsigned int entry)
{
return (entry & PMB_E_MASK) << PMB_E_SHIFT;
@@ -73,6 +86,142 @@ static __always_inline unsigned long mk_pmb_data(unsigned int entry)
return mk_pmb_entry(entry) | PMB_DATA;
}
+static __always_inline unsigned int pmb_ppn_in_range(unsigned long ppn)
+{
+ return ppn >= __pa(memory_start) && ppn < __pa(memory_end);
+}
+
+/*
+ * Ensure that the PMB entries match our cache configuration.
+ *
+ * When we are in 32-bit address extended mode, CCR.CB becomes
+ * invalid, so care must be taken to manually adjust cacheable
+ * translations.
+ */
+static __always_inline unsigned long pmb_cache_flags(void)
+{
+ unsigned long flags = 0;
+
+#if defined(CONFIG_CACHE_OFF)
+ flags |= PMB_WT | PMB_UB;
+#elif defined(CONFIG_CACHE_WRITETHROUGH)
+ flags |= PMB_C | PMB_WT | PMB_UB;
+#elif defined(CONFIG_CACHE_WRITEBACK)
+ flags |= PMB_C;
+#endif
+
+ return flags;
+}
+
+/*
+ * Convert typical pgprot value to the PMB equivalent
+ */
+static inline unsigned long pgprot_to_pmb_flags(pgprot_t prot)
+{
+ unsigned long pmb_flags = 0;
+ u64 flags = pgprot_val(prot);
+
+ if (flags & _PAGE_CACHABLE)
+ pmb_flags |= PMB_C;
+ if (flags & _PAGE_WT)
+ pmb_flags |= PMB_WT | PMB_UB;
+
+ return pmb_flags;
+}
+
+static inline bool pmb_can_merge(struct pmb_entry *a, struct pmb_entry *b)
+{
+ return (b->vpn == (a->vpn + a->size)) &&
+ (b->ppn == (a->ppn + a->size)) &&
+ (b->flags == a->flags);
+}
+
+static bool pmb_mapping_exists(unsigned long vaddr, phys_addr_t phys,
+ unsigned long size)
+{
+ int i;
+
+ read_lock(&pmb_rwlock);
+
+ for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
+ struct pmb_entry *pmbe, *iter;
+ unsigned long span;
+
+ if (!test_bit(i, pmb_map))
+ continue;
+
+ pmbe = &pmb_entry_list[i];
+
+ /*
+ * See if VPN and PPN are bounded by an existing mapping.
+ */
+ if ((vaddr < pmbe->vpn) || (vaddr >= (pmbe->vpn + pmbe->size)))
+ continue;
+ if ((phys < pmbe->ppn) || (phys >= (pmbe->ppn + pmbe->size)))
+ continue;
+
+ /*
+ * Now see if we're in range of a simple mapping.
+ */
+ if (size <= pmbe->size) {
+ read_unlock(&pmb_rwlock);
+ return true;
+ }
+
+ span = pmbe->size;
+
+ /*
+ * Finally for sizes that involve compound mappings, walk
+ * the chain.
+ */
+ for (iter = pmbe->link; iter; iter = iter->link)
+ span += iter->size;
+
+ /*
+ * Nothing else to do if the range requirements are met.
+ */
+ if (size <= span) {
+ read_unlock(&pmb_rwlock);
+ return true;
+ }
+ }
+
+ read_unlock(&pmb_rwlock);
+ return false;
+}
+
+static bool pmb_size_valid(unsigned long size)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++)
+ if (pmb_sizes[i].size == size)
+ return true;
+
+ return false;
+}
+
+static inline bool pmb_addr_valid(unsigned long addr, unsigned long size)
+{
+ return (addr >= P1SEG && (addr + size - 1) < P3SEG);
+}
+
+static inline bool pmb_prot_valid(pgprot_t prot)
+{
+ return (pgprot_val(prot) & _PAGE_USER) == 0;
+}
+
+static int pmb_size_to_flags(unsigned long size)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++)
+ if (pmb_sizes[i].size == size)
+ return pmb_sizes[i].flag;
+
+ return 0;
+}
+
static int pmb_alloc_entry(void)
{
int pos;
@@ -140,33 +289,22 @@ static void pmb_free(struct pmb_entry *pmbe)
}
/*
- * Ensure that the PMB entries match our cache configuration.
- *
- * When we are in 32-bit address extended mode, CCR.CB becomes
- * invalid, so care must be taken to manually adjust cacheable
- * translations.
+ * Must be run uncached.
*/
-static __always_inline unsigned long pmb_cache_flags(void)
+static void __set_pmb_entry(struct pmb_entry *pmbe)
{
- unsigned long flags = 0;
+ unsigned long addr, data;
-#if defined(CONFIG_CACHE_WRITETHROUGH)
- flags |= PMB_C | PMB_WT | PMB_UB;
-#elif defined(CONFIG_CACHE_WRITEBACK)
- flags |= PMB_C;
-#endif
+ addr = mk_pmb_addr(pmbe->entry);
+ data = mk_pmb_data(pmbe->entry);
- return flags;
-}
+ jump_to_uncached();
-/*
- * Must be run uncached.
- */
-static void __set_pmb_entry(struct pmb_entry *pmbe)
-{
- writel_uncached(pmbe->vpn | PMB_V, mk_pmb_addr(pmbe->entry));
- writel_uncached(pmbe->ppn | pmbe->flags | PMB_V,
- mk_pmb_data(pmbe->entry));
+ /* Set V-bit */
+ __raw_writel(pmbe->vpn | PMB_V, addr);
+ __raw_writel(pmbe->ppn | pmbe->flags | PMB_V, data);
+
+ back_to_cached();
}
static void __clear_pmb_entry(struct pmb_entry *pmbe)
@@ -194,144 +332,155 @@ static void set_pmb_entry(struct pmb_entry *pmbe)
spin_unlock_irqrestore(&pmbe->lock, flags);
}
-static struct {
- unsigned long size;
- int flag;
-} pmb_sizes[] = {
- { .size = SZ_512M, .flag = PMB_SZ_512M, },
- { .size = SZ_128M, .flag = PMB_SZ_128M, },
- { .size = SZ_64M, .flag = PMB_SZ_64M, },
- { .size = SZ_16M, .flag = PMB_SZ_16M, },
-};
-
-long pmb_remap(unsigned long vaddr, unsigned long phys,
- unsigned long size, pgprot_t prot)
+int pmb_bolt_mapping(unsigned long vaddr, phys_addr_t phys,
+ unsigned long size, pgprot_t prot)
{
struct pmb_entry *pmbp, *pmbe;
- unsigned long wanted;
- int pmb_flags, i;
- long err;
- u64 flags;
+ unsigned long orig_addr, orig_size;
+ unsigned long flags, pmb_flags;
+ int i, mapped;
- flags = pgprot_val(prot);
+ if (!pmb_addr_valid(vaddr, size))
+ return -EFAULT;
+ if (pmb_mapping_exists(vaddr, phys, size))
+ return 0;
- pmb_flags = PMB_WT | PMB_UB;
-
- /* Convert typical pgprot value to the PMB equivalent */
- if (flags & _PAGE_CACHABLE) {
- pmb_flags |= PMB_C;
+ orig_addr = vaddr;
+ orig_size = size;
- if ((flags & _PAGE_WT) == 0)
- pmb_flags &= ~(PMB_WT | PMB_UB);
- }
+ flush_tlb_kernel_range(vaddr, vaddr + size);
+ pmb_flags = pgprot_to_pmb_flags(prot);
pmbp = NULL;
- wanted = size;
-again:
- for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++) {
- unsigned long flags;
+ do {
+ for (i = mapped = 0; i < ARRAY_SIZE(pmb_sizes); i++) {
+ if (size < pmb_sizes[i].size)
+ continue;
+
+ pmbe = pmb_alloc(vaddr, phys, pmb_flags |
+ pmb_sizes[i].flag, PMB_NO_ENTRY);
+ if (IS_ERR(pmbe)) {
+ pmb_unmap_entry(pmbp, mapped);
+ return PTR_ERR(pmbe);
+ }
- if (size < pmb_sizes[i].size)
- continue;
+ spin_lock_irqsave(&pmbe->lock, flags);
- pmbe = pmb_alloc(vaddr, phys, pmb_flags | pmb_sizes[i].flag,
- PMB_NO_ENTRY);
- if (IS_ERR(pmbe)) {
- err = PTR_ERR(pmbe);
- goto out;
- }
+ pmbe->size = pmb_sizes[i].size;
- spin_lock_irqsave(&pmbe->lock, flags);
+ __set_pmb_entry(pmbe);
- __set_pmb_entry(pmbe);
+ phys += pmbe->size;
+ vaddr += pmbe->size;
+ size -= pmbe->size;
- phys += pmb_sizes[i].size;
- vaddr += pmb_sizes[i].size;
- size -= pmb_sizes[i].size;
+ /*
+ * Link adjacent entries that span multiple PMB
+ * entries for easier tear-down.
+ */
+ if (likely(pmbp)) {
+ spin_lock(&pmbp->lock);
+ pmbp->link = pmbe;
+ spin_unlock(&pmbp->lock);
+ }
- pmbe->size = pmb_sizes[i].size;
+ pmbp = pmbe;
- /*
- * Link adjacent entries that span multiple PMB entries
- * for easier tear-down.
- */
- if (likely(pmbp)) {
- spin_lock(&pmbp->lock);
- pmbp->link = pmbe;
- spin_unlock(&pmbp->lock);
+ /*
+ * Instead of trying smaller sizes on every
+ * iteration (even if we succeed in allocating
+ * space), try using pmb_sizes[i].size again.
+ */
+ i--;
+ mapped++;
+
+ spin_unlock_irqrestore(&pmbe->lock, flags);
}
+ } while (size >= SZ_16M);
- pmbp = pmbe;
+ flush_cache_vmap(orig_addr, orig_addr + orig_size);
- /*
- * Instead of trying smaller sizes on every iteration
- * (even if we succeed in allocating space), try using
- * pmb_sizes[i].size again.
- */
- i--;
+ return 0;
+}
- spin_unlock_irqrestore(&pmbe->lock, flags);
- }
+void __iomem *pmb_remap_caller(phys_addr_t phys, unsigned long size,
+ pgprot_t prot, void *caller)
+{
+ unsigned long vaddr;
+ phys_addr_t offset, last_addr;
+ phys_addr_t align_mask;
+ unsigned long aligned;
+ struct vm_struct *area;
+ int i, ret;
- if (size >= SZ_16M)
- goto again;
+ if (!pmb_iomapping_enabled)
+ return NULL;
- return wanted - size;
+ /*
+ * Small mappings need to go through the TLB.
+ */
+ if (size < SZ_16M)
+ return ERR_PTR(-EINVAL);
+ if (!pmb_prot_valid(prot))
+ return ERR_PTR(-EINVAL);
-out:
- pmb_unmap_entry(pmbp, NR_PMB_ENTRIES);
+ for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++)
+ if (size >= pmb_sizes[i].size)
+ break;
+
+ last_addr = phys + size;
+ align_mask = ~(pmb_sizes[i].size - 1);
+ offset = phys & ~align_mask;
+ phys &= align_mask;
+ aligned = ALIGN(last_addr, pmb_sizes[i].size) - phys;
+
+ /*
+ * XXX: This should really start from uncached_end, but this
+ * causes the MMU to reset, so for now we restrict it to the
+ * 0xb000...0xc000 range.
+ */
+ area = __get_vm_area_caller(aligned, VM_IOREMAP, 0xb0000000,
+ P3SEG, caller);
+ if (!area)
+ return NULL;
+
+ area->phys_addr = phys;
+ vaddr = (unsigned long)area->addr;
+
+ ret = pmb_bolt_mapping(vaddr, phys, size, prot);
+ if (unlikely(ret != 0))
+ return ERR_PTR(ret);
- return err;
+ return (void __iomem *)(offset + (char *)vaddr);
}
-void pmb_unmap(unsigned long addr)
+int pmb_unmap(void __iomem *addr)
{
struct pmb_entry *pmbe = NULL;
- int i;
+ unsigned long vaddr = (unsigned long __force)addr;
+ int i, found = 0;
read_lock(&pmb_rwlock);
for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
if (test_bit(i, pmb_map)) {
pmbe = &pmb_entry_list[i];
- if (pmbe->vpn == addr)
+ if (pmbe->vpn == vaddr) {
+ found = 1;
break;
+ }
}
}
read_unlock(&pmb_rwlock);
- pmb_unmap_entry(pmbe, NR_PMB_ENTRIES);
-}
-
-static bool pmb_can_merge(struct pmb_entry *a, struct pmb_entry *b)
-{
- return (b->vpn == (a->vpn + a->size)) &&
- (b->ppn == (a->ppn + a->size)) &&
- (b->flags == a->flags);
-}
-
-static bool pmb_size_valid(unsigned long size)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++)
- if (pmb_sizes[i].size == size)
- return true;
-
- return false;
-}
-
-static int pmb_size_to_flags(unsigned long size)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(pmb_sizes); i++)
- if (pmb_sizes[i].size == size)
- return pmb_sizes[i].flag;
+ if (found) {
+ pmb_unmap_entry(pmbe, NR_PMB_ENTRIES);
+ return 0;
+ }
- return 0;
+ return -EINVAL;
}
static void __pmb_unmap_entry(struct pmb_entry *pmbe, int depth)
@@ -351,6 +500,8 @@ static void __pmb_unmap_entry(struct pmb_entry *pmbe, int depth)
*/
__clear_pmb_entry(pmbe);
+ flush_cache_vunmap(pmbe->vpn, pmbe->vpn + pmbe->size);
+
pmbe = pmblink->link;
pmb_free(pmblink);
@@ -369,11 +520,6 @@ static void pmb_unmap_entry(struct pmb_entry *pmbe, int depth)
write_unlock_irqrestore(&pmb_rwlock, flags);
}
-static __always_inline unsigned int pmb_ppn_in_range(unsigned long ppn)
-{
- return ppn >= __pa(memory_start) && ppn < __pa(memory_end);
-}
-
static void __init pmb_notify(void)
{
int i;
@@ -625,6 +771,18 @@ static void __init pmb_resize(void)
}
#endif
+static int __init early_pmb(char *p)
+{
+ if (!p)
+ return 0;
+
+ if (strstr(p, "iomap"))
+ pmb_iomapping_enabled = 1;
+
+ return 0;
+}
+early_param("pmb", early_pmb);
+
void __init pmb_init(void)
{
/* Synchronize software state */
@@ -713,7 +871,7 @@ static int __init pmb_debugfs_init(void)
return 0;
}
-postcore_initcall(pmb_debugfs_init);
+subsys_initcall(pmb_debugfs_init);
#ifdef CONFIG_PM
static int pmb_sysdev_suspend(struct sys_device *dev, pm_message_t state)
diff --git a/arch/um/.gitignore b/arch/um/.gitignore
new file mode 100644
index 00000000000..a73d3a1cc74
--- /dev/null
+++ b/arch/um/.gitignore
@@ -0,0 +1,3 @@
+kernel/config.c
+kernel/config.tmp
+kernel/vmlinux.lds
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index cf8a97f3451..64cda95f59c 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -18,10 +18,10 @@ static irqreturn_t line_interrupt(int irq, void *data)
{
struct chan *chan = data;
struct line *line = chan->line;
- struct tty_struct *tty = line->tty;
+ struct tty_struct *tty;
if (line)
- chan_interrupt(&line->chan_list, &line->task, tty, irq);
+ chan_interrupt(&line->chan_list, &line->task, line->tty, irq);
return IRQ_HANDLED;
}
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 1b549bca464..804b28dd032 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -6,6 +6,8 @@ obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \
sys_call_table.o tls.o
+obj-$(CONFIG_BINFMT_ELF) += elfcore.o
+
subarch-obj-y = lib/semaphore_32.o lib/string_32.o
subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o
subarch-obj-$(CONFIG_MODULES) += kernel/module.o
diff --git a/arch/um/sys-i386/asm/elf.h b/arch/um/sys-i386/asm/elf.h
index 770885472ed..e64cd41d7ba 100644
--- a/arch/um/sys-i386/asm/elf.h
+++ b/arch/um/sys-i386/asm/elf.h
@@ -116,47 +116,4 @@ do { \
} \
} while (0)
-/*
- * These macros parameterize elf_core_dump in fs/binfmt_elf.c to write out
- * extra segments containing the vsyscall DSO contents. Dumping its
- * contents makes post-mortem fully interpretable later without matching up
- * the same kernel and hardware config to see what PC values meant.
- * Dumping its extra ELF program headers includes all the other information
- * a debugger needs to easily find how the vsyscall DSO was being used.
- */
-#define ELF_CORE_EXTRA_PHDRS \
- (vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0 )
-
-#define ELF_CORE_WRITE_EXTRA_PHDRS \
-if ( vsyscall_ehdr ) { \
- const struct elfhdr *const ehdrp = (struct elfhdr *)vsyscall_ehdr; \
- const struct elf_phdr *const phdrp = \
- (const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff); \
- int i; \
- Elf32_Off ofs = 0; \
- for (i = 0; i < ehdrp->e_phnum; ++i) { \
- struct elf_phdr phdr = phdrp[i]; \
- if (phdr.p_type == PT_LOAD) { \
- ofs = phdr.p_offset = offset; \
- offset += phdr.p_filesz; \
- } \
- else \
- phdr.p_offset += ofs; \
- phdr.p_paddr = 0; /* match other core phdrs */ \
- DUMP_WRITE(&phdr, sizeof(phdr)); \
- } \
-}
-#define ELF_CORE_WRITE_EXTRA_DATA \
-if ( vsyscall_ehdr ) { \
- const struct elfhdr *const ehdrp = (struct elfhdr *)vsyscall_ehdr; \
- const struct elf_phdr *const phdrp = \
- (const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff); \
- int i; \
- for (i = 0; i < ehdrp->e_phnum; ++i) { \
- if (phdrp[i].p_type == PT_LOAD) \
- DUMP_WRITE((void *) phdrp[i].p_vaddr, \
- phdrp[i].p_filesz); \
- } \
-}
-
#endif
diff --git a/arch/um/sys-i386/elfcore.c b/arch/um/sys-i386/elfcore.c
new file mode 100644
index 00000000000..6bb49b687c9
--- /dev/null
+++ b/arch/um/sys-i386/elfcore.c
@@ -0,0 +1,83 @@
+#include <linux/elf.h>
+#include <linux/coredump.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+
+#include <asm/elf.h>
+
+
+Elf32_Half elf_core_extra_phdrs(void)
+{
+ return vsyscall_ehdr ? (((struct elfhdr *)vsyscall_ehdr)->e_phnum) : 0;
+}
+
+int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
+ unsigned long limit)
+{
+ if ( vsyscall_ehdr ) {
+ const struct elfhdr *const ehdrp =
+ (struct elfhdr *) vsyscall_ehdr;
+ const struct elf_phdr *const phdrp =
+ (const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
+ int i;
+ Elf32_Off ofs = 0;
+
+ for (i = 0; i < ehdrp->e_phnum; ++i) {
+ struct elf_phdr phdr = phdrp[i];
+
+ if (phdr.p_type == PT_LOAD) {
+ ofs = phdr.p_offset = offset;
+ offset += phdr.p_filesz;
+ } else {
+ phdr.p_offset += ofs;
+ }
+ phdr.p_paddr = 0; /* match other core phdrs */
+ *size += sizeof(phdr);
+ if (*size > limit
+ || !dump_write(file, &phdr, sizeof(phdr)))
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int elf_core_write_extra_data(struct file *file, size_t *size,
+ unsigned long limit)
+{
+ if ( vsyscall_ehdr ) {
+ const struct elfhdr *const ehdrp =
+ (struct elfhdr *) vsyscall_ehdr;
+ const struct elf_phdr *const phdrp =
+ (const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
+ int i;
+
+ for (i = 0; i < ehdrp->e_phnum; ++i) {
+ if (phdrp[i].p_type == PT_LOAD) {
+ void *addr = (void *) phdrp[i].p_vaddr;
+ size_t filesz = phdrp[i].p_filesz;
+
+ *size += filesz;
+ if (*size > limit
+ || !dump_write(file, addr, filesz))
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+
+size_t elf_core_extra_data_size(void)
+{
+ if ( vsyscall_ehdr ) {
+ const struct elfhdr *const ehdrp =
+ (struct elfhdr *)vsyscall_ehdr;
+ const struct elf_phdr *const phdrp =
+ (const struct elf_phdr *) (vsyscall_ehdr + ehdrp->e_phoff);
+ int i;
+
+ for (i = 0; i < ehdrp->e_phnum; ++i)
+ if (phdrp[i].p_type == PT_LOAD)
+ return (size_t) phdrp[i].p_filesz;
+ }
+ return 0;
+}
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index f15f37bfbd6..e9844037152 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -393,8 +393,12 @@ config X86_ELAN
config X86_MRST
bool "Moorestown MID platform"
+ depends on PCI
+ depends on PCI_GOANY
depends on X86_32
depends on X86_EXTENDED_PLATFORM
+ depends on X86_IO_APIC
+ select APB_TIMER
---help---
Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin
Internet Device(MID) platform. Moorestown consists of two chips:
@@ -429,6 +433,7 @@ config X86_32_NON_STANDARD
config X86_NUMAQ
bool "NUMAQ (IBM/Sequent)"
depends on X86_32_NON_STANDARD
+ depends on PCI
select NUMA
select X86_MPPARSE
---help---
@@ -629,6 +634,16 @@ config HPET_EMULATE_RTC
def_bool y
depends on HPET_TIMER && (RTC=y || RTC=m || RTC_DRV_CMOS=m || RTC_DRV_CMOS=y)
+config APB_TIMER
+ def_bool y if MRST
+ prompt "Langwell APB Timer Support" if X86_MRST
+ help
+ APB timer is the replacement for 8254, HPET on X86 MID platforms.
+ The APBT provides a stable time base on SMP
+ systems, unlike the TSC, but it is more expensive to access,
+ as it is off-chip. APB timers are always running regardless of CPU
+ C states, they are used as per CPU clockevent device when possible.
+
# Mark as embedded because too many people got it wrong.
# The code disables itself when not needed.
config DMI
diff --git a/arch/x86/include/asm/apb_timer.h b/arch/x86/include/asm/apb_timer.h
new file mode 100644
index 00000000000..c74a2eebe57
--- /dev/null
+++ b/arch/x86/include/asm/apb_timer.h
@@ -0,0 +1,70 @@
+/*
+ * apb_timer.h: Driver for Langwell APB timer based on Synopsis DesignWare
+ *
+ * (C) Copyright 2009 Intel Corporation
+ * Author: Jacob Pan (jacob.jun.pan@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; version 2
+ * of the License.
+ *
+ * Note:
+ */
+
+#ifndef ASM_X86_APBT_H
+#define ASM_X86_APBT_H
+#include <linux/sfi.h>
+
+#ifdef CONFIG_APB_TIMER
+
+/* Langwell DW APB timer registers */
+#define APBTMR_N_LOAD_COUNT 0x00
+#define APBTMR_N_CURRENT_VALUE 0x04
+#define APBTMR_N_CONTROL 0x08
+#define APBTMR_N_EOI 0x0c
+#define APBTMR_N_INT_STATUS 0x10
+
+#define APBTMRS_INT_STATUS 0xa0
+#define APBTMRS_EOI 0xa4
+#define APBTMRS_RAW_INT_STATUS 0xa8
+#define APBTMRS_COMP_VERSION 0xac
+#define APBTMRS_REG_SIZE 0x14
+
+/* register bits */
+#define APBTMR_CONTROL_ENABLE (1<<0)
+#define APBTMR_CONTROL_MODE_PERIODIC (1<<1) /*1: periodic 0:free running */
+#define APBTMR_CONTROL_INT (1<<2)
+
+/* default memory mapped register base */
+#define LNW_SCU_ADDR 0xFF100000
+#define LNW_EXT_TIMER_OFFSET 0x1B800
+#define APBT_DEFAULT_BASE (LNW_SCU_ADDR+LNW_EXT_TIMER_OFFSET)
+#define LNW_EXT_TIMER_PGOFFSET 0x800
+
+/* APBT clock speed range from PCLK to fabric base, 25-100MHz */
+#define APBT_MAX_FREQ 50
+#define APBT_MIN_FREQ 1
+#define APBT_MMAP_SIZE 1024
+
+#define APBT_DEV_USED 1
+
+extern void apbt_time_init(void);
+extern struct clock_event_device *global_clock_event;
+extern unsigned long apbt_quick_calibrate(void);
+extern int arch_setup_apbt_irqs(int irq, int trigger, int mask, int cpu);
+extern void apbt_setup_secondary_clock(void);
+extern unsigned int boot_cpu_id;
+extern int disable_apbt_percpu;
+
+extern struct sfi_timer_table_entry *sfi_get_mtmr(int hint);
+extern void sfi_free_mtmr(struct sfi_timer_table_entry *mtmr);
+extern int sfi_mtimer_num;
+
+#else /* CONFIG_APB_TIMER */
+
+static inline unsigned long apbt_quick_calibrate(void) {return 0; }
+static inline void apbt_time_init(void) {return 0; }
+
+#endif
+#endif /* ASM_X86_APBT_H */
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index eeac829a0f4..a929c9ede33 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -53,13 +53,6 @@ extern void threshold_interrupt(void);
extern void call_function_interrupt(void);
extern void call_function_single_interrupt(void);
-/* PIC specific functions */
-extern void disable_8259A_irq(unsigned int irq);
-extern void enable_8259A_irq(unsigned int irq);
-extern int i8259A_irq_pending(unsigned int irq);
-extern void make_8259A_irq(unsigned int irq);
-extern void init_8259A(int aeoi);
-
/* IOAPIC */
#define IO_APIC_IRQ(x) (((x) >= NR_IRQS_LEGACY) || ((1<<(x)) & io_apic_irqs))
extern unsigned long io_apic_irqs;
diff --git a/arch/x86/include/asm/i8259.h b/arch/x86/include/asm/i8259.h
index 7ec65b18085..1655147646a 100644
--- a/arch/x86/include/asm/i8259.h
+++ b/arch/x86/include/asm/i8259.h
@@ -26,11 +26,6 @@ extern unsigned int cached_irq_mask;
extern raw_spinlock_t i8259A_lock;
-extern void init_8259A(int auto_eoi);
-extern void enable_8259A_irq(unsigned int irq);
-extern void disable_8259A_irq(unsigned int irq);
-extern unsigned int startup_8259A_irq(unsigned int irq);
-
/* the PIC may need a careful delay on some platforms, hence specific calls */
static inline unsigned char inb_pic(unsigned int port)
{
@@ -57,7 +52,17 @@ static inline void outb_pic(unsigned char value, unsigned int port)
extern struct irq_chip i8259A_chip;
-extern void mask_8259A(void);
-extern void unmask_8259A(void);
+struct legacy_pic {
+ int nr_legacy_irqs;
+ struct irq_chip *chip;
+ void (*mask_all)(void);
+ void (*restore_mask)(void);
+ void (*init)(int auto_eoi);
+ int (*irq_pending)(unsigned int irq);
+ void (*make_irq)(unsigned int irq);
+};
+
+extern struct legacy_pic *legacy_pic;
+extern struct legacy_pic null_legacy_pic;
#endif /* _ASM_X86_I8259_H */
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
index 5f61f6e0ffd..35832a03a51 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -143,8 +143,6 @@ extern int noioapicreroute;
/* 1 if the timer IRQ uses the '8259A Virtual Wire' mode */
extern int timer_through_8259;
-extern void io_apic_disable_legacy(void);
-
/*
* If we use the IO-APIC for IRQ routing, disable automatic
* assignment of PCI IRQ's.
@@ -189,6 +187,7 @@ extern struct mp_ioapic_gsi mp_gsi_routing[];
int mp_find_ioapic(int gsi);
int mp_find_ioapic_pin(int ioapic, int gsi);
void __init mp_register_ioapic(int id, u32 address, u32 gsi_base);
+extern void __init pre_init_apic_IRQ0(void);
#else /* !CONFIG_X86_IO_APIC */
@@ -198,7 +197,11 @@ static const int timer_through_8259 = 0;
static inline void ioapic_init_mappings(void) { }
static inline void ioapic_insert_resources(void) { }
static inline void probe_nr_irqs_gsi(void) { }
+static inline int mp_find_ioapic(int gsi) { return 0; }
+struct io_apic_irq_attr;
+static inline int io_apic_set_pci_routing(struct device *dev, int irq,
+ struct io_apic_irq_attr *irq_attr) { return 0; }
#endif
#endif /* _ASM_X86_IO_APIC_H */
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h
index 262292729fc..5458380b6ef 100644
--- a/arch/x86/include/asm/irq.h
+++ b/arch/x86/include/asm/irq.h
@@ -48,6 +48,5 @@ extern DECLARE_BITMAP(used_vectors, NR_VECTORS);
extern int vector_used_by_percpu_irq(unsigned int vector);
extern void init_ISA_irqs(void);
-extern int nr_legacy_irqs;
#endif /* _ASM_X86_IRQ_H */
diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h
new file mode 100644
index 00000000000..451d30e7f62
--- /dev/null
+++ b/arch/x86/include/asm/mrst.h
@@ -0,0 +1,19 @@
+/*
+ * mrst.h: Intel Moorestown platform specific setup code
+ *
+ * (C) Copyright 2009 Intel 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; version 2
+ * of the License.
+ */
+#ifndef _ASM_X86_MRST_H
+#define _ASM_X86_MRST_H
+extern int pci_mrst_init(void);
+int __init sfi_parse_mrtc(struct sfi_table_header *table);
+
+#define SFI_MTMR_MAX_NUM 8
+#define SFI_MRTC_MAX 8
+
+#endif /* _ASM_X86_MRST_H */
diff --git a/arch/x86/include/asm/numaq.h b/arch/x86/include/asm/numaq.h
index 13370b95ea9..37c516545ec 100644
--- a/arch/x86/include/asm/numaq.h
+++ b/arch/x86/include/asm/numaq.h
@@ -30,6 +30,7 @@
extern int found_numaq;
extern int get_memcfg_numaq(void);
+extern int pci_numaq_init(void);
extern void *xquad_portio;
diff --git a/arch/x86/include/asm/olpc.h b/arch/x86/include/asm/olpc.h
index 3a57385d9fa..101229b0d8e 100644
--- a/arch/x86/include/asm/olpc.h
+++ b/arch/x86/include/asm/olpc.h
@@ -13,7 +13,6 @@ struct olpc_platform_t {
#define OLPC_F_PRESENT 0x01
#define OLPC_F_DCON 0x02
-#define OLPC_F_VSA 0x04
#ifdef CONFIG_OLPC
@@ -51,18 +50,6 @@ static inline int olpc_has_dcon(void)
}
/*
- * The VSA is software from AMD that typical Geode bioses will include.
- * It is used to emulate the PCI bus, VGA, etc. OLPC's Open Firmware does
- * not include the VSA; instead, PCI is emulated by the kernel.
- *
- * The VSA is described further in arch/x86/pci/olpc.c.
- */
-static inline int olpc_has_vsa(void)
-{
- return (olpc_platform_info.flags & OLPC_F_VSA) ? 1 : 0;
-}
-
-/*
* The "Mass Production" version of OLPC's XO is identified as being model
* C2. During the prototype phase, the following models (in chronological
* order) were created: A1, B1, B2, B3, B4, C1. The A1 through B2 models
@@ -87,13 +74,10 @@ static inline int olpc_has_dcon(void)
return 0;
}
-static inline int olpc_has_vsa(void)
-{
- return 0;
-}
-
#endif
+extern int pci_olpc_init(void);
+
/* EC related functions */
extern int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen,
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index b4a00dd4eed..3e002ca5a28 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -45,8 +45,15 @@ static inline int pci_proc_domain(struct pci_bus *bus)
#ifdef CONFIG_PCI
extern unsigned int pcibios_assign_all_busses(void);
+extern int pci_legacy_init(void);
+# ifdef CONFIG_ACPI
+# define x86_default_pci_init pci_acpi_init
+# else
+# define x86_default_pci_init pci_legacy_init
+# endif
#else
-#define pcibios_assign_all_busses() 0
+# define pcibios_assign_all_busses() 0
+# define x86_default_pci_init NULL
#endif
extern unsigned long pci_mem_start;
diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
index 05b58ccb2e8..1a0422348d6 100644
--- a/arch/x86/include/asm/pci_x86.h
+++ b/arch/x86/include/asm/pci_x86.h
@@ -83,7 +83,6 @@ struct irq_routing_table {
extern unsigned int pcibios_irq_mask;
-extern int pcibios_scanned;
extern spinlock_t pci_config_lock;
extern int (*pcibios_enable_irq)(struct pci_dev *dev);
@@ -106,16 +105,15 @@ extern bool port_cf9_safe;
extern int pci_direct_probe(void);
extern void pci_direct_init(int type);
extern void pci_pcbios_init(void);
-extern int pci_olpc_init(void);
extern void __init dmi_check_pciprobe(void);
extern void __init dmi_check_skip_isa_align(void);
/* some common used subsys_initcalls */
extern int __init pci_acpi_init(void);
-extern int __init pcibios_irq_init(void);
-extern int __init pci_visws_init(void);
-extern int __init pci_numaq_init(void);
+extern void __init pcibios_irq_init(void);
extern int __init pcibios_init(void);
+extern int pci_legacy_init(void);
+extern void pcibios_fixup_irqs(void);
/* pci-mmconfig.c */
@@ -183,3 +181,17 @@ static inline void mmio_config_writel(void __iomem *pos, u32 val)
{
asm volatile("movl %%eax,(%1)" : : "a" (val), "r" (pos) : "memory");
}
+
+#ifdef CONFIG_PCI
+# ifdef CONFIG_ACPI
+# define x86_default_pci_init pci_acpi_init
+# else
+# define x86_default_pci_init pci_legacy_init
+# endif
+# define x86_default_pci_init_irq pcibios_irq_init
+# define x86_default_pci_fixup_irqs pcibios_fixup_irqs
+#else
+# define x86_default_pci_init NULL
+# define x86_default_pci_init_irq NULL
+# define x86_default_pci_fixup_irqs NULL
+#endif
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index 18e496c98ff..86b1506f417 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -37,10 +37,8 @@ void setup_bios_corruption_check(void);
#ifdef CONFIG_X86_VISWS
extern void visws_early_detect(void);
-extern int is_visws_box(void);
#else
static inline void visws_early_detect(void) { }
-static inline int is_visws_box(void) { return 0; }
#endif
extern unsigned long saved_video_mode;
diff --git a/arch/x86/include/asm/visws/cobalt.h b/arch/x86/include/asm/visws/cobalt.h
index 166adf61e77..2edb37637ea 100644
--- a/arch/x86/include/asm/visws/cobalt.h
+++ b/arch/x86/include/asm/visws/cobalt.h
@@ -122,4 +122,6 @@ extern char visws_board_type;
extern char visws_board_rev;
+extern int pci_visws_init(void);
+
#endif /* _ASM_X86_VISWS_COBALT_H */
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index 60cc3526908..519b54327d7 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -99,6 +99,20 @@ struct x86_init_iommu {
};
/**
+ * struct x86_init_pci - platform specific pci init functions
+ * @arch_init: platform specific pci arch init call
+ * @init: platform specific pci subsystem init
+ * @init_irq: platform specific pci irq init
+ * @fixup_irqs: platform specific pci irq fixup
+ */
+struct x86_init_pci {
+ int (*arch_init)(void);
+ int (*init)(void);
+ void (*init_irq)(void);
+ void (*fixup_irqs)(void);
+};
+
+/**
* struct x86_init_ops - functions for platform specific setup
*
*/
@@ -110,6 +124,7 @@ struct x86_init_ops {
struct x86_init_paging paging;
struct x86_init_timers timers;
struct x86_init_iommu iommu;
+ struct x86_init_pci pci;
};
/**
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index d87f09bc5a5..4c58352209e 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -87,6 +87,7 @@ obj-$(CONFIG_VM86) += vm86_32.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_HPET_TIMER) += hpet.o
+obj-$(CONFIG_APB_TIMER) += apb_timer.o
obj-$(CONFIG_K8_NB) += k8.o
obj-$(CONFIG_DEBUG_RODATA_TEST) += test_rodata.o
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 738fcb60e70..a54d714545f 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -35,6 +35,7 @@
#include <linux/ioport.h>
#include <linux/pci.h>
+#include <asm/pci_x86.h>
#include <asm/pgtable.h>
#include <asm/io_apic.h>
#include <asm/apic.h>
@@ -1624,6 +1625,9 @@ int __init acpi_boot_init(void)
acpi_table_parse(ACPI_SIG_HPET, acpi_parse_hpet);
+ if (!acpi_noirq)
+ x86_init.pci.init = pci_acpi_init;
+
return 0;
}
diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c
new file mode 100644
index 00000000000..4b7099526d2
--- /dev/null
+++ b/arch/x86/kernel/apb_timer.c
@@ -0,0 +1,784 @@
+/*
+ * apb_timer.c: Driver for Langwell APB timers
+ *
+ * (C) Copyright 2009 Intel Corporation
+ * Author: Jacob Pan (jacob.jun.pan@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; version 2
+ * of the License.
+ *
+ * Note:
+ * Langwell is the south complex of Intel Moorestown MID platform. There are
+ * eight external timers in total that can be used by the operating system.
+ * The timer information, such as frequency and addresses, is provided to the
+ * OS via SFI tables.
+ * Timer interrupts are routed via FW/HW emulated IOAPIC independently via
+ * individual redirection table entries (RTE).
+ * Unlike HPET, there is no master counter, therefore one of the timers are
+ * used as clocksource. The overall allocation looks like:
+ * - timer 0 - NR_CPUs for per cpu timer
+ * - one timer for clocksource
+ * - one timer for watchdog driver.
+ * It is also worth notice that APB timer does not support true one-shot mode,
+ * free-running mode will be used here to emulate one-shot mode.
+ * APB timer can also be used as broadcast timer along with per cpu local APIC
+ * timer, but by default APB timer has higher rating than local APIC timers.
+ */
+
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/sysdev.h>
+#include <linux/pm.h>
+#include <linux/pci.h>
+#include <linux/sfi.h>
+#include <linux/interrupt.h>
+#include <linux/cpu.h>
+#include <linux/irq.h>
+
+#include <asm/fixmap.h>
+#include <asm/apb_timer.h>
+
+#define APBT_MASK CLOCKSOURCE_MASK(32)
+#define APBT_SHIFT 22
+#define APBT_CLOCKEVENT_RATING 150
+#define APBT_CLOCKSOURCE_RATING 250
+#define APBT_MIN_DELTA_USEC 200
+
+#define EVT_TO_APBT_DEV(evt) container_of(evt, struct apbt_dev, evt)
+#define APBT_CLOCKEVENT0_NUM (0)
+#define APBT_CLOCKEVENT1_NUM (1)
+#define APBT_CLOCKSOURCE_NUM (2)
+
+static unsigned long apbt_address;
+static int apb_timer_block_enabled;
+static void __iomem *apbt_virt_address;
+static int phy_cs_timer_id;
+
+/*
+ * Common DW APB timer info
+ */
+static uint64_t apbt_freq;
+
+static void apbt_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt);
+static int apbt_next_event(unsigned long delta,
+ struct clock_event_device *evt);
+static cycle_t apbt_read_clocksource(struct clocksource *cs);
+static void apbt_restart_clocksource(struct clocksource *cs);
+
+struct apbt_dev {
+ struct clock_event_device evt;
+ unsigned int num;
+ int cpu;
+ unsigned int irq;
+ unsigned int tick;
+ unsigned int count;
+ unsigned int flags;
+ char name[10];
+};
+
+int disable_apbt_percpu __cpuinitdata;
+
+static DEFINE_PER_CPU(struct apbt_dev, cpu_apbt_dev);
+
+#ifdef CONFIG_SMP
+static unsigned int apbt_num_timers_used;
+static struct apbt_dev *apbt_devs;
+#endif
+
+static inline unsigned long apbt_readl_reg(unsigned long a)
+{
+ return readl(apbt_virt_address + a);
+}
+
+static inline void apbt_writel_reg(unsigned long d, unsigned long a)
+{
+ writel(d, apbt_virt_address + a);
+}
+
+static inline unsigned long apbt_readl(int n, unsigned long a)
+{
+ return readl(apbt_virt_address + a + n * APBTMRS_REG_SIZE);
+}
+
+static inline void apbt_writel(int n, unsigned long d, unsigned long a)
+{
+ writel(d, apbt_virt_address + a + n * APBTMRS_REG_SIZE);
+}
+
+static inline void apbt_set_mapping(void)
+{
+ struct sfi_timer_table_entry *mtmr;
+
+ if (apbt_virt_address) {
+ pr_debug("APBT base already mapped\n");
+ return;
+ }
+ mtmr = sfi_get_mtmr(APBT_CLOCKEVENT0_NUM);
+ if (mtmr == NULL) {
+ printk(KERN_ERR "Failed to get MTMR %d from SFI\n",
+ APBT_CLOCKEVENT0_NUM);
+ return;
+ }
+ apbt_address = (unsigned long)mtmr->phys_addr;
+ if (!apbt_address) {
+ printk(KERN_WARNING "No timer base from SFI, use default\n");
+ apbt_address = APBT_DEFAULT_BASE;
+ }
+ apbt_virt_address = ioremap_nocache(apbt_address, APBT_MMAP_SIZE);
+ if (apbt_virt_address) {
+ pr_debug("Mapped APBT physical addr %p at virtual addr %p\n",\
+ (void *)apbt_address, (void *)apbt_virt_address);
+ } else {
+ pr_debug("Failed mapping APBT phy address at %p\n",\
+ (void *)apbt_address);
+ goto panic_noapbt;
+ }
+ apbt_freq = mtmr->freq_hz / USEC_PER_SEC;
+ sfi_free_mtmr(mtmr);
+
+ /* Now figure out the physical timer id for clocksource device */
+ mtmr = sfi_get_mtmr(APBT_CLOCKSOURCE_NUM);
+ if (mtmr == NULL)
+ goto panic_noapbt;
+
+ /* Now figure out the physical timer id */
+ phy_cs_timer_id = (unsigned int)(mtmr->phys_addr & 0xff)
+ / APBTMRS_REG_SIZE;
+ pr_debug("Use timer %d for clocksource\n", phy_cs_timer_id);
+ return;
+
+panic_noapbt:
+ panic("Failed to setup APB system timer\n");
+
+}
+
+static inline void apbt_clear_mapping(void)
+{
+ iounmap(apbt_virt_address);
+ apbt_virt_address = NULL;
+}
+
+/*
+ * APBT timer interrupt enable / disable
+ */
+static inline int is_apbt_capable(void)
+{
+ return apbt_virt_address ? 1 : 0;
+}
+
+static struct clocksource clocksource_apbt = {
+ .name = "apbt",
+ .rating = APBT_CLOCKSOURCE_RATING,
+ .read = apbt_read_clocksource,
+ .mask = APBT_MASK,
+ .shift = APBT_SHIFT,
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .resume = apbt_restart_clocksource,
+};
+
+/* boot APB clock event device */
+static struct clock_event_device apbt_clockevent = {
+ .name = "apbt0",
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .set_mode = apbt_set_mode,
+ .set_next_event = apbt_next_event,
+ .shift = APBT_SHIFT,
+ .irq = 0,
+ .rating = APBT_CLOCKEVENT_RATING,
+};
+
+/*
+ * if user does not want to use per CPU apb timer, just give it a lower rating
+ * than local apic timer and skip the late per cpu timer init.
+ */
+static inline int __init setup_x86_mrst_timer(char *arg)
+{
+ if (!arg)
+ return -EINVAL;
+
+ if (strcmp("apbt_only", arg) == 0)
+ disable_apbt_percpu = 0;
+ else if (strcmp("lapic_and_apbt", arg) == 0)
+ disable_apbt_percpu = 1;
+ else {
+ pr_warning("X86 MRST timer option %s not recognised"
+ " use x86_mrst_timer=apbt_only or lapic_and_apbt\n",
+ arg);
+ return -EINVAL;
+ }
+ return 0;
+}
+__setup("x86_mrst_timer=", setup_x86_mrst_timer);
+
+/*
+ * start count down from 0xffff_ffff. this is done by toggling the enable bit
+ * then load initial load count to ~0.
+ */
+static void apbt_start_counter(int n)
+{
+ unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
+
+ ctrl &= ~APBTMR_CONTROL_ENABLE;
+ apbt_writel(n, ctrl, APBTMR_N_CONTROL);
+ apbt_writel(n, ~0, APBTMR_N_LOAD_COUNT);
+ /* enable, mask interrupt */
+ ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
+ ctrl |= (APBTMR_CONTROL_ENABLE | APBTMR_CONTROL_INT);
+ apbt_writel(n, ctrl, APBTMR_N_CONTROL);
+ /* read it once to get cached counter value initialized */
+ apbt_read_clocksource(&clocksource_apbt);
+}
+
+static irqreturn_t apbt_interrupt_handler(int irq, void *data)
+{
+ struct apbt_dev *dev = (struct apbt_dev *)data;
+ struct clock_event_device *aevt = &dev->evt;
+
+ if (!aevt->event_handler) {
+ printk(KERN_INFO "Spurious APBT timer interrupt on %d\n",
+ dev->num);
+ return IRQ_NONE;
+ }
+ aevt->event_handler(aevt);
+ return IRQ_HANDLED;
+}
+
+static void apbt_restart_clocksource(struct clocksource *cs)
+{
+ apbt_start_counter(phy_cs_timer_id);
+}
+
+/* Setup IRQ routing via IOAPIC */
+#ifdef CONFIG_SMP
+static void apbt_setup_irq(struct apbt_dev *adev)
+{
+ struct irq_chip *chip;
+ struct irq_desc *desc;
+
+ /* timer0 irq has been setup early */
+ if (adev->irq == 0)
+ return;
+ desc = irq_to_desc(adev->irq);
+ chip = get_irq_chip(adev->irq);
+ disable_irq(adev->irq);
+ desc->status |= IRQ_MOVE_PCNTXT;
+ irq_set_affinity(adev->irq, cpumask_of(adev->cpu));
+ /* APB timer irqs are set up as mp_irqs, timer is edge triggerred */
+ set_irq_chip_and_handler_name(adev->irq, chip, handle_edge_irq, "edge");
+ enable_irq(adev->irq);
+ if (system_state == SYSTEM_BOOTING)
+ if (request_irq(adev->irq, apbt_interrupt_handler,
+ IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING,
+ adev->name, adev)) {
+ printk(KERN_ERR "Failed request IRQ for APBT%d\n",
+ adev->num);
+ }
+}
+#endif
+
+static void apbt_enable_int(int n)
+{
+ unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
+ /* clear pending intr */
+ apbt_readl(n, APBTMR_N_EOI);
+ ctrl &= ~APBTMR_CONTROL_INT;
+ apbt_writel(n, ctrl, APBTMR_N_CONTROL);
+}
+
+static void apbt_disable_int(int n)
+{
+ unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
+
+ ctrl |= APBTMR_CONTROL_INT;
+ apbt_writel(n, ctrl, APBTMR_N_CONTROL);
+}
+
+
+static int __init apbt_clockevent_register(void)
+{
+ struct sfi_timer_table_entry *mtmr;
+ struct apbt_dev *adev = &__get_cpu_var(cpu_apbt_dev);
+
+ mtmr = sfi_get_mtmr(APBT_CLOCKEVENT0_NUM);
+ if (mtmr == NULL) {
+ printk(KERN_ERR "Failed to get MTMR %d from SFI\n",
+ APBT_CLOCKEVENT0_NUM);
+ return -ENODEV;
+ }
+
+ /*
+ * We need to calculate the scaled math multiplication factor for
+ * nanosecond to apbt tick conversion.
+ * mult = (nsec/cycle)*2^APBT_SHIFT
+ */
+ apbt_clockevent.mult = div_sc((unsigned long) mtmr->freq_hz
+ , NSEC_PER_SEC, APBT_SHIFT);
+
+ /* Calculate the min / max delta */
+ apbt_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
+ &apbt_clockevent);
+ apbt_clockevent.min_delta_ns = clockevent_delta2ns(
+ APBT_MIN_DELTA_USEC*apbt_freq,
+ &apbt_clockevent);
+ /*
+ * Start apbt with the boot cpu mask and make it
+ * global if not used for per cpu timer.
+ */
+ apbt_clockevent.cpumask = cpumask_of(smp_processor_id());
+ adev->num = smp_processor_id();
+ memcpy(&adev->evt, &apbt_clockevent, sizeof(struct clock_event_device));
+
+ if (disable_apbt_percpu) {
+ apbt_clockevent.rating = APBT_CLOCKEVENT_RATING - 100;
+ global_clock_event = &adev->evt;
+ printk(KERN_DEBUG "%s clockevent registered as global\n",
+ global_clock_event->name);
+ }
+
+ if (request_irq(apbt_clockevent.irq, apbt_interrupt_handler,
+ IRQF_TIMER | IRQF_DISABLED | IRQF_NOBALANCING,
+ apbt_clockevent.name, adev)) {
+ printk(KERN_ERR "Failed request IRQ for APBT%d\n",
+ apbt_clockevent.irq);
+ }
+
+ clockevents_register_device(&adev->evt);
+ /* Start APBT 0 interrupts */
+ apbt_enable_int(APBT_CLOCKEVENT0_NUM);
+
+ sfi_free_mtmr(mtmr);
+ return 0;
+}
+
+#ifdef CONFIG_SMP
+/* Should be called with per cpu */
+void apbt_setup_secondary_clock(void)
+{
+ struct apbt_dev *adev;
+ struct clock_event_device *aevt;
+ int cpu;
+
+ /* Don't register boot CPU clockevent */
+ cpu = smp_processor_id();
+ if (cpu == boot_cpu_id)
+ return;
+ /*
+ * We need to calculate the scaled math multiplication factor for
+ * nanosecond to apbt tick conversion.
+ * mult = (nsec/cycle)*2^APBT_SHIFT
+ */
+ printk(KERN_INFO "Init per CPU clockevent %d\n", cpu);
+ adev = &per_cpu(cpu_apbt_dev, cpu);
+ aevt = &adev->evt;
+
+ memcpy(aevt, &apbt_clockevent, sizeof(*aevt));
+ aevt->cpumask = cpumask_of(cpu);
+ aevt->name = adev->name;
+ aevt->mode = CLOCK_EVT_MODE_UNUSED;
+
+ printk(KERN_INFO "Registering CPU %d clockevent device %s, mask %08x\n",
+ cpu, aevt->name, *(u32 *)aevt->cpumask);
+
+ apbt_setup_irq(adev);
+
+ clockevents_register_device(aevt);
+
+ apbt_enable_int(cpu);
+
+ return;
+}
+
+/*
+ * this notify handler process CPU hotplug events. in case of S0i3, nonboot
+ * cpus are disabled/enabled frequently, for performance reasons, we keep the
+ * per cpu timer irq registered so that we do need to do free_irq/request_irq.
+ *
+ * TODO: it might be more reliable to directly disable percpu clockevent device
+ * without the notifier chain. currently, cpu 0 may get interrupts from other
+ * cpu timers during the offline process due to the ordering of notification.
+ * the extra interrupt is harmless.
+ */
+static int apbt_cpuhp_notify(struct notifier_block *n,
+ unsigned long action, void *hcpu)
+{
+ unsigned long cpu = (unsigned long)hcpu;
+ struct apbt_dev *adev = &per_cpu(cpu_apbt_dev, cpu);
+
+ switch (action & 0xf) {
+ case CPU_DEAD:
+ apbt_disable_int(cpu);
+ if (system_state == SYSTEM_RUNNING)
+ pr_debug("skipping APBT CPU %lu offline\n", cpu);
+ else if (adev) {
+ pr_debug("APBT clockevent for cpu %lu offline\n", cpu);
+ free_irq(adev->irq, adev);
+ }
+ break;
+ default:
+ pr_debug(KERN_INFO "APBT notified %lu, no action\n", action);
+ }
+ return NOTIFY_OK;
+}
+
+static __init int apbt_late_init(void)
+{
+ if (disable_apbt_percpu)
+ return 0;
+ /* This notifier should be called after workqueue is ready */
+ hotcpu_notifier(apbt_cpuhp_notify, -20);
+ return 0;
+}
+fs_initcall(apbt_late_init);
+#else
+
+void apbt_setup_secondary_clock(void) {}
+
+#endif /* CONFIG_SMP */
+
+static void apbt_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ unsigned long ctrl;
+ uint64_t delta;
+ int timer_num;
+ struct apbt_dev *adev = EVT_TO_APBT_DEV(evt);
+
+ timer_num = adev->num;
+ pr_debug("%s CPU %d timer %d mode=%d\n",
+ __func__, first_cpu(*evt->cpumask), timer_num, mode);
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ delta = ((uint64_t)(NSEC_PER_SEC/HZ)) * apbt_clockevent.mult;
+ delta >>= apbt_clockevent.shift;
+ ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
+ ctrl |= APBTMR_CONTROL_MODE_PERIODIC;
+ apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+ /*
+ * DW APB p. 46, have to disable timer before load counter,
+ * may cause sync problem.
+ */
+ ctrl &= ~APBTMR_CONTROL_ENABLE;
+ apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+ udelay(1);
+ pr_debug("Setting clock period %d for HZ %d\n", (int)delta, HZ);
+ apbt_writel(timer_num, delta, APBTMR_N_LOAD_COUNT);
+ ctrl |= APBTMR_CONTROL_ENABLE;
+ apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+ break;
+ /* APB timer does not have one-shot mode, use free running mode */
+ case CLOCK_EVT_MODE_ONESHOT:
+ ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
+ /*
+ * set free running mode, this mode will let timer reload max
+ * timeout which will give time (3min on 25MHz clock) to rearm
+ * the next event, therefore emulate the one-shot mode.
+ */
+ ctrl &= ~APBTMR_CONTROL_ENABLE;
+ ctrl &= ~APBTMR_CONTROL_MODE_PERIODIC;
+
+ apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+ /* write again to set free running mode */
+ apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+
+ /*
+ * DW APB p. 46, load counter with all 1s before starting free
+ * running mode.
+ */
+ apbt_writel(timer_num, ~0, APBTMR_N_LOAD_COUNT);
+ ctrl &= ~APBTMR_CONTROL_INT;
+ ctrl |= APBTMR_CONTROL_ENABLE;
+ apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+ break;
+
+ case CLOCK_EVT_MODE_UNUSED:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ apbt_disable_int(timer_num);
+ ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
+ ctrl &= ~APBTMR_CONTROL_ENABLE;
+ apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+ break;
+
+ case CLOCK_EVT_MODE_RESUME:
+ apbt_enable_int(timer_num);
+ break;
+ }
+}
+
+static int apbt_next_event(unsigned long delta,
+ struct clock_event_device *evt)
+{
+ unsigned long ctrl;
+ int timer_num;
+
+ struct apbt_dev *adev = EVT_TO_APBT_DEV(evt);
+
+ timer_num = adev->num;
+ /* Disable timer */
+ ctrl = apbt_readl(timer_num, APBTMR_N_CONTROL);
+ ctrl &= ~APBTMR_CONTROL_ENABLE;
+ apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+ /* write new count */
+ apbt_writel(timer_num, delta, APBTMR_N_LOAD_COUNT);
+ ctrl |= APBTMR_CONTROL_ENABLE;
+ apbt_writel(timer_num, ctrl, APBTMR_N_CONTROL);
+ return 0;
+}
+
+/*
+ * APB timer clock is not in sync with pclk on Langwell, which translates to
+ * unreliable read value caused by sampling error. the error does not add up
+ * overtime and only happens when sampling a 0 as a 1 by mistake. so the time
+ * would go backwards. the following code is trying to prevent time traveling
+ * backwards. little bit paranoid.
+ */
+static cycle_t apbt_read_clocksource(struct clocksource *cs)
+{
+ unsigned long t0, t1, t2;
+ static unsigned long last_read;
+
+bad_count:
+ t1 = apbt_readl(phy_cs_timer_id,
+ APBTMR_N_CURRENT_VALUE);
+ t2 = apbt_readl(phy_cs_timer_id,
+ APBTMR_N_CURRENT_VALUE);
+ if (unlikely(t1 < t2)) {
+ pr_debug("APBT: read current count error %lx:%lx:%lx\n",
+ t1, t2, t2 - t1);
+ goto bad_count;
+ }
+ /*
+ * check against cached last read, makes sure time does not go back.
+ * it could be a normal rollover but we will do tripple check anyway
+ */
+ if (unlikely(t2 > last_read)) {
+ /* check if we have a normal rollover */
+ unsigned long raw_intr_status =
+ apbt_readl_reg(APBTMRS_RAW_INT_STATUS);
+ /*
+ * cs timer interrupt is masked but raw intr bit is set if
+ * rollover occurs. then we read EOI reg to clear it.
+ */
+ if (raw_intr_status & (1 << phy_cs_timer_id)) {
+ apbt_readl(phy_cs_timer_id, APBTMR_N_EOI);
+ goto out;
+ }
+ pr_debug("APB CS going back %lx:%lx:%lx ",
+ t2, last_read, t2 - last_read);
+bad_count_x3:
+ pr_debug(KERN_INFO "tripple check enforced\n");
+ t0 = apbt_readl(phy_cs_timer_id,
+ APBTMR_N_CURRENT_VALUE);
+ udelay(1);
+ t1 = apbt_readl(phy_cs_timer_id,
+ APBTMR_N_CURRENT_VALUE);
+ udelay(1);
+ t2 = apbt_readl(phy_cs_timer_id,
+ APBTMR_N_CURRENT_VALUE);
+ if ((t2 > t1) || (t1 > t0)) {
+ printk(KERN_ERR "Error: APB CS tripple check failed\n");
+ goto bad_count_x3;
+ }
+ }
+out:
+ last_read = t2;
+ return (cycle_t)~t2;
+}
+
+static int apbt_clocksource_register(void)
+{
+ u64 start, now;
+ cycle_t t1;
+
+ /* Start the counter, use timer 2 as source, timer 0/1 for event */
+ apbt_start_counter(phy_cs_timer_id);
+
+ /* Verify whether apbt counter works */
+ t1 = apbt_read_clocksource(&clocksource_apbt);
+ rdtscll(start);
+
+ /*
+ * We don't know the TSC frequency yet, but waiting for
+ * 200000 TSC cycles is safe:
+ * 4 GHz == 50us
+ * 1 GHz == 200us
+ */
+ do {
+ rep_nop();
+ rdtscll(now);
+ } while ((now - start) < 200000UL);
+
+ /* APBT is the only always on clocksource, it has to work! */
+ if (t1 == apbt_read_clocksource(&clocksource_apbt))
+ panic("APBT counter not counting. APBT disabled\n");
+
+ /*
+ * initialize and register APBT clocksource
+ * convert that to ns/clock cycle
+ * mult = (ns/c) * 2^APBT_SHIFT
+ */
+ clocksource_apbt.mult = div_sc(MSEC_PER_SEC,
+ (unsigned long) apbt_freq, APBT_SHIFT);
+ clocksource_register(&clocksource_apbt);
+
+ return 0;
+}
+
+/*
+ * Early setup the APBT timer, only use timer 0 for booting then switch to
+ * per CPU timer if possible.
+ * returns 1 if per cpu apbt is setup
+ * returns 0 if no per cpu apbt is chosen
+ * panic if set up failed, this is the only platform timer on Moorestown.
+ */
+void __init apbt_time_init(void)
+{
+#ifdef CONFIG_SMP
+ int i;
+ struct sfi_timer_table_entry *p_mtmr;
+ unsigned int percpu_timer;
+ struct apbt_dev *adev;
+#endif
+
+ if (apb_timer_block_enabled)
+ return;
+ apbt_set_mapping();
+ if (apbt_virt_address) {
+ pr_debug("Found APBT version 0x%lx\n",\
+ apbt_readl_reg(APBTMRS_COMP_VERSION));
+ } else
+ goto out_noapbt;
+ /*
+ * Read the frequency and check for a sane value, for ESL model
+ * we extend the possible clock range to allow time scaling.
+ */
+
+ if (apbt_freq < APBT_MIN_FREQ || apbt_freq > APBT_MAX_FREQ) {
+ pr_debug("APBT has invalid freq 0x%llx\n", apbt_freq);
+ goto out_noapbt;
+ }
+ if (apbt_clocksource_register()) {
+ pr_debug("APBT has failed to register clocksource\n");
+ goto out_noapbt;
+ }
+ if (!apbt_clockevent_register())
+ apb_timer_block_enabled = 1;
+ else {
+ pr_debug("APBT has failed to register clockevent\n");
+ goto out_noapbt;
+ }
+#ifdef CONFIG_SMP
+ /* kernel cmdline disable apb timer, so we will use lapic timers */
+ if (disable_apbt_percpu) {
+ printk(KERN_INFO "apbt: disabled per cpu timer\n");
+ return;
+ }
+ pr_debug("%s: %d CPUs online\n", __func__, num_online_cpus());
+ if (num_possible_cpus() <= sfi_mtimer_num) {
+ percpu_timer = 1;
+ apbt_num_timers_used = num_possible_cpus();
+ } else {
+ percpu_timer = 0;
+ apbt_num_timers_used = 1;
+ adev = &per_cpu(cpu_apbt_dev, 0);
+ adev->flags &= ~APBT_DEV_USED;
+ }
+ pr_debug("%s: %d APB timers used\n", __func__, apbt_num_timers_used);
+
+ /* here we set up per CPU timer data structure */
+ apbt_devs = kzalloc(sizeof(struct apbt_dev) * apbt_num_timers_used,
+ GFP_KERNEL);
+ if (!apbt_devs) {
+ printk(KERN_ERR "Failed to allocate APB timer devices\n");
+ return;
+ }
+ for (i = 0; i < apbt_num_timers_used; i++) {
+ adev = &per_cpu(cpu_apbt_dev, i);
+ adev->num = i;
+ adev->cpu = i;
+ p_mtmr = sfi_get_mtmr(i);
+ if (p_mtmr) {
+ adev->tick = p_mtmr->freq_hz;
+ adev->irq = p_mtmr->irq;
+ } else
+ printk(KERN_ERR "Failed to get timer for cpu %d\n", i);
+ adev->count = 0;
+ sprintf(adev->name, "apbt%d", i);
+ }
+#endif
+
+ return;
+
+out_noapbt:
+ apbt_clear_mapping();
+ apb_timer_block_enabled = 0;
+ panic("failed to enable APB timer\n");
+}
+
+static inline void apbt_disable(int n)
+{
+ if (is_apbt_capable()) {
+ unsigned long ctrl = apbt_readl(n, APBTMR_N_CONTROL);
+ ctrl &= ~APBTMR_CONTROL_ENABLE;
+ apbt_writel(n, ctrl, APBTMR_N_CONTROL);
+ }
+}
+
+/* called before apb_timer_enable, use early map */
+unsigned long apbt_quick_calibrate()
+{
+ int i, scale;
+ u64 old, new;
+ cycle_t t1, t2;
+ unsigned long khz = 0;
+ u32 loop, shift;
+
+ apbt_set_mapping();
+ apbt_start_counter(phy_cs_timer_id);
+
+ /* check if the timer can count down, otherwise return */
+ old = apbt_read_clocksource(&clocksource_apbt);
+ i = 10000;
+ while (--i) {
+ if (old != apbt_read_clocksource(&clocksource_apbt))
+ break;
+ }
+ if (!i)
+ goto failed;
+
+ /* count 16 ms */
+ loop = (apbt_freq * 1000) << 4;
+
+ /* restart the timer to ensure it won't get to 0 in the calibration */
+ apbt_start_counter(phy_cs_timer_id);
+
+ old = apbt_read_clocksource(&clocksource_apbt);
+ old += loop;
+
+ t1 = __native_read_tsc();
+
+ do {
+ new = apbt_read_clocksource(&clocksource_apbt);
+ } while (new < old);
+
+ t2 = __native_read_tsc();
+
+ shift = 5;
+ if (unlikely(loop >> shift == 0)) {
+ printk(KERN_INFO
+ "APBT TSC calibration failed, not enough resolution\n");
+ return 0;
+ }
+ scale = (int)div_u64((t2 - t1), loop >> shift);
+ khz = (scale * apbt_freq * 1000) >> shift;
+ printk(KERN_INFO "TSC freq calculated by APB timer is %lu khz\n", khz);
+ return khz;
+failed:
+ return 0;
+}
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 6e29b2a77aa..00187f1fcfb 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1390,7 +1390,7 @@ void __init enable_IR_x2apic(void)
}
local_irq_save(flags);
- mask_8259A();
+ legacy_pic->mask_all();
mask_IO_APIC_setup(ioapic_entries);
if (dmar_table_init_ret)
@@ -1422,7 +1422,7 @@ void __init enable_IR_x2apic(void)
nox2apic:
if (!ret) /* IR enabling failed */
restore_IO_APIC_setup(ioapic_entries);
- unmask_8259A();
+ legacy_pic->restore_mask();
local_irq_restore(flags);
out:
@@ -2018,7 +2018,7 @@ static int lapic_resume(struct sys_device *dev)
}
mask_IO_APIC_setup(ioapic_entries);
- mask_8259A();
+ legacy_pic->mask_all();
}
if (x2apic_mode)
@@ -2062,7 +2062,7 @@ static int lapic_resume(struct sys_device *dev)
if (intr_remapping_enabled) {
reenable_intr_remapping(x2apic_mode);
- unmask_8259A();
+ legacy_pic->restore_mask();
restore_IO_APIC_setup(ioapic_entries);
free_ioapic_entries(ioapic_entries);
}
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 14862f11cc4..e4e0ddcb154 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -143,12 +143,6 @@ static struct irq_cfg irq_cfgx[NR_IRQS_LEGACY];
static struct irq_cfg irq_cfgx[NR_IRQS];
#endif
-void __init io_apic_disable_legacy(void)
-{
- nr_legacy_irqs = 0;
- nr_irqs_gsi = 0;
-}
-
int __init arch_early_irq_init(void)
{
struct irq_cfg *cfg;
@@ -157,6 +151,11 @@ int __init arch_early_irq_init(void)
int node;
int i;
+ if (!legacy_pic->nr_legacy_irqs) {
+ nr_irqs_gsi = 0;
+ io_apic_irqs = ~0UL;
+ }
+
cfg = irq_cfgx;
count = ARRAY_SIZE(irq_cfgx);
node= cpu_to_node(boot_cpu_id);
@@ -170,7 +169,7 @@ int __init arch_early_irq_init(void)
* For legacy IRQ's, start with assigning irq0 to irq15 to
* IRQ0_VECTOR to IRQ15_VECTOR on cpu 0.
*/
- if (i < nr_legacy_irqs) {
+ if (i < legacy_pic->nr_legacy_irqs) {
cfg[i].vector = IRQ0_VECTOR + i;
cpumask_set_cpu(0, cfg[i].domain);
}
@@ -852,7 +851,7 @@ static int __init find_isa_irq_apic(int irq, int type)
*/
static int EISA_ELCR(unsigned int irq)
{
- if (irq < nr_legacy_irqs) {
+ if (irq < legacy_pic->nr_legacy_irqs) {
unsigned int port = 0x4d0 + (irq >> 3);
return (inb(port) >> (irq & 7)) & 1;
}
@@ -1439,7 +1438,7 @@ static void setup_IO_APIC_irq(int apic_id, int pin, unsigned int irq, struct irq
* controllers like 8259. Now that IO-APIC can handle this irq, update
* the cfg->domain.
*/
- if (irq < nr_legacy_irqs && cpumask_test_cpu(0, cfg->domain))
+ if (irq < legacy_pic->nr_legacy_irqs && cpumask_test_cpu(0, cfg->domain))
apic->vector_allocation_domain(0, cfg->domain);
if (assign_irq_vector(irq, cfg, apic->target_cpus()))
@@ -1463,8 +1462,8 @@ static void setup_IO_APIC_irq(int apic_id, int pin, unsigned int irq, struct irq
}
ioapic_register_intr(irq, desc, trigger);
- if (irq < nr_legacy_irqs)
- disable_8259A_irq(irq);
+ if (irq < legacy_pic->nr_legacy_irqs)
+ legacy_pic->chip->mask(irq);
ioapic_write_entry(apic_id, pin, entry);
}
@@ -1873,7 +1872,7 @@ __apicdebuginit(void) print_PIC(void)
unsigned int v;
unsigned long flags;
- if (!nr_legacy_irqs)
+ if (!legacy_pic->nr_legacy_irqs)
return;
printk(KERN_DEBUG "\nprinting PIC contents\n");
@@ -1957,7 +1956,7 @@ void __init enable_IO_APIC(void)
nr_ioapic_registers[apic] = reg_01.bits.entries+1;
}
- if (!nr_legacy_irqs)
+ if (!legacy_pic->nr_legacy_irqs)
return;
for(apic = 0; apic < nr_ioapics; apic++) {
@@ -2014,7 +2013,7 @@ void disable_IO_APIC(void)
*/
clear_IO_APIC();
- if (!nr_legacy_irqs)
+ if (!legacy_pic->nr_legacy_irqs)
return;
/*
@@ -2247,9 +2246,9 @@ static unsigned int startup_ioapic_irq(unsigned int irq)
struct irq_cfg *cfg;
raw_spin_lock_irqsave(&ioapic_lock, flags);
- if (irq < nr_legacy_irqs) {
- disable_8259A_irq(irq);
- if (i8259A_irq_pending(irq))
+ if (irq < legacy_pic->nr_legacy_irqs) {
+ legacy_pic->chip->mask(irq);
+ if (legacy_pic->irq_pending(irq))
was_pending = 1;
}
cfg = irq_cfg(irq);
@@ -2782,8 +2781,8 @@ static inline void init_IO_APIC_traps(void)
* so default to an old-fashioned 8259
* interrupt if we can..
*/
- if (irq < nr_legacy_irqs)
- make_8259A_irq(irq);
+ if (irq < legacy_pic->nr_legacy_irqs)
+ legacy_pic->make_irq(irq);
else
/* Strange. Oh, well.. */
desc->chip = &no_irq_chip;
@@ -2940,7 +2939,7 @@ static inline void __init check_timer(void)
/*
* get/set the timer IRQ vector:
*/
- disable_8259A_irq(0);
+ legacy_pic->chip->mask(0);
assign_irq_vector(0, cfg, apic->target_cpus());
/*
@@ -2953,7 +2952,7 @@ static inline void __init check_timer(void)
* automatically.
*/
apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT);
- init_8259A(1);
+ legacy_pic->init(1);
#ifdef CONFIG_X86_32
{
unsigned int ver;
@@ -3012,7 +3011,7 @@ static inline void __init check_timer(void)
if (timer_irq_works()) {
if (nmi_watchdog == NMI_IO_APIC) {
setup_nmi();
- enable_8259A_irq(0);
+ legacy_pic->chip->unmask(0);
}
if (disable_timer_pin_1 > 0)
clear_IO_APIC_pin(0, pin1);
@@ -3035,14 +3034,14 @@ static inline void __init check_timer(void)
*/
replace_pin_at_irq_node(cfg, node, apic1, pin1, apic2, pin2);
setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
- enable_8259A_irq(0);
+ legacy_pic->chip->unmask(0);
if (timer_irq_works()) {
apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
timer_through_8259 = 1;
if (nmi_watchdog == NMI_IO_APIC) {
- disable_8259A_irq(0);
+ legacy_pic->chip->mask(0);
setup_nmi();
- enable_8259A_irq(0);
+ legacy_pic->chip->unmask(0);
}
goto out;
}
@@ -3050,7 +3049,7 @@ static inline void __init check_timer(void)
* Cleanup, just in case ...
*/
local_irq_disable();
- disable_8259A_irq(0);
+ legacy_pic->chip->mask(0);
clear_IO_APIC_pin(apic2, pin2);
apic_printk(APIC_QUIET, KERN_INFO "....... failed.\n");
}
@@ -3069,22 +3068,22 @@ static inline void __init check_timer(void)
lapic_register_intr(0, desc);
apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector); /* Fixed mode */
- enable_8259A_irq(0);
+ legacy_pic->chip->unmask(0);
if (timer_irq_works()) {
apic_printk(APIC_QUIET, KERN_INFO "..... works.\n");
goto out;
}
local_irq_disable();
- disable_8259A_irq(0);
+ legacy_pic->chip->mask(0);
apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
apic_printk(APIC_QUIET, KERN_INFO "..... failed.\n");
apic_printk(APIC_QUIET, KERN_INFO
"...trying to set up timer as ExtINT IRQ...\n");
- init_8259A(0);
- make_8259A_irq(0);
+ legacy_pic->init(0);
+ legacy_pic->make_irq(0);
apic_write(APIC_LVT0, APIC_DM_EXTINT);
unlock_ExtINT_logic();
@@ -3126,7 +3125,7 @@ void __init setup_IO_APIC(void)
/*
* calling enable_IO_APIC() is moved to setup_local_APIC for BP
*/
- io_apic_irqs = nr_legacy_irqs ? ~PIC_IRQS : ~0UL;
+ io_apic_irqs = legacy_pic->nr_legacy_irqs ? ~PIC_IRQS : ~0UL;
apic_printk(APIC_VERBOSE, "ENABLING IO-APIC IRQs\n");
/*
@@ -3137,7 +3136,7 @@ void __init setup_IO_APIC(void)
sync_Arb_IDs();
setup_IO_APIC_irqs();
init_IO_APIC_traps();
- if (nr_legacy_irqs)
+ if (legacy_pic->nr_legacy_irqs)
check_timer();
}
@@ -3928,7 +3927,7 @@ static int __io_apic_set_pci_routing(struct device *dev, int irq,
/*
* IRQs < 16 are already in the irq_2_pin[] map
*/
- if (irq >= nr_legacy_irqs) {
+ if (irq >= legacy_pic->nr_legacy_irqs) {
cfg = desc->chip_data;
if (add_pin_to_irq_node_nopanic(cfg, node, ioapic, pin)) {
printk(KERN_INFO "can not add pin %d for irq %d\n",
@@ -4302,3 +4301,24 @@ void __init mp_register_ioapic(int id, u32 address, u32 gsi_base)
nr_ioapics++;
}
+
+/* Enable IOAPIC early just for system timer */
+void __init pre_init_apic_IRQ0(void)
+{
+ struct irq_cfg *cfg;
+ struct irq_desc *desc;
+
+ printk(KERN_INFO "Early APIC setup for system timer0\n");
+#ifndef CONFIG_SMP
+ phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid);
+#endif
+ desc = irq_to_desc_alloc_node(0, 0);
+
+ setup_local_APIC();
+
+ cfg = irq_cfg(0);
+ add_pin_to_irq_node(cfg, 0, 0, 0);
+ set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
+
+ setup_IO_APIC_irq(0, 0, 0, desc, 0, 0);
+}
diff --git a/arch/x86/kernel/apic/nmi.c b/arch/x86/kernel/apic/nmi.c
index bd7c96b5e8d..8aa65adbd25 100644
--- a/arch/x86/kernel/apic/nmi.c
+++ b/arch/x86/kernel/apic/nmi.c
@@ -177,7 +177,7 @@ int __init check_nmi_watchdog(void)
error:
if (nmi_watchdog == NMI_IO_APIC) {
if (!timer_through_8259)
- disable_8259A_irq(0);
+ legacy_pic->chip->mask(0);
on_each_cpu(__acpi_nmi_disable, NULL, 1);
}
diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c
index 47dd856708e..3e28401f161 100644
--- a/arch/x86/kernel/apic/numaq_32.c
+++ b/arch/x86/kernel/apic/numaq_32.c
@@ -277,6 +277,7 @@ static __init void early_check_numaq(void)
x86_init.mpparse.mpc_oem_pci_bus = mpc_oem_pci_bus;
x86_init.mpparse.mpc_oem_bus_info = mpc_oem_bus_info;
x86_init.timers.tsc_pre_init = numaq_tsc_init;
+ x86_init.pci.init = pci_numaq_init;
}
}
diff --git a/arch/x86/kernel/cpu/cpufreq/Kconfig b/arch/x86/kernel/cpu/cpufreq/Kconfig
index f138c6c389b..870e6cc6ad2 100644
--- a/arch/x86/kernel/cpu/cpufreq/Kconfig
+++ b/arch/x86/kernel/cpu/cpufreq/Kconfig
@@ -10,6 +10,20 @@ if CPU_FREQ
comment "CPUFreq processor drivers"
+config X86_PCC_CPUFREQ
+ tristate "Processor Clocking Control interface driver"
+ depends on ACPI && ACPI_PROCESSOR
+ help
+ This driver adds support for the PCC interface.
+
+ For details, take a look at:
+ <file:Documentation/cpu-freq/pcc-cpufreq.txt>.
+
+ To compile this driver as a module, choose M here: the
+ module will be called pcc-cpufreq.
+
+ If in doubt, say N.
+
config X86_ACPI_CPUFREQ
tristate "ACPI Processor P-States driver"
select CPU_FREQ_TABLE
diff --git a/arch/x86/kernel/cpu/cpufreq/Makefile b/arch/x86/kernel/cpu/cpufreq/Makefile
index 509296df294..1840c0a5170 100644
--- a/arch/x86/kernel/cpu/cpufreq/Makefile
+++ b/arch/x86/kernel/cpu/cpufreq/Makefile
@@ -4,6 +4,7 @@
obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o
obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o
+obj-$(CONFIG_X86_PCC_CPUFREQ) += pcc-cpufreq.o
obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o
obj-$(CONFIG_X86_POWERNOW_K7) += powernow-k7.o
obj-$(CONFIG_X86_LONGHAUL) += longhaul.o
diff --git a/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
new file mode 100644
index 00000000000..ff36d2979a9
--- /dev/null
+++ b/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
@@ -0,0 +1,620 @@
+/*
+ * pcc-cpufreq.c - Processor Clocking Control firmware cpufreq interface
+ *
+ * Copyright (C) 2009 Red Hat, Matthew Garrett <mjg@redhat.com>
+ * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
+ * Nagananda Chumbalkar <nagananda.chumbalkar@hp.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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or NON
+ * INFRINGEMENT. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/sched.h>
+#include <linux/cpufreq.h>
+#include <linux/compiler.h>
+
+#include <linux/acpi.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+
+#include <acpi/processor.h>
+
+#define PCC_VERSION "1.00.00"
+#define POLL_LOOPS 300
+
+#define CMD_COMPLETE 0x1
+#define CMD_GET_FREQ 0x0
+#define CMD_SET_FREQ 0x1
+
+#define BUF_SZ 4
+
+#define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, \
+ "pcc-cpufreq", msg)
+
+struct pcc_register_resource {
+ u8 descriptor;
+ u16 length;
+ u8 space_id;
+ u8 bit_width;
+ u8 bit_offset;
+ u8 access_size;
+ u64 address;
+} __attribute__ ((packed));
+
+struct pcc_memory_resource {
+ u8 descriptor;
+ u16 length;
+ u8 space_id;
+ u8 resource_usage;
+ u8 type_specific;
+ u64 granularity;
+ u64 minimum;
+ u64 maximum;
+ u64 translation_offset;
+ u64 address_length;
+} __attribute__ ((packed));
+
+static struct cpufreq_driver pcc_cpufreq_driver;
+
+struct pcc_header {
+ u32 signature;
+ u16 length;
+ u8 major;
+ u8 minor;
+ u32 features;
+ u16 command;
+ u16 status;
+ u32 latency;
+ u32 minimum_time;
+ u32 maximum_time;
+ u32 nominal;
+ u32 throttled_frequency;
+ u32 minimum_frequency;
+};
+
+static void __iomem *pcch_virt_addr;
+static struct pcc_header __iomem *pcch_hdr;
+
+static DEFINE_SPINLOCK(pcc_lock);
+
+static struct acpi_generic_address doorbell;
+
+static u64 doorbell_preserve;
+static u64 doorbell_write;
+
+static u8 OSC_UUID[16] = {0x63, 0x9B, 0x2C, 0x9F, 0x70, 0x91, 0x49, 0x1f,
+ 0xBB, 0x4F, 0xA5, 0x98, 0x2F, 0xA1, 0xB5, 0x46};
+
+struct pcc_cpu {
+ u32 input_offset;
+ u32 output_offset;
+};
+
+static struct pcc_cpu *pcc_cpu_info;
+
+static int pcc_cpufreq_verify(struct cpufreq_policy *policy)
+{
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
+ policy->cpuinfo.max_freq);
+ return 0;
+}
+
+static inline void pcc_cmd(void)
+{
+ u64 doorbell_value;
+ int i;
+
+ acpi_read(&doorbell_value, &doorbell);
+ acpi_write((doorbell_value & doorbell_preserve) | doorbell_write,
+ &doorbell);
+
+ for (i = 0; i < POLL_LOOPS; i++) {
+ if (ioread16(&pcch_hdr->status) & CMD_COMPLETE)
+ break;
+ }
+}
+
+static inline void pcc_clear_mapping(void)
+{
+ if (pcch_virt_addr)
+ iounmap(pcch_virt_addr);
+ pcch_virt_addr = NULL;
+}
+
+static unsigned int pcc_get_freq(unsigned int cpu)
+{
+ struct pcc_cpu *pcc_cpu_data;
+ unsigned int curr_freq;
+ unsigned int freq_limit;
+ u16 status;
+ u32 input_buffer;
+ u32 output_buffer;
+
+ spin_lock(&pcc_lock);
+
+ dprintk("get: get_freq for CPU %d\n", cpu);
+ pcc_cpu_data = per_cpu_ptr(pcc_cpu_info, cpu);
+
+ input_buffer = 0x1;
+ iowrite32(input_buffer,
+ (pcch_virt_addr + pcc_cpu_data->input_offset));
+ iowrite16(CMD_GET_FREQ, &pcch_hdr->command);
+
+ pcc_cmd();
+
+ output_buffer =
+ ioread32(pcch_virt_addr + pcc_cpu_data->output_offset);
+
+ /* Clear the input buffer - we are done with the current command */
+ memset_io((pcch_virt_addr + pcc_cpu_data->input_offset), 0, BUF_SZ);
+
+ status = ioread16(&pcch_hdr->status);
+ if (status != CMD_COMPLETE) {
+ dprintk("get: FAILED: for CPU %d, status is %d\n",
+ cpu, status);
+ goto cmd_incomplete;
+ }
+ iowrite16(0, &pcch_hdr->status);
+ curr_freq = (((ioread32(&pcch_hdr->nominal) * (output_buffer & 0xff))
+ / 100) * 1000);
+
+ dprintk("get: SUCCESS: (virtual) output_offset for cpu %d is "
+ "0x%x, contains a value of: 0x%x. Speed is: %d MHz\n",
+ cpu, (pcch_virt_addr + pcc_cpu_data->output_offset),
+ output_buffer, curr_freq);
+
+ freq_limit = (output_buffer >> 8) & 0xff;
+ if (freq_limit != 0xff) {
+ dprintk("get: frequency for cpu %d is being temporarily"
+ " capped at %d\n", cpu, curr_freq);
+ }
+
+ spin_unlock(&pcc_lock);
+ return curr_freq;
+
+cmd_incomplete:
+ iowrite16(0, &pcch_hdr->status);
+ spin_unlock(&pcc_lock);
+ return -EINVAL;
+}
+
+static int pcc_cpufreq_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ struct pcc_cpu *pcc_cpu_data;
+ struct cpufreq_freqs freqs;
+ u16 status;
+ u32 input_buffer;
+ int cpu;
+
+ spin_lock(&pcc_lock);
+ cpu = policy->cpu;
+ pcc_cpu_data = per_cpu_ptr(pcc_cpu_info, cpu);
+
+ dprintk("target: CPU %d should go to target freq: %d "
+ "(virtual) input_offset is 0x%x\n",
+ cpu, target_freq,
+ (pcch_virt_addr + pcc_cpu_data->input_offset));
+
+ freqs.new = target_freq;
+ freqs.cpu = cpu;
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+ input_buffer = 0x1 | (((target_freq * 100)
+ / (ioread32(&pcch_hdr->nominal) * 1000)) << 8);
+ iowrite32(input_buffer,
+ (pcch_virt_addr + pcc_cpu_data->input_offset));
+ iowrite16(CMD_SET_FREQ, &pcch_hdr->command);
+
+ pcc_cmd();
+
+ /* Clear the input buffer - we are done with the current command */
+ memset_io((pcch_virt_addr + pcc_cpu_data->input_offset), 0, BUF_SZ);
+
+ status = ioread16(&pcch_hdr->status);
+ if (status != CMD_COMPLETE) {
+ dprintk("target: FAILED for cpu %d, with status: 0x%x\n",
+ cpu, status);
+ goto cmd_incomplete;
+ }
+ iowrite16(0, &pcch_hdr->status);
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ dprintk("target: was SUCCESSFUL for cpu %d\n", cpu);
+ spin_unlock(&pcc_lock);
+
+ return 0;
+
+cmd_incomplete:
+ iowrite16(0, &pcch_hdr->status);
+ spin_unlock(&pcc_lock);
+ return -EINVAL;
+}
+
+static int pcc_get_offset(int cpu)
+{
+ acpi_status status;
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ union acpi_object *pccp, *offset;
+ struct pcc_cpu *pcc_cpu_data;
+ struct acpi_processor *pr;
+ int ret = 0;
+
+ pr = per_cpu(processors, cpu);
+ pcc_cpu_data = per_cpu_ptr(pcc_cpu_info, cpu);
+
+ status = acpi_evaluate_object(pr->handle, "PCCP", NULL, &buffer);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ pccp = buffer.pointer;
+ if (!pccp || pccp->type != ACPI_TYPE_PACKAGE) {
+ ret = -ENODEV;
+ goto out_free;
+ };
+
+ offset = &(pccp->package.elements[0]);
+ if (!offset || offset->type != ACPI_TYPE_INTEGER) {
+ ret = -ENODEV;
+ goto out_free;
+ }
+
+ pcc_cpu_data->input_offset = offset->integer.value;
+
+ offset = &(pccp->package.elements[1]);
+ if (!offset || offset->type != ACPI_TYPE_INTEGER) {
+ ret = -ENODEV;
+ goto out_free;
+ }
+
+ pcc_cpu_data->output_offset = offset->integer.value;
+
+ memset_io((pcch_virt_addr + pcc_cpu_data->input_offset), 0, BUF_SZ);
+ memset_io((pcch_virt_addr + pcc_cpu_data->output_offset), 0, BUF_SZ);
+
+ dprintk("pcc_get_offset: for CPU %d: pcc_cpu_data "
+ "input_offset: 0x%x, pcc_cpu_data output_offset: 0x%x\n",
+ cpu, pcc_cpu_data->input_offset, pcc_cpu_data->output_offset);
+out_free:
+ kfree(buffer.pointer);
+ return ret;
+}
+
+static int __init pcc_cpufreq_do_osc(acpi_handle *handle)
+{
+ acpi_status status;
+ struct acpi_object_list input;
+ struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+ union acpi_object in_params[4];
+ union acpi_object *out_obj;
+ u32 capabilities[2];
+ u32 errors;
+ u32 supported;
+ int ret = 0;
+
+ input.count = 4;
+ input.pointer = in_params;
+ input.count = 4;
+ input.pointer = in_params;
+ in_params[0].type = ACPI_TYPE_BUFFER;
+ in_params[0].buffer.length = 16;
+ in_params[0].buffer.pointer = OSC_UUID;
+ in_params[1].type = ACPI_TYPE_INTEGER;
+ in_params[1].integer.value = 1;
+ in_params[2].type = ACPI_TYPE_INTEGER;
+ in_params[2].integer.value = 2;
+ in_params[3].type = ACPI_TYPE_BUFFER;
+ in_params[3].buffer.length = 8;
+ in_params[3].buffer.pointer = (u8 *)&capabilities;
+
+ capabilities[0] = OSC_QUERY_ENABLE;
+ capabilities[1] = 0x1;
+
+ status = acpi_evaluate_object(*handle, "_OSC", &input, &output);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ if (!output.length)
+ return -ENODEV;
+
+ out_obj = output.pointer;
+ if (out_obj->type != ACPI_TYPE_BUFFER) {
+ ret = -ENODEV;
+ goto out_free;
+ }
+
+ errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0);
+ if (errors) {
+ ret = -ENODEV;
+ goto out_free;
+ }
+
+ supported = *((u32 *)(out_obj->buffer.pointer + 4));
+ if (!(supported & 0x1)) {
+ ret = -ENODEV;
+ goto out_free;
+ }
+
+ kfree(output.pointer);
+ capabilities[0] = 0x0;
+ capabilities[1] = 0x1;
+
+ status = acpi_evaluate_object(*handle, "_OSC", &input, &output);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ if (!output.length)
+ return -ENODEV;
+
+ out_obj = output.pointer;
+ if (out_obj->type != ACPI_TYPE_BUFFER) {
+ ret = -ENODEV;
+ goto out_free;
+ }
+
+ errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0);
+ if (errors) {
+ ret = -ENODEV;
+ goto out_free;
+ }
+
+ supported = *((u32 *)(out_obj->buffer.pointer + 4));
+ if (!(supported & 0x1)) {
+ ret = -ENODEV;
+ goto out_free;
+ }
+
+out_free:
+ kfree(output.pointer);
+ return ret;
+}
+
+static int __init pcc_cpufreq_probe(void)
+{
+ acpi_status status;
+ struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+ struct pcc_memory_resource *mem_resource;
+ struct pcc_register_resource *reg_resource;
+ union acpi_object *out_obj, *member;
+ acpi_handle handle, osc_handle;
+ int ret = 0;
+
+ status = acpi_get_handle(NULL, "\\_SB", &handle);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ status = acpi_get_handle(handle, "_OSC", &osc_handle);
+ if (ACPI_SUCCESS(status)) {
+ ret = pcc_cpufreq_do_osc(&osc_handle);
+ if (ret)
+ dprintk("probe: _OSC evaluation did not succeed\n");
+ /* Firmware's use of _OSC is optional */
+ ret = 0;
+ }
+
+ status = acpi_evaluate_object(handle, "PCCH", NULL, &output);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ out_obj = output.pointer;
+ if (out_obj->type != ACPI_TYPE_PACKAGE) {
+ ret = -ENODEV;
+ goto out_free;
+ }
+
+ member = &out_obj->package.elements[0];
+ if (member->type != ACPI_TYPE_BUFFER) {
+ ret = -ENODEV;
+ goto out_free;
+ }
+
+ mem_resource = (struct pcc_memory_resource *)member->buffer.pointer;
+
+ dprintk("probe: mem_resource descriptor: 0x%x,"
+ " length: %d, space_id: %d, resource_usage: %d,"
+ " type_specific: %d, granularity: 0x%llx,"
+ " minimum: 0x%llx, maximum: 0x%llx,"
+ " translation_offset: 0x%llx, address_length: 0x%llx\n",
+ mem_resource->descriptor, mem_resource->length,
+ mem_resource->space_id, mem_resource->resource_usage,
+ mem_resource->type_specific, mem_resource->granularity,
+ mem_resource->minimum, mem_resource->maximum,
+ mem_resource->translation_offset,
+ mem_resource->address_length);
+
+ if (mem_resource->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) {
+ ret = -ENODEV;
+ goto out_free;
+ }
+
+ pcch_virt_addr = ioremap_nocache(mem_resource->minimum,
+ mem_resource->address_length);
+ if (pcch_virt_addr == NULL) {
+ dprintk("probe: could not map shared mem region\n");
+ goto out_free;
+ }
+ pcch_hdr = pcch_virt_addr;
+
+ dprintk("probe: PCCH header (virtual) addr: 0x%p\n", pcch_hdr);
+ dprintk("probe: PCCH header is at physical address: 0x%llx,"
+ " signature: 0x%x, length: %d bytes, major: %d, minor: %d,"
+ " supported features: 0x%x, command field: 0x%x,"
+ " status field: 0x%x, nominal latency: %d us\n",
+ mem_resource->minimum, ioread32(&pcch_hdr->signature),
+ ioread16(&pcch_hdr->length), ioread8(&pcch_hdr->major),
+ ioread8(&pcch_hdr->minor), ioread32(&pcch_hdr->features),
+ ioread16(&pcch_hdr->command), ioread16(&pcch_hdr->status),
+ ioread32(&pcch_hdr->latency));
+
+ dprintk("probe: min time between commands: %d us,"
+ " max time between commands: %d us,"
+ " nominal CPU frequency: %d MHz,"
+ " minimum CPU frequency: %d MHz,"
+ " minimum CPU frequency without throttling: %d MHz\n",
+ ioread32(&pcch_hdr->minimum_time),
+ ioread32(&pcch_hdr->maximum_time),
+ ioread32(&pcch_hdr->nominal),
+ ioread32(&pcch_hdr->throttled_frequency),
+ ioread32(&pcch_hdr->minimum_frequency));
+
+ member = &out_obj->package.elements[1];
+ if (member->type != ACPI_TYPE_BUFFER) {
+ ret = -ENODEV;
+ goto pcch_free;
+ }
+
+ reg_resource = (struct pcc_register_resource *)member->buffer.pointer;
+
+ doorbell.space_id = reg_resource->space_id;
+ doorbell.bit_width = reg_resource->bit_width;
+ doorbell.bit_offset = reg_resource->bit_offset;
+ doorbell.access_width = 64;
+ doorbell.address = reg_resource->address;
+
+ dprintk("probe: doorbell: space_id is %d, bit_width is %d, "
+ "bit_offset is %d, access_width is %d, address is 0x%llx\n",
+ doorbell.space_id, doorbell.bit_width, doorbell.bit_offset,
+ doorbell.access_width, reg_resource->address);
+
+ member = &out_obj->package.elements[2];
+ if (member->type != ACPI_TYPE_INTEGER) {
+ ret = -ENODEV;
+ goto pcch_free;
+ }
+
+ doorbell_preserve = member->integer.value;
+
+ member = &out_obj->package.elements[3];
+ if (member->type != ACPI_TYPE_INTEGER) {
+ ret = -ENODEV;
+ goto pcch_free;
+ }
+
+ doorbell_write = member->integer.value;
+
+ dprintk("probe: doorbell_preserve: 0x%llx,"
+ " doorbell_write: 0x%llx\n",
+ doorbell_preserve, doorbell_write);
+
+ pcc_cpu_info = alloc_percpu(struct pcc_cpu);
+ if (!pcc_cpu_info) {
+ ret = -ENOMEM;
+ goto pcch_free;
+ }
+
+ printk(KERN_DEBUG "pcc-cpufreq: (v%s) driver loaded with frequency"
+ " limits: %d MHz, %d MHz\n", PCC_VERSION,
+ ioread32(&pcch_hdr->minimum_frequency),
+ ioread32(&pcch_hdr->nominal));
+ kfree(output.pointer);
+ return ret;
+pcch_free:
+ pcc_clear_mapping();
+out_free:
+ kfree(output.pointer);
+ return ret;
+}
+
+static int pcc_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+ unsigned int cpu = policy->cpu;
+ unsigned int result = 0;
+
+ if (!pcch_virt_addr) {
+ result = -1;
+ goto pcch_null;
+ }
+
+ result = pcc_get_offset(cpu);
+ if (result) {
+ dprintk("init: PCCP evaluation failed\n");
+ goto free;
+ }
+
+ policy->max = policy->cpuinfo.max_freq =
+ ioread32(&pcch_hdr->nominal) * 1000;
+ policy->min = policy->cpuinfo.min_freq =
+ ioread32(&pcch_hdr->minimum_frequency) * 1000;
+ policy->cur = pcc_get_freq(cpu);
+
+ dprintk("init: policy->max is %d, policy->min is %d\n",
+ policy->max, policy->min);
+
+ return 0;
+free:
+ pcc_clear_mapping();
+ free_percpu(pcc_cpu_info);
+pcch_null:
+ return result;
+}
+
+static int pcc_cpufreq_cpu_exit(struct cpufreq_policy *policy)
+{
+ return 0;
+}
+
+static struct cpufreq_driver pcc_cpufreq_driver = {
+ .flags = CPUFREQ_CONST_LOOPS,
+ .get = pcc_get_freq,
+ .verify = pcc_cpufreq_verify,
+ .target = pcc_cpufreq_target,
+ .init = pcc_cpufreq_cpu_init,
+ .exit = pcc_cpufreq_cpu_exit,
+ .name = "pcc-cpufreq",
+ .owner = THIS_MODULE,
+};
+
+static int __init pcc_cpufreq_init(void)
+{
+ int ret;
+
+ if (acpi_disabled)
+ return 0;
+
+ ret = pcc_cpufreq_probe();
+ if (ret) {
+ dprintk("pcc_cpufreq_init: PCCH evaluation failed\n");
+ return ret;
+ }
+
+ ret = cpufreq_register_driver(&pcc_cpufreq_driver);
+
+ return ret;
+}
+
+static void __exit pcc_cpufreq_exit(void)
+{
+ cpufreq_unregister_driver(&pcc_cpufreq_driver);
+
+ pcc_clear_mapping();
+
+ free_percpu(pcc_cpu_info);
+}
+
+MODULE_AUTHOR("Matthew Garrett, Naga Chumbalkar");
+MODULE_VERSION(PCC_VERSION);
+MODULE_DESCRIPTION("Processor Clocking Control interface driver");
+MODULE_LICENSE("GPL");
+
+late_initcall(pcc_cpufreq_init);
+module_exit(pcc_cpufreq_exit);
diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c
index eddb1bdd1b8..b3eeb66c0a5 100644
--- a/arch/x86/kernel/cpu/intel_cacheinfo.c
+++ b/arch/x86/kernel/cpu/intel_cacheinfo.c
@@ -903,7 +903,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
return ret;
}
-static struct sysfs_ops sysfs_ops = {
+static const struct sysfs_ops sysfs_ops = {
.show = show,
.store = store,
};
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index a8aacd4b513..28cba46bf32 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -2044,6 +2044,7 @@ static __init void mce_init_banks(void)
struct mce_bank *b = &mce_banks[i];
struct sysdev_attribute *a = &b->attr;
+ sysfs_attr_init(&a->attr);
a->attr.name = b->attrname;
snprintf(b->attrname, ATTR_LEN, "bank%d", i);
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 83a3d1f4efc..cda932ca3ad 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -388,7 +388,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
return ret;
}
-static struct sysfs_ops threshold_ops = {
+static const struct sysfs_ops threshold_ops = {
.show = show,
.store = store,
};
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 641ccb9dddb..b1fbdeecf6c 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -676,7 +676,7 @@ static int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
if (c->weight != w)
continue;
- for_each_bit(j, c->idxmsk, X86_PMC_IDX_MAX) {
+ for_each_set_bit(j, c->idxmsk, X86_PMC_IDX_MAX) {
if (!test_bit(j, used_mask))
break;
}
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index cf6590cf4a5..977e7544738 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -757,7 +757,7 @@ again:
inc_irq_stat(apic_perf_irqs);
ack = status;
- for_each_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
+ for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
struct perf_event *event = cpuc->events[bit];
clear_bit(bit, (unsigned long *) &status);
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c
index 8c93a84bb62..fb725ee15f5 100644
--- a/arch/x86/kernel/i8259.c
+++ b/arch/x86/kernel/i8259.c
@@ -34,6 +34,12 @@
static int i8259A_auto_eoi;
DEFINE_RAW_SPINLOCK(i8259A_lock);
static void mask_and_ack_8259A(unsigned int);
+static void mask_8259A(void);
+static void unmask_8259A(void);
+static void disable_8259A_irq(unsigned int irq);
+static void enable_8259A_irq(unsigned int irq);
+static void init_8259A(int auto_eoi);
+static int i8259A_irq_pending(unsigned int irq);
struct irq_chip i8259A_chip = {
.name = "XT-PIC",
@@ -63,7 +69,7 @@ unsigned int cached_irq_mask = 0xffff;
*/
unsigned long io_apic_irqs;
-void disable_8259A_irq(unsigned int irq)
+static void disable_8259A_irq(unsigned int irq)
{
unsigned int mask = 1 << irq;
unsigned long flags;
@@ -77,7 +83,7 @@ void disable_8259A_irq(unsigned int irq)
raw_spin_unlock_irqrestore(&i8259A_lock, flags);
}
-void enable_8259A_irq(unsigned int irq)
+static void enable_8259A_irq(unsigned int irq)
{
unsigned int mask = ~(1 << irq);
unsigned long flags;
@@ -91,7 +97,7 @@ void enable_8259A_irq(unsigned int irq)
raw_spin_unlock_irqrestore(&i8259A_lock, flags);
}
-int i8259A_irq_pending(unsigned int irq)
+static int i8259A_irq_pending(unsigned int irq)
{
unsigned int mask = 1<<irq;
unsigned long flags;
@@ -107,7 +113,7 @@ int i8259A_irq_pending(unsigned int irq)
return ret;
}
-void make_8259A_irq(unsigned int irq)
+static void make_8259A_irq(unsigned int irq)
{
disable_irq_nosync(irq);
io_apic_irqs &= ~(1<<irq);
@@ -281,7 +287,7 @@ static int __init i8259A_init_sysfs(void)
device_initcall(i8259A_init_sysfs);
-void mask_8259A(void)
+static void mask_8259A(void)
{
unsigned long flags;
@@ -293,7 +299,7 @@ void mask_8259A(void)
raw_spin_unlock_irqrestore(&i8259A_lock, flags);
}
-void unmask_8259A(void)
+static void unmask_8259A(void)
{
unsigned long flags;
@@ -305,7 +311,7 @@ void unmask_8259A(void)
raw_spin_unlock_irqrestore(&i8259A_lock, flags);
}
-void init_8259A(int auto_eoi)
+static void init_8259A(int auto_eoi)
{
unsigned long flags;
@@ -358,3 +364,47 @@ void init_8259A(int auto_eoi)
raw_spin_unlock_irqrestore(&i8259A_lock, flags);
}
+
+/*
+ * make i8259 a driver so that we can select pic functions at run time. the goal
+ * is to make x86 binary compatible among pc compatible and non-pc compatible
+ * platforms, such as x86 MID.
+ */
+
+static void legacy_pic_noop(void) { };
+static void legacy_pic_uint_noop(unsigned int unused) { };
+static void legacy_pic_int_noop(int unused) { };
+
+static struct irq_chip dummy_pic_chip = {
+ .name = "dummy pic",
+ .mask = legacy_pic_uint_noop,
+ .unmask = legacy_pic_uint_noop,
+ .disable = legacy_pic_uint_noop,
+ .mask_ack = legacy_pic_uint_noop,
+};
+static int legacy_pic_irq_pending_noop(unsigned int irq)
+{
+ return 0;
+}
+
+struct legacy_pic null_legacy_pic = {
+ .nr_legacy_irqs = 0,
+ .chip = &dummy_pic_chip,
+ .mask_all = legacy_pic_noop,
+ .restore_mask = legacy_pic_noop,
+ .init = legacy_pic_int_noop,
+ .irq_pending = legacy_pic_irq_pending_noop,
+ .make_irq = legacy_pic_uint_noop,
+};
+
+struct legacy_pic default_legacy_pic = {
+ .nr_legacy_irqs = NR_IRQS_LEGACY,
+ .chip = &i8259A_chip,
+ .mask_all = mask_8259A,
+ .restore_mask = unmask_8259A,
+ .init = init_8259A,
+ .irq_pending = i8259A_irq_pending,
+ .make_irq = make_8259A_irq,
+};
+
+struct legacy_pic *legacy_pic = &default_legacy_pic;
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index fce55d53263..ef257fc2921 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -99,9 +99,6 @@ int vector_used_by_percpu_irq(unsigned int vector)
return 0;
}
-/* Number of legacy interrupts */
-int nr_legacy_irqs __read_mostly = NR_IRQS_LEGACY;
-
void __init init_ISA_irqs(void)
{
int i;
@@ -109,12 +106,12 @@ void __init init_ISA_irqs(void)
#if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC)
init_bsp_APIC();
#endif
- init_8259A(0);
+ legacy_pic->init(0);
/*
* 16 old-style INTA-cycle interrupts:
*/
- for (i = 0; i < NR_IRQS_LEGACY; i++) {
+ for (i = 0; i < legacy_pic->nr_legacy_irqs; i++) {
struct irq_desc *desc = irq_to_desc(i);
desc->status = IRQ_DISABLED;
@@ -138,7 +135,7 @@ void __init init_IRQ(void)
* then this vector space can be freed and re-used dynamically as the
* irq's migrate etc.
*/
- for (i = 0; i < nr_legacy_irqs; i++)
+ for (i = 0; i < legacy_pic->nr_legacy_irqs; i++)
per_cpu(vector_irq, 0)[IRQ0_VECTOR + i] = i;
x86_init.irqs.intr_init();
diff --git a/arch/x86/kernel/mrst.c b/arch/x86/kernel/mrst.c
index 3b7078abc87..0aad8670858 100644
--- a/arch/x86/kernel/mrst.c
+++ b/arch/x86/kernel/mrst.c
@@ -10,8 +10,211 @@
* of the License.
*/
#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/sfi.h>
+#include <linux/irq.h>
+#include <linux/module.h>
#include <asm/setup.h>
+#include <asm/mpspec_def.h>
+#include <asm/hw_irq.h>
+#include <asm/apic.h>
+#include <asm/io_apic.h>
+#include <asm/mrst.h>
+#include <asm/io.h>
+#include <asm/i8259.h>
+#include <asm/apb_timer.h>
+
+static u32 sfi_mtimer_usage[SFI_MTMR_MAX_NUM];
+static struct sfi_timer_table_entry sfi_mtimer_array[SFI_MTMR_MAX_NUM];
+int sfi_mtimer_num;
+
+struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX];
+EXPORT_SYMBOL_GPL(sfi_mrtc_array);
+int sfi_mrtc_num;
+
+static inline void assign_to_mp_irq(struct mpc_intsrc *m,
+ struct mpc_intsrc *mp_irq)
+{
+ memcpy(mp_irq, m, sizeof(struct mpc_intsrc));
+}
+
+static inline int mp_irq_cmp(struct mpc_intsrc *mp_irq,
+ struct mpc_intsrc *m)
+{
+ return memcmp(mp_irq, m, sizeof(struct mpc_intsrc));
+}
+
+static void save_mp_irq(struct mpc_intsrc *m)
+{
+ int i;
+
+ for (i = 0; i < mp_irq_entries; i++) {
+ if (!mp_irq_cmp(&mp_irqs[i], m))
+ return;
+ }
+
+ assign_to_mp_irq(m, &mp_irqs[mp_irq_entries]);
+ if (++mp_irq_entries == MAX_IRQ_SOURCES)
+ panic("Max # of irq sources exceeded!!\n");
+}
+
+/* parse all the mtimer info to a static mtimer array */
+static int __init sfi_parse_mtmr(struct sfi_table_header *table)
+{
+ struct sfi_table_simple *sb;
+ struct sfi_timer_table_entry *pentry;
+ struct mpc_intsrc mp_irq;
+ int totallen;
+
+ sb = (struct sfi_table_simple *)table;
+ if (!sfi_mtimer_num) {
+ sfi_mtimer_num = SFI_GET_NUM_ENTRIES(sb,
+ struct sfi_timer_table_entry);
+ pentry = (struct sfi_timer_table_entry *) sb->pentry;
+ totallen = sfi_mtimer_num * sizeof(*pentry);
+ memcpy(sfi_mtimer_array, pentry, totallen);
+ }
+
+ printk(KERN_INFO "SFI: MTIMER info (num = %d):\n", sfi_mtimer_num);
+ pentry = sfi_mtimer_array;
+ for (totallen = 0; totallen < sfi_mtimer_num; totallen++, pentry++) {
+ printk(KERN_INFO "timer[%d]: paddr = 0x%08x, freq = %dHz,"
+ " irq = %d\n", totallen, (u32)pentry->phys_addr,
+ pentry->freq_hz, pentry->irq);
+ if (!pentry->irq)
+ continue;
+ mp_irq.type = MP_IOAPIC;
+ mp_irq.irqtype = mp_INT;
+/* triggering mode edge bit 2-3, active high polarity bit 0-1 */
+ mp_irq.irqflag = 5;
+ mp_irq.srcbus = 0;
+ mp_irq.srcbusirq = pentry->irq; /* IRQ */
+ mp_irq.dstapic = MP_APIC_ALL;
+ mp_irq.dstirq = pentry->irq;
+ save_mp_irq(&mp_irq);
+ }
+
+ return 0;
+}
+
+struct sfi_timer_table_entry *sfi_get_mtmr(int hint)
+{
+ int i;
+ if (hint < sfi_mtimer_num) {
+ if (!sfi_mtimer_usage[hint]) {
+ pr_debug("hint taken for timer %d irq %d\n",\
+ hint, sfi_mtimer_array[hint].irq);
+ sfi_mtimer_usage[hint] = 1;
+ return &sfi_mtimer_array[hint];
+ }
+ }
+ /* take the first timer available */
+ for (i = 0; i < sfi_mtimer_num;) {
+ if (!sfi_mtimer_usage[i]) {
+ sfi_mtimer_usage[i] = 1;
+ return &sfi_mtimer_array[i];
+ }
+ i++;
+ }
+ return NULL;
+}
+
+void sfi_free_mtmr(struct sfi_timer_table_entry *mtmr)
+{
+ int i;
+ for (i = 0; i < sfi_mtimer_num;) {
+ if (mtmr->irq == sfi_mtimer_array[i].irq) {
+ sfi_mtimer_usage[i] = 0;
+ return;
+ }
+ i++;
+ }
+}
+
+/* parse all the mrtc info to a global mrtc array */
+int __init sfi_parse_mrtc(struct sfi_table_header *table)
+{
+ struct sfi_table_simple *sb;
+ struct sfi_rtc_table_entry *pentry;
+ struct mpc_intsrc mp_irq;
+
+ int totallen;
+
+ sb = (struct sfi_table_simple *)table;
+ if (!sfi_mrtc_num) {
+ sfi_mrtc_num = SFI_GET_NUM_ENTRIES(sb,
+ struct sfi_rtc_table_entry);
+ pentry = (struct sfi_rtc_table_entry *)sb->pentry;
+ totallen = sfi_mrtc_num * sizeof(*pentry);
+ memcpy(sfi_mrtc_array, pentry, totallen);
+ }
+
+ printk(KERN_INFO "SFI: RTC info (num = %d):\n", sfi_mrtc_num);
+ pentry = sfi_mrtc_array;
+ for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) {
+ printk(KERN_INFO "RTC[%d]: paddr = 0x%08x, irq = %d\n",
+ totallen, (u32)pentry->phys_addr, pentry->irq);
+ mp_irq.type = MP_IOAPIC;
+ mp_irq.irqtype = mp_INT;
+ mp_irq.irqflag = 0;
+ mp_irq.srcbus = 0;
+ mp_irq.srcbusirq = pentry->irq; /* IRQ */
+ mp_irq.dstapic = MP_APIC_ALL;
+ mp_irq.dstirq = pentry->irq;
+ save_mp_irq(&mp_irq);
+ }
+ return 0;
+}
+
+/*
+ * the secondary clock in Moorestown can be APBT or LAPIC clock, default to
+ * APBT but cmdline option can also override it.
+ */
+static void __cpuinit mrst_setup_secondary_clock(void)
+{
+ /* restore default lapic clock if disabled by cmdline */
+ if (disable_apbt_percpu)
+ return setup_secondary_APIC_clock();
+ apbt_setup_secondary_clock();
+}
+
+static unsigned long __init mrst_calibrate_tsc(void)
+{
+ unsigned long flags, fast_calibrate;
+
+ local_irq_save(flags);
+ fast_calibrate = apbt_quick_calibrate();
+ local_irq_restore(flags);
+
+ if (fast_calibrate)
+ return fast_calibrate;
+
+ return 0;
+}
+
+void __init mrst_time_init(void)
+{
+ sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr);
+ pre_init_apic_IRQ0();
+ apbt_time_init();
+}
+
+void __init mrst_rtc_init(void)
+{
+ sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc);
+}
+
+/*
+ * if we use per cpu apb timer, the bootclock already setup. if we use lapic
+ * timer and one apbt timer for broadcast, we need to set up lapic boot clock.
+ */
+static void __init mrst_setup_boot_clock(void)
+{
+ pr_info("%s: per cpu apbt flag %d \n", __func__, disable_apbt_percpu);
+ if (disable_apbt_percpu)
+ setup_boot_APIC_clock();
+};
/*
* Moorestown specific x86_init function overrides and early setup
@@ -21,4 +224,17 @@ void __init x86_mrst_early_setup(void)
{
x86_init.resources.probe_roms = x86_init_noop;
x86_init.resources.reserve_resources = x86_init_noop;
+
+ x86_init.timers.timer_init = mrst_time_init;
+ x86_init.timers.setup_percpu_clockev = mrst_setup_boot_clock;
+
+ x86_init.irqs.pre_vector_init = x86_init_noop;
+
+ x86_cpuinit.setup_percpu_clockev = mrst_setup_secondary_clock;
+
+ x86_platform.calibrate_tsc = mrst_calibrate_tsc;
+ x86_init.pci.init = pci_mrst_init;
+ x86_init.pci.fixup_irqs = x86_init_noop;
+
+ legacy_pic = &null_legacy_pic;
}
diff --git a/arch/x86/kernel/olpc.c b/arch/x86/kernel/olpc.c
index 9d1d263f786..8297160c41b 100644
--- a/arch/x86/kernel/olpc.c
+++ b/arch/x86/kernel/olpc.c
@@ -17,7 +17,9 @@
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/string.h>
+
#include <asm/geode.h>
+#include <asm/setup.h>
#include <asm/olpc.h>
#ifdef CONFIG_OPEN_FIRMWARE
@@ -243,9 +245,11 @@ static int __init olpc_init(void)
olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0,
(unsigned char *) &olpc_platform_info.ecver, 1);
- /* check to see if the VSA exists */
- if (cs5535_has_vsa2())
- olpc_platform_info.flags |= OLPC_F_VSA;
+#ifdef CONFIG_PCI_OLPC
+ /* If the VSA exists let it emulate PCI, if not emulate in kernel */
+ if (!cs5535_has_vsa2())
+ x86_init.pci.arch_init = pci_olpc_init;
+#endif
printk(KERN_INFO "OLPC board revision %s%X (EC=%x)\n",
((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "",
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index a435c76d714..a02e80c3c54 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -48,6 +48,7 @@
#include <linux/err.h>
#include <linux/nmi.h>
#include <linux/tboot.h>
+#include <linux/stackprotector.h>
#include <asm/acpi.h>
#include <asm/desc.h>
@@ -67,6 +68,7 @@
#include <linux/mc146818rtc.h>
#include <asm/smpboot_hooks.h>
+#include <asm/i8259.h>
#ifdef CONFIG_X86_32
u8 apicid_2_node[MAX_APICID];
@@ -291,9 +293,9 @@ notrace static void __cpuinit start_secondary(void *unused)
check_tsc_sync_target();
if (nmi_watchdog == NMI_IO_APIC) {
- disable_8259A_irq(0);
+ legacy_pic->chip->mask(0);
enable_NMI_through_LVT0();
- enable_8259A_irq(0);
+ legacy_pic->chip->unmask(0);
}
#ifdef CONFIG_X86_32
@@ -329,6 +331,9 @@ notrace static void __cpuinit start_secondary(void *unused)
/* enable local interrupts */
local_irq_enable();
+ /* to prevent fake stack check failure in clock setup */
+ boot_init_stack_canary();
+
x86_cpuinit.setup_percpu_clockev();
wmb();
diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c
index ab38ce0984f..e680ea52db9 100644
--- a/arch/x86/kernel/visws_quirks.c
+++ b/arch/x86/kernel/visws_quirks.c
@@ -49,11 +49,6 @@ extern int no_broadcast;
char visws_board_type = -1;
char visws_board_rev = -1;
-int is_visws_box(void)
-{
- return visws_board_type >= 0;
-}
-
static void __init visws_time_init(void)
{
printk(KERN_INFO "Starting Cobalt Timer system clock\n");
@@ -242,6 +237,8 @@ void __init visws_early_detect(void)
x86_init.irqs.pre_vector_init = visws_pre_intr_init;
x86_init.irqs.trap_init = visws_trap_init;
x86_init.timers.timer_init = visws_time_init;
+ x86_init.pci.init = pci_visws_init;
+ x86_init.pci.init_irq = x86_init_noop;
/*
* Install reboot quirks:
@@ -508,7 +505,7 @@ static struct irq_chip cobalt_irq_type = {
*/
static unsigned int startup_piix4_master_irq(unsigned int irq)
{
- init_8259A(0);
+ legacy_pic->init(0);
return startup_cobalt_irq(irq);
}
@@ -532,9 +529,6 @@ static struct irq_chip piix4_master_irq_type = {
static struct irq_chip piix4_virtual_irq_type = {
.name = "PIIX4-virtual",
- .shutdown = disable_8259A_irq,
- .enable = enable_8259A_irq,
- .disable = disable_8259A_irq,
};
@@ -609,7 +603,7 @@ static irqreturn_t piix4_master_intr(int irq, void *dev_id)
handle_IRQ_event(realirq, desc->action);
if (!(desc->status & IRQ_DISABLED))
- enable_8259A_irq(realirq);
+ legacy_pic->chip->unmask(realirq);
return IRQ_HANDLED;
@@ -628,6 +622,12 @@ static struct irqaction cascade_action = {
.name = "cascade",
};
+static inline void set_piix4_virtual_irq_type(void)
+{
+ piix4_virtual_irq_type.shutdown = i8259A_chip.mask;
+ piix4_virtual_irq_type.enable = i8259A_chip.unmask;
+ piix4_virtual_irq_type.disable = i8259A_chip.mask;
+}
void init_VISWS_APIC_irqs(void)
{
@@ -653,6 +653,7 @@ void init_VISWS_APIC_irqs(void)
desc->chip = &piix4_master_irq_type;
}
else if (i < CO_IRQ_APIC0) {
+ set_piix4_virtual_irq_type();
desc->chip = &piix4_virtual_irq_type;
}
else if (IS_CO_APIC(i)) {
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index ee5746c9462..61a1e8c7e19 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -4,9 +4,11 @@
* For licencing details see kernel-base/COPYING
*/
#include <linux/init.h>
+#include <linux/ioport.h>
#include <asm/bios_ebda.h>
#include <asm/paravirt.h>
+#include <asm/pci_x86.h>
#include <asm/mpspec.h>
#include <asm/setup.h>
#include <asm/apic.h>
@@ -70,6 +72,12 @@ struct x86_init_ops x86_init __initdata = {
.iommu = {
.iommu_init = iommu_init_noop,
},
+
+ .pci = {
+ .init = x86_default_pci_init,
+ .init_irq = x86_default_pci_init_irq,
+ .fixup_irqs = x86_default_pci_fixup_irqs,
+ },
};
struct x86_cpuinit_ops x86_cpuinit __cpuinitdata = {
diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile
index 0b7d3e9593e..b110d97fb92 100644
--- a/arch/x86/pci/Makefile
+++ b/arch/x86/pci/Makefile
@@ -13,6 +13,8 @@ obj-$(CONFIG_X86_VISWS) += visws.o
obj-$(CONFIG_X86_NUMAQ) += numaq_32.o
+obj-$(CONFIG_X86_MRST) += mrst.o
+
obj-y += common.o early.o
obj-y += amd_bus.o bus_numa.o
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index 5f11ff6f538..6e22454bfaa 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -298,17 +298,14 @@ int __init pci_acpi_init(void)
{
struct pci_dev *dev = NULL;
- if (pcibios_scanned)
- return 0;
-
if (acpi_noirq)
- return 0;
+ return -ENODEV;
printk(KERN_INFO "PCI: Using ACPI for IRQ routing\n");
acpi_irq_penalty_init();
- pcibios_scanned++;
pcibios_enable_irq = acpi_pci_irq_enable;
pcibios_disable_irq = acpi_pci_irq_disable;
+ x86_init.pci.init_irq = x86_init_noop;
if (pci_routeirq) {
/*
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 3736176acaa..294e10cb11e 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -72,12 +72,6 @@ struct pci_ops pci_root_ops = {
};
/*
- * legacy, numa, and acpi all want to call pcibios_scan_root
- * from their initcalls. This flag prevents that.
- */
-int pcibios_scanned;
-
-/*
* This interrupt-safe spinlock protects all accesses to PCI
* configuration space.
*/
diff --git a/arch/x86/pci/init.c b/arch/x86/pci/init.c
index 25a1f8efed4..adb62aaa7ec 100644
--- a/arch/x86/pci/init.c
+++ b/arch/x86/pci/init.c
@@ -1,6 +1,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <asm/pci_x86.h>
+#include <asm/x86_init.h>
/* arch_initcall has too random ordering, so call the initializers
in the right sequence from here. */
@@ -15,10 +16,9 @@ static __init int pci_arch_init(void)
if (!(pci_probe & PCI_PROBE_NOEARLY))
pci_mmcfg_early_init();
-#ifdef CONFIG_PCI_OLPC
- if (!pci_olpc_init())
- return 0; /* skip additional checks if it's an XO */
-#endif
+ if (x86_init.pci.arch_init && !x86_init.pci.arch_init())
+ return 0;
+
#ifdef CONFIG_PCI_BIOS
pci_pcbios_init();
#endif
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
index b02f6d8ac92..8b107521d24 100644
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -53,7 +53,7 @@ struct irq_router_handler {
int (*probe)(struct irq_router *r, struct pci_dev *router, u16 device);
};
-int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL;
+int (*pcibios_enable_irq)(struct pci_dev *dev) = pirq_enable_irq;
void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL;
/*
@@ -1018,7 +1018,7 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
return 1;
}
-static void __init pcibios_fixup_irqs(void)
+void __init pcibios_fixup_irqs(void)
{
struct pci_dev *dev = NULL;
u8 pin;
@@ -1112,12 +1112,12 @@ static struct dmi_system_id __initdata pciirq_dmi_table[] = {
{ }
};
-int __init pcibios_irq_init(void)
+void __init pcibios_irq_init(void)
{
DBG(KERN_DEBUG "PCI: IRQ init\n");
- if (pcibios_enable_irq || raw_pci_ops == NULL)
- return 0;
+ if (raw_pci_ops == NULL)
+ return;
dmi_check_system(pciirq_dmi_table);
@@ -1144,9 +1144,7 @@ int __init pcibios_irq_init(void)
pirq_table = NULL;
}
- pcibios_enable_irq = pirq_enable_irq;
-
- pcibios_fixup_irqs();
+ x86_init.pci.fixup_irqs();
if (io_apic_assign_pci_irqs && pci_routeirq) {
struct pci_dev *dev = NULL;
@@ -1159,8 +1157,6 @@ int __init pcibios_irq_init(void)
for_each_pci_dev(dev)
pirq_enable_irq(dev);
}
-
- return 0;
}
static void pirq_penalize_isa_irq(int irq, int active)
diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c
index 4061bb0f267..0db5eaf5456 100644
--- a/arch/x86/pci/legacy.c
+++ b/arch/x86/pci/legacy.c
@@ -35,16 +35,13 @@ static void __devinit pcibios_fixup_peer_bridges(void)
}
}
-static int __init pci_legacy_init(void)
+int __init pci_legacy_init(void)
{
if (!raw_pci_ops) {
printk("PCI: System does not support PCI\n");
return 0;
}
- if (pcibios_scanned++)
- return 0;
-
printk("PCI: Probing PCI hardware\n");
pci_root_bus = pcibios_scan_root(0);
if (pci_root_bus)
@@ -55,18 +52,15 @@ static int __init pci_legacy_init(void)
int __init pci_subsys_init(void)
{
-#ifdef CONFIG_X86_NUMAQ
- pci_numaq_init();
-#endif
-#ifdef CONFIG_ACPI
- pci_acpi_init();
-#endif
-#ifdef CONFIG_X86_VISWS
- pci_visws_init();
-#endif
- pci_legacy_init();
+ /*
+ * The init function returns an non zero value when
+ * pci_legacy_init should be invoked.
+ */
+ if (x86_init.pci.init())
+ pci_legacy_init();
+
pcibios_fixup_peer_bridges();
- pcibios_irq_init();
+ x86_init.pci.init_irq();
pcibios_init();
return 0;
diff --git a/arch/x86/pci/mrst.c b/arch/x86/pci/mrst.c
new file mode 100644
index 00000000000..8bf2fcb88d0
--- /dev/null
+++ b/arch/x86/pci/mrst.c
@@ -0,0 +1,262 @@
+/*
+ * Moorestown PCI support
+ * Copyright (c) 2008 Intel Corporation
+ * Jesse Barnes <jesse.barnes@intel.com>
+ *
+ * Moorestown has an interesting PCI implementation:
+ * - configuration space is memory mapped (as defined by MCFG)
+ * - Lincroft devices also have a real, type 1 configuration space
+ * - Early Lincroft silicon has a type 1 access bug that will cause
+ * a hang if non-existent devices are accessed
+ * - some devices have the "fixed BAR" capability, which means
+ * they can't be relocated or modified; check for that during
+ * BAR sizing
+ *
+ * So, we use the MCFG space for all reads and writes, but also send
+ * Lincroft writes to type 1 space. But only read/write if the device
+ * actually exists, otherwise return all 1s for reads and bit bucket
+ * the writes.
+ */
+
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/dmi.h>
+
+#include <asm/acpi.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/pci_x86.h>
+#include <asm/hw_irq.h>
+#include <asm/io_apic.h>
+
+#define PCIE_CAP_OFFSET 0x100
+
+/* Fixed BAR fields */
+#define PCIE_VNDR_CAP_ID_FIXED_BAR 0x00 /* Fixed BAR (TBD) */
+#define PCI_FIXED_BAR_0_SIZE 0x04
+#define PCI_FIXED_BAR_1_SIZE 0x08
+#define PCI_FIXED_BAR_2_SIZE 0x0c
+#define PCI_FIXED_BAR_3_SIZE 0x10
+#define PCI_FIXED_BAR_4_SIZE 0x14
+#define PCI_FIXED_BAR_5_SIZE 0x1c
+
+/**
+ * fixed_bar_cap - return the offset of the fixed BAR cap if found
+ * @bus: PCI bus
+ * @devfn: device in question
+ *
+ * Look for the fixed BAR cap on @bus and @devfn, returning its offset
+ * if found or 0 otherwise.
+ */
+static int fixed_bar_cap(struct pci_bus *bus, unsigned int devfn)
+{
+ int pos;
+ u32 pcie_cap = 0, cap_data;
+
+ pos = PCIE_CAP_OFFSET;
+
+ if (!raw_pci_ext_ops)
+ return 0;
+
+ while (pos) {
+ if (raw_pci_ext_ops->read(pci_domain_nr(bus), bus->number,
+ devfn, pos, 4, &pcie_cap))
+ return 0;
+
+ if (pcie_cap == 0xffffffff)
+ return 0;
+
+ if (PCI_EXT_CAP_ID(pcie_cap) == PCI_EXT_CAP_ID_VNDR) {
+ raw_pci_ext_ops->read(pci_domain_nr(bus), bus->number,
+ devfn, pos + 4, 4, &cap_data);
+ if ((cap_data & 0xffff) == PCIE_VNDR_CAP_ID_FIXED_BAR)
+ return pos;
+ }
+
+ pos = pcie_cap >> 20;
+ }
+
+ return 0;
+}
+
+static int pci_device_update_fixed(struct pci_bus *bus, unsigned int devfn,
+ int reg, int len, u32 val, int offset)
+{
+ u32 size;
+ unsigned int domain, busnum;
+ int bar = (reg - PCI_BASE_ADDRESS_0) >> 2;
+
+ domain = pci_domain_nr(bus);
+ busnum = bus->number;
+
+ if (val == ~0 && len == 4) {
+ unsigned long decode;
+
+ raw_pci_ext_ops->read(domain, busnum, devfn,
+ offset + 8 + (bar * 4), 4, &size);
+
+ /* Turn the size into a decode pattern for the sizing code */
+ if (size) {
+ decode = size - 1;
+ decode |= decode >> 1;
+ decode |= decode >> 2;
+ decode |= decode >> 4;
+ decode |= decode >> 8;
+ decode |= decode >> 16;
+ decode++;
+ decode = ~(decode - 1);
+ } else {
+ decode = ~0;
+ }
+
+ /*
+ * If val is all ones, the core code is trying to size the reg,
+ * so update the mmconfig space with the real size.
+ *
+ * Note: this assumes the fixed size we got is a power of two.
+ */
+ return raw_pci_ext_ops->write(domain, busnum, devfn, reg, 4,
+ decode);
+ }
+
+ /* This is some other kind of BAR write, so just do it. */
+ return raw_pci_ext_ops->write(domain, busnum, devfn, reg, len, val);
+}
+
+/**
+ * type1_access_ok - check whether to use type 1
+ * @bus: bus number
+ * @devfn: device & function in question
+ *
+ * If the bus is on a Lincroft chip and it exists, or is not on a Lincroft at
+ * all, the we can go ahead with any reads & writes. If it's on a Lincroft,
+ * but doesn't exist, avoid the access altogether to keep the chip from
+ * hanging.
+ */
+static bool type1_access_ok(unsigned int bus, unsigned int devfn, int reg)
+{
+ /* This is a workaround for A0 LNC bug where PCI status register does
+ * not have new CAP bit set. can not be written by SW either.
+ *
+ * PCI header type in real LNC indicates a single function device, this
+ * will prevent probing other devices under the same function in PCI
+ * shim. Therefore, use the header type in shim instead.
+ */
+ if (reg >= 0x100 || reg == PCI_STATUS || reg == PCI_HEADER_TYPE)
+ return 0;
+ if (bus == 0 && (devfn == PCI_DEVFN(2, 0) || devfn == PCI_DEVFN(0, 0)))
+ return 1;
+ return 0; /* langwell on others */
+}
+
+static int pci_read(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, u32 *value)
+{
+ if (type1_access_ok(bus->number, devfn, where))
+ return pci_direct_conf1.read(pci_domain_nr(bus), bus->number,
+ devfn, where, size, value);
+ return raw_pci_ext_ops->read(pci_domain_nr(bus), bus->number,
+ devfn, where, size, value);
+}
+
+static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
+ int size, u32 value)
+{
+ int offset;
+
+ /* On MRST, there is no PCI ROM BAR, this will cause a subsequent read
+ * to ROM BAR return 0 then being ignored.
+ */
+ if (where == PCI_ROM_ADDRESS)
+ return 0;
+
+ /*
+ * Devices with fixed BARs need special handling:
+ * - BAR sizing code will save, write ~0, read size, restore
+ * - so writes to fixed BARs need special handling
+ * - other writes to fixed BAR devices should go through mmconfig
+ */
+ offset = fixed_bar_cap(bus, devfn);
+ if (offset &&
+ (where >= PCI_BASE_ADDRESS_0 && where <= PCI_BASE_ADDRESS_5)) {
+ return pci_device_update_fixed(bus, devfn, where, size, value,
+ offset);
+ }
+
+ /*
+ * On Moorestown update both real & mmconfig space
+ * Note: early Lincroft silicon can't handle type 1 accesses to
+ * non-existent devices, so just eat the write in that case.
+ */
+ if (type1_access_ok(bus->number, devfn, where))
+ return pci_direct_conf1.write(pci_domain_nr(bus), bus->number,
+ devfn, where, size, value);
+ return raw_pci_ext_ops->write(pci_domain_nr(bus), bus->number, devfn,
+ where, size, value);
+}
+
+static int mrst_pci_irq_enable(struct pci_dev *dev)
+{
+ u8 pin;
+ struct io_apic_irq_attr irq_attr;
+
+ pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+
+ /* MRST only have IOAPIC, the PCI irq lines are 1:1 mapped to
+ * IOAPIC RTE entries, so we just enable RTE for the device.
+ */
+ irq_attr.ioapic = mp_find_ioapic(dev->irq);
+ irq_attr.ioapic_pin = dev->irq;
+ irq_attr.trigger = 1; /* level */
+ irq_attr.polarity = 1; /* active low */
+ io_apic_set_pci_routing(&dev->dev, dev->irq, &irq_attr);
+
+ return 0;
+}
+
+struct pci_ops pci_mrst_ops = {
+ .read = pci_read,
+ .write = pci_write,
+};
+
+/**
+ * pci_mrst_init - installs pci_mrst_ops
+ *
+ * Moorestown has an interesting PCI implementation (see above).
+ * Called when the early platform detection installs it.
+ */
+int __init pci_mrst_init(void)
+{
+ printk(KERN_INFO "Moorestown platform detected, using MRST PCI ops\n");
+ pci_mmcfg_late_init();
+ pcibios_enable_irq = mrst_pci_irq_enable;
+ pci_root_ops = pci_mrst_ops;
+ /* Continue with standard init */
+ return 1;
+}
+
+/*
+ * Langwell devices reside at fixed offsets, don't try to move them.
+ */
+static void __devinit pci_fixed_bar_fixup(struct pci_dev *dev)
+{
+ unsigned long offset;
+ u32 size;
+ int i;
+
+ /* Fixup the BAR sizes for fixed BAR devices and make them unmoveable */
+ offset = fixed_bar_cap(dev->bus, dev->devfn);
+ if (!offset || PCI_DEVFN(2, 0) == dev->devfn ||
+ PCI_DEVFN(2, 2) == dev->devfn)
+ return;
+
+ for (i = 0; i < PCI_ROM_RESOURCE; i++) {
+ pci_read_config_dword(dev, offset + 8 + (i * 4), &size);
+ dev->resource[i].end = dev->resource[i].start + size - 1;
+ dev->resource[i].flags |= IORESOURCE_PCI_FIXED;
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixed_bar_fixup);
diff --git a/arch/x86/pci/numaq_32.c b/arch/x86/pci/numaq_32.c
index 8884a1c1ada..8223738ad80 100644
--- a/arch/x86/pci/numaq_32.c
+++ b/arch/x86/pci/numaq_32.c
@@ -148,14 +148,8 @@ int __init pci_numaq_init(void)
{
int quad;
- if (!found_numaq)
- return 0;
-
raw_pci_ops = &pci_direct_conf1_mq;
- if (pcibios_scanned++)
- return 0;
-
pci_root_bus = pcibios_scan_root(0);
if (pci_root_bus)
pci_bus_add_devices(pci_root_bus);
diff --git a/arch/x86/pci/olpc.c b/arch/x86/pci/olpc.c
index b889d824f7c..b34815408f5 100644
--- a/arch/x86/pci/olpc.c
+++ b/arch/x86/pci/olpc.c
@@ -304,9 +304,6 @@ static struct pci_raw_ops pci_olpc_conf = {
int __init pci_olpc_init(void)
{
- if (!machine_is_olpc() || olpc_has_vsa())
- return -ENODEV;
-
printk(KERN_INFO "PCI: Using configuration type OLPC\n");
raw_pci_ops = &pci_olpc_conf;
is_lx = is_geode_lx();
diff --git a/arch/x86/pci/visws.c b/arch/x86/pci/visws.c
index bcead7a4687..03008f72eb0 100644
--- a/arch/x86/pci/visws.c
+++ b/arch/x86/pci/visws.c
@@ -69,9 +69,6 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
int __init pci_visws_init(void)
{
- if (!is_visws_box())
- return -1;
-
pcibios_enable_irq = &pci_visws_enable_irq;
pcibios_disable_irq = &pci_visws_disable_irq;
@@ -90,5 +87,6 @@ int __init pci_visws_init(void)
pci_scan_bus_with_sysdata(pci_bus1);
pci_fixup_irqs(pci_common_swizzle, visws_map_irq);
pcibios_resource_survey();
- return 0;
+ /* Request bus scan */
+ return 1;
}
diff --git a/block/blk-integrity.c b/block/blk-integrity.c
index 15c630813b1..96e83c2bdb9 100644
--- a/block/blk-integrity.c
+++ b/block/blk-integrity.c
@@ -278,7 +278,7 @@ static struct attribute *integrity_attrs[] = {
NULL,
};
-static struct sysfs_ops integrity_ops = {
+static const struct sysfs_ops integrity_ops = {
.show = &integrity_attr_show,
.store = &integrity_attr_store,
};
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index e85442415db..2ae2cb3f362 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -450,7 +450,7 @@ static void blk_release_queue(struct kobject *kobj)
kmem_cache_free(blk_requestq_cachep, q);
}
-static struct sysfs_ops queue_sysfs_ops = {
+static const struct sysfs_ops queue_sysfs_ops = {
.show = queue_attr_show,
.store = queue_attr_store,
};
diff --git a/block/elevator.c b/block/elevator.c
index ee3a883840f..df75676f667 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -892,7 +892,7 @@ elv_attr_store(struct kobject *kobj, struct attribute *attr,
return error;
}
-static struct sysfs_ops elv_sysfs_ops = {
+static const struct sysfs_ops elv_sysfs_ops = {
.show = elv_attr_show,
.store = elv_attr_store,
};
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 368ae6d3a09..a2b902f4d43 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -96,8 +96,6 @@ source "drivers/edac/Kconfig"
source "drivers/rtc/Kconfig"
-source "drivers/clocksource/Kconfig"
-
source "drivers/dma/Kconfig"
source "drivers/dca/Kconfig"
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 9863c98c81b..e9b7b402dbf 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -123,6 +123,8 @@ static const struct file_operations acpi_processor_info_fops = {
#endif
DEFINE_PER_CPU(struct acpi_processor *, processors);
+EXPORT_PER_CPU_SYMBOL(processors);
+
struct acpi_processor_errata errata __read_mostly;
/* --------------------------------------------------------------------------
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c
index a206a12da78..743f2445e2a 100644
--- a/drivers/acpi/system.c
+++ b/drivers/acpi/system.c
@@ -101,6 +101,7 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr,
struct acpi_table_header *header = NULL;
struct acpi_table_attr *attr = NULL;
+ sysfs_attr_init(&table_attr->attr.attr);
if (table_header->signature[0] != '\0')
memcpy(table_attr->name, table_header->signature,
ACPI_NAME_SIZE);
@@ -475,6 +476,7 @@ void acpi_irq_stats_init(void)
goto fail;
strncpy(name, buffer, strlen(buffer) + 1);
+ sysfs_attr_init(&counter_attrs[i].attr);
counter_attrs[i].attr.name = name;
counter_attrs[i].attr.mode = 0644;
counter_attrs[i].show = counter_show;
diff --git a/drivers/auxdisplay/cfag12864bfb.c b/drivers/auxdisplay/cfag12864bfb.c
index fe3a865be4e..b0ca5a47f47 100644
--- a/drivers/auxdisplay/cfag12864bfb.c
+++ b/drivers/auxdisplay/cfag12864bfb.c
@@ -81,7 +81,7 @@ static struct fb_ops cfag12864bfb_ops = {
.fb_mmap = cfag12864bfb_mmap,
};
-static int __init cfag12864bfb_probe(struct platform_device *device)
+static int __devinit cfag12864bfb_probe(struct platform_device *device)
{
int ret = -EINVAL;
struct fb_info *info = framebuffer_alloc(0, &device->dev);
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index ee377270beb..fd52c48ee76 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -3,35 +3,50 @@ menu "Generic Driver Options"
config UEVENT_HELPER_PATH
string "path to uevent helper"
depends on HOTPLUG
- default "/sbin/hotplug"
+ default ""
help
Path to uevent helper program forked by the kernel for
every uevent.
+ Before the switch to the netlink-based uevent source, this was
+ used to hook hotplug scripts into kernel device events. It
+ usually pointed to a shell script at /sbin/hotplug.
+ This should not be used today, because usual systems create
+ many events at bootup or device discovery in a very short time
+ frame. One forked process per event can create so many processes
+ that it creates a high system load, or on smaller systems
+ it is known to create out-of-memory situations during bootup.
config DEVTMPFS
- bool "Create a kernel maintained /dev tmpfs (EXPERIMENTAL)"
+ bool "Maintain a devtmpfs filesystem to mount at /dev"
depends on HOTPLUG && SHMEM && TMPFS
help
- This creates a tmpfs filesystem, and mounts it at bootup
- and mounts it at /dev. The kernel driver core creates device
- nodes for all registered devices in that filesystem. All device
- nodes are owned by root and have the default mode of 0600.
- Userspace can add and delete the nodes as needed. This is
- intended to simplify bootup, and make it possible to delay
- the initial coldplug at bootup done by udev in userspace.
- It should also provide a simpler way for rescue systems
- to bring up a kernel with dynamic major/minor numbers.
- Meaningful symlinks, permissions and device ownership must
- still be handled by userspace.
- If unsure, say N here.
+ This creates a tmpfs filesystem instance early at bootup.
+ In this filesystem, the kernel driver core maintains device
+ nodes with their default names and permissions for all
+ registered devices with an assigned major/minor number.
+ Userspace can modify the filesystem content as needed, add
+ symlinks, and apply needed permissions.
+ It provides a fully functional /dev directory, where usually
+ udev runs on top, managing permissions and adding meaningful
+ symlinks.
+ In very limited environments, it may provide a sufficient
+ functional /dev without any further help. It also allows simple
+ rescue systems, and reliably handles dynamic major/minor numbers.
config DEVTMPFS_MOUNT
- bool "Automount devtmpfs at /dev"
+ bool "Automount devtmpfs at /dev, after the kernel mounted the rootfs"
depends on DEVTMPFS
help
- This will mount devtmpfs at /dev if the kernel mounts the root
- filesystem. It will not affect initramfs based mounting.
- If unsure, say N here.
+ This will instruct the kernel to automatically mount the
+ devtmpfs filesystem at /dev, directly after the kernel has
+ mounted the root filesystem. The behavior can be overridden
+ with the commandline parameter: devtmpfs.mount=0|1.
+ This option does not affect initramfs based booting, here
+ the devtmpfs filesystem always needs to be mounted manually
+ after the roots is mounted.
+ With this option enabled, it allows to bring up a system in
+ rescue mode with init=/bin/sh, even when the /dev directory
+ on the rootfs is completely empty.
config STANDALONE
bool "Select only drivers that don't need compile-time external firmware" if EXPERIMENTAL
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index c0c5a43d9fb..71f6af5c8b0 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -70,7 +70,7 @@ static ssize_t drv_attr_store(struct kobject *kobj, struct attribute *attr,
return ret;
}
-static struct sysfs_ops driver_sysfs_ops = {
+static const struct sysfs_ops driver_sysfs_ops = {
.show = drv_attr_show,
.store = drv_attr_store,
};
@@ -115,7 +115,7 @@ static ssize_t bus_attr_store(struct kobject *kobj, struct attribute *attr,
return ret;
}
-static struct sysfs_ops bus_sysfs_ops = {
+static const struct sysfs_ops bus_sysfs_ops = {
.show = bus_attr_show,
.store = bus_attr_store,
};
@@ -154,7 +154,7 @@ static int bus_uevent_filter(struct kset *kset, struct kobject *kobj)
return 0;
}
-static struct kset_uevent_ops bus_uevent_ops = {
+static const struct kset_uevent_ops bus_uevent_ops = {
.filter = bus_uevent_filter,
};
@@ -173,10 +173,10 @@ static ssize_t driver_unbind(struct device_driver *drv,
dev = bus_find_device_by_name(bus, NULL, buf);
if (dev && dev->driver == drv) {
if (dev->parent) /* Needed for USB */
- down(&dev->parent->sem);
+ device_lock(dev->parent);
device_release_driver(dev);
if (dev->parent)
- up(&dev->parent->sem);
+ device_unlock(dev->parent);
err = count;
}
put_device(dev);
@@ -200,12 +200,12 @@ static ssize_t driver_bind(struct device_driver *drv,
dev = bus_find_device_by_name(bus, NULL, buf);
if (dev && dev->driver == NULL && driver_match_device(drv, dev)) {
if (dev->parent) /* Needed for USB */
- down(&dev->parent->sem);
- down(&dev->sem);
+ device_lock(dev->parent);
+ device_lock(dev);
err = driver_probe_device(drv, dev);
- up(&dev->sem);
+ device_unlock(dev);
if (dev->parent)
- up(&dev->parent->sem);
+ device_unlock(dev->parent);
if (err > 0) {
/* success */
@@ -744,10 +744,10 @@ static int __must_check bus_rescan_devices_helper(struct device *dev,
if (!dev->driver) {
if (dev->parent) /* Needed for USB */
- down(&dev->parent->sem);
+ device_lock(dev->parent);
ret = device_attach(dev);
if (dev->parent)
- up(&dev->parent->sem);
+ device_unlock(dev->parent);
}
return ret < 0 ? ret : 0;
}
@@ -779,10 +779,10 @@ int device_reprobe(struct device *dev)
{
if (dev->driver) {
if (dev->parent) /* Needed for USB */
- down(&dev->parent->sem);
+ device_lock(dev->parent);
device_release_driver(dev);
if (dev->parent)
- up(&dev->parent->sem);
+ device_unlock(dev->parent);
}
return bus_rescan_devices_helper(dev, NULL);
}
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 6e2c3b064f5..0147f476b8a 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -31,7 +31,7 @@ static ssize_t class_attr_show(struct kobject *kobj, struct attribute *attr,
ssize_t ret = -EIO;
if (class_attr->show)
- ret = class_attr->show(cp->class, buf);
+ ret = class_attr->show(cp->class, class_attr, buf);
return ret;
}
@@ -43,7 +43,7 @@ static ssize_t class_attr_store(struct kobject *kobj, struct attribute *attr,
ssize_t ret = -EIO;
if (class_attr->store)
- ret = class_attr->store(cp->class, buf, count);
+ ret = class_attr->store(cp->class, class_attr, buf, count);
return ret;
}
@@ -63,7 +63,7 @@ static void class_release(struct kobject *kobj)
kfree(cp);
}
-static struct sysfs_ops class_sysfs_ops = {
+static const struct sysfs_ops class_sysfs_ops = {
.show = class_attr_show,
.store = class_attr_store,
};
@@ -490,6 +490,16 @@ void class_interface_unregister(struct class_interface *class_intf)
class_put(parent);
}
+ssize_t show_class_attr_string(struct class *class, struct class_attribute *attr,
+ char *buf)
+{
+ struct class_attribute_string *cs;
+ cs = container_of(attr, struct class_attribute_string, attr);
+ return snprintf(buf, PAGE_SIZE, "%s\n", cs->str);
+}
+
+EXPORT_SYMBOL_GPL(show_class_attr_string);
+
struct class_compat {
struct kobject *kobj;
};
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 28202577042..ef55df34ddd 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -100,7 +100,7 @@ static ssize_t dev_attr_store(struct kobject *kobj, struct attribute *attr,
return ret;
}
-static struct sysfs_ops dev_sysfs_ops = {
+static const struct sysfs_ops dev_sysfs_ops = {
.show = dev_attr_show,
.store = dev_attr_store,
};
@@ -252,7 +252,7 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
return retval;
}
-static struct kset_uevent_ops device_uevent_ops = {
+static const struct kset_uevent_ops device_uevent_ops = {
.filter = dev_uevent_filter,
.name = dev_uevent_name,
.uevent = dev_uevent,
@@ -306,15 +306,10 @@ static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
{
enum kobject_action action;
- if (kobject_action_type(buf, count, &action) == 0) {
+ if (kobject_action_type(buf, count, &action) == 0)
kobject_uevent(&dev->kobj, action);
- goto out;
- }
-
- dev_err(dev, "uevent: unsupported action-string; this will "
- "be ignored in a future kernel version\n");
- kobject_uevent(&dev->kobj, KOBJ_ADD);
-out:
+ else
+ dev_err(dev, "uevent: unknown action-string\n");
return count;
}
@@ -607,6 +602,7 @@ static struct kobject *get_device_parent(struct device *dev,
int retval;
if (dev->class) {
+ static DEFINE_MUTEX(gdp_mutex);
struct kobject *kobj = NULL;
struct kobject *parent_kobj;
struct kobject *k;
@@ -623,6 +619,8 @@ static struct kobject *get_device_parent(struct device *dev,
else
parent_kobj = &parent->kobj;
+ mutex_lock(&gdp_mutex);
+
/* find our class-directory at the parent and reference it */
spin_lock(&dev->class->p->class_dirs.list_lock);
list_for_each_entry(k, &dev->class->p->class_dirs.list, entry)
@@ -631,20 +629,26 @@ static struct kobject *get_device_parent(struct device *dev,
break;
}
spin_unlock(&dev->class->p->class_dirs.list_lock);
- if (kobj)
+ if (kobj) {
+ mutex_unlock(&gdp_mutex);
return kobj;
+ }
/* or create a new class-directory at the parent device */
k = kobject_create();
- if (!k)
+ if (!k) {
+ mutex_unlock(&gdp_mutex);
return NULL;
+ }
k->kset = &dev->class->p->class_dirs;
retval = kobject_add(k, parent_kobj, "%s", dev->class->name);
if (retval < 0) {
+ mutex_unlock(&gdp_mutex);
kobject_put(k);
return NULL;
}
/* do not emit an uevent for this simple "glue" directory */
+ mutex_unlock(&gdp_mutex);
return k;
}
@@ -1574,22 +1578,16 @@ int device_rename(struct device *dev, char *new_name)
if (old_class_name) {
new_class_name = make_class_name(dev->class->name, &dev->kobj);
if (new_class_name) {
- error = sysfs_create_link_nowarn(&dev->parent->kobj,
- &dev->kobj,
- new_class_name);
- if (error)
- goto out;
- sysfs_remove_link(&dev->parent->kobj, old_class_name);
+ error = sysfs_rename_link(&dev->parent->kobj,
+ &dev->kobj,
+ old_class_name,
+ new_class_name);
}
}
#else
if (dev->class) {
- error = sysfs_create_link_nowarn(&dev->class->p->class_subsys.kobj,
- &dev->kobj, dev_name(dev));
- if (error)
- goto out;
- sysfs_remove_link(&dev->class->p->class_subsys.kobj,
- old_device_name);
+ error = sysfs_rename_link(&dev->class->p->class_subsys.kobj,
+ &dev->kobj, old_device_name, new_name);
}
#endif
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 958bd1540c3..7036e8e96ab 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -13,8 +13,11 @@
#include "base.h"
+static struct sysdev_class_attribute *cpu_sysdev_class_attrs[];
+
struct sysdev_class cpu_sysdev_class = {
.name = "cpu",
+ .attrs = cpu_sysdev_class_attrs,
};
EXPORT_SYMBOL(cpu_sysdev_class);
@@ -76,34 +79,24 @@ void unregister_cpu(struct cpu *cpu)
}
#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
-static ssize_t cpu_probe_store(struct class *class, const char *buf,
+static ssize_t cpu_probe_store(struct sys_device *dev,
+ struct sysdev_attribute *attr,
+ const char *buf,
size_t count)
{
return arch_cpu_probe(buf, count);
}
-static ssize_t cpu_release_store(struct class *class, const char *buf,
+static ssize_t cpu_release_store(struct sys_device *dev,
+ struct sysdev_attribute *attr,
+ const char *buf,
size_t count)
{
return arch_cpu_release(buf, count);
}
-static CLASS_ATTR(probe, S_IWUSR, NULL, cpu_probe_store);
-static CLASS_ATTR(release, S_IWUSR, NULL, cpu_release_store);
-
-int __init cpu_probe_release_init(void)
-{
- int rc;
-
- rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
- &class_attr_probe.attr);
- if (!rc)
- rc = sysfs_create_file(&cpu_sysdev_class.kset.kobj,
- &class_attr_release.attr);
-
- return rc;
-}
-device_initcall(cpu_probe_release_init);
+static SYSDEV_ATTR(probe, S_IWUSR, NULL, cpu_probe_store);
+static SYSDEV_ATTR(release, S_IWUSR, NULL, cpu_release_store);
#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
#else /* ... !CONFIG_HOTPLUG_CPU */
@@ -141,31 +134,39 @@ static SYSDEV_ATTR(crash_notes, 0400, show_crash_notes, NULL);
/*
* Print cpu online, possible, present, and system maps
*/
-static ssize_t print_cpus_map(char *buf, const struct cpumask *map)
+
+struct cpu_attr {
+ struct sysdev_class_attribute attr;
+ const struct cpumask *const * const map;
+};
+
+static ssize_t show_cpus_attr(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
- int n = cpulist_scnprintf(buf, PAGE_SIZE-2, map);
+ struct cpu_attr *ca = container_of(attr, struct cpu_attr, attr);
+ int n = cpulist_scnprintf(buf, PAGE_SIZE-2, *(ca->map));
buf[n++] = '\n';
buf[n] = '\0';
return n;
}
-#define print_cpus_func(type) \
-static ssize_t print_cpus_##type(struct sysdev_class *class, char *buf) \
-{ \
- return print_cpus_map(buf, cpu_##type##_mask); \
-} \
-static struct sysdev_class_attribute attr_##type##_map = \
- _SYSDEV_CLASS_ATTR(type, 0444, print_cpus_##type, NULL)
+#define _CPU_ATTR(name, map) \
+ { _SYSDEV_CLASS_ATTR(name, 0444, show_cpus_attr, NULL), map }
-print_cpus_func(online);
-print_cpus_func(possible);
-print_cpus_func(present);
+/* Keep in sync with cpu_sysdev_class_attrs */
+static struct cpu_attr cpu_attrs[] = {
+ _CPU_ATTR(online, &cpu_online_mask),
+ _CPU_ATTR(possible, &cpu_possible_mask),
+ _CPU_ATTR(present, &cpu_present_mask),
+};
/*
* Print values for NR_CPUS and offlined cpus
*/
-static ssize_t print_cpus_kernel_max(struct sysdev_class *class, char *buf)
+static ssize_t print_cpus_kernel_max(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr, char *buf)
{
int n = snprintf(buf, PAGE_SIZE-2, "%d\n", NR_CPUS - 1);
return n;
@@ -175,7 +176,8 @@ static SYSDEV_CLASS_ATTR(kernel_max, 0444, print_cpus_kernel_max, NULL);
/* arch-optional setting to enable display of offline cpus >= nr_cpu_ids */
unsigned int total_cpus;
-static ssize_t print_cpus_offline(struct sysdev_class *class, char *buf)
+static ssize_t print_cpus_offline(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr, char *buf)
{
int n = 0, len = PAGE_SIZE-2;
cpumask_var_t offline;
@@ -204,29 +206,6 @@ static ssize_t print_cpus_offline(struct sysdev_class *class, char *buf)
}
static SYSDEV_CLASS_ATTR(offline, 0444, print_cpus_offline, NULL);
-static struct sysdev_class_attribute *cpu_state_attr[] = {
- &attr_online_map,
- &attr_possible_map,
- &attr_present_map,
- &attr_kernel_max,
- &attr_offline,
-};
-
-static int cpu_states_init(void)
-{
- int i;
- int err = 0;
-
- for (i = 0; i < ARRAY_SIZE(cpu_state_attr); i++) {
- int ret;
- ret = sysdev_class_create_file(&cpu_sysdev_class,
- cpu_state_attr[i]);
- if (!err)
- err = ret;
- }
- return err;
-}
-
/*
* register_cpu - Setup a sysfs device for a CPU.
* @cpu - cpu->hotpluggable field set to 1 will generate a control file in
@@ -272,9 +251,6 @@ int __init cpu_dev_init(void)
int err;
err = sysdev_class_register(&cpu_sysdev_class);
- if (!err)
- err = cpu_states_init();
-
#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
if (!err)
err = sched_create_sysfs_power_savings_entries(&cpu_sysdev_class);
@@ -282,3 +258,16 @@ int __init cpu_dev_init(void)
return err;
}
+
+static struct sysdev_class_attribute *cpu_sysdev_class_attrs[] = {
+#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
+ &attr_probe,
+ &attr_release,
+#endif
+ &cpu_attrs[0].attr,
+ &cpu_attrs[1].attr,
+ &cpu_attrs[2].attr,
+ &attr_kernel_max,
+ &attr_offline,
+ NULL
+};
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index ee95c76bfd3..c89291f8a16 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -85,7 +85,7 @@ static void driver_sysfs_remove(struct device *dev)
* for before calling this. (It is ok to call with no other effort
* from a driver's probe() method.)
*
- * This function must be called with @dev->sem held.
+ * This function must be called with the device lock held.
*/
int device_bind_driver(struct device *dev)
{
@@ -190,8 +190,8 @@ EXPORT_SYMBOL_GPL(wait_for_device_probe);
* This function returns -ENODEV if the device is not registered,
* 1 if the device is bound successfully and 0 otherwise.
*
- * This function must be called with @dev->sem held. When called for a
- * USB interface, @dev->parent->sem must be held as well.
+ * This function must be called with @dev lock held. When called for a
+ * USB interface, @dev->parent lock must be held as well.
*/
int driver_probe_device(struct device_driver *drv, struct device *dev)
{
@@ -233,13 +233,13 @@ static int __device_attach(struct device_driver *drv, void *data)
* 0 if no matching driver was found;
* -ENODEV if the device is not registered.
*
- * When called for a USB interface, @dev->parent->sem must be held.
+ * When called for a USB interface, @dev->parent lock must be held.
*/
int device_attach(struct device *dev)
{
int ret = 0;
- down(&dev->sem);
+ device_lock(dev);
if (dev->driver) {
ret = device_bind_driver(dev);
if (ret == 0)
@@ -253,7 +253,7 @@ int device_attach(struct device *dev)
ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
pm_runtime_put_sync(dev);
}
- up(&dev->sem);
+ device_unlock(dev);
return ret;
}
EXPORT_SYMBOL_GPL(device_attach);
@@ -276,13 +276,13 @@ static int __driver_attach(struct device *dev, void *data)
return 0;
if (dev->parent) /* Needed for USB */
- down(&dev->parent->sem);
- down(&dev->sem);
+ device_lock(dev->parent);
+ device_lock(dev);
if (!dev->driver)
driver_probe_device(drv, dev);
- up(&dev->sem);
+ device_unlock(dev);
if (dev->parent)
- up(&dev->parent->sem);
+ device_unlock(dev->parent);
return 0;
}
@@ -303,8 +303,8 @@ int driver_attach(struct device_driver *drv)
EXPORT_SYMBOL_GPL(driver_attach);
/*
- * __device_release_driver() must be called with @dev->sem held.
- * When called for a USB interface, @dev->parent->sem must be held as well.
+ * __device_release_driver() must be called with @dev lock held.
+ * When called for a USB interface, @dev->parent lock must be held as well.
*/
static void __device_release_driver(struct device *dev)
{
@@ -343,7 +343,7 @@ static void __device_release_driver(struct device *dev)
* @dev: device.
*
* Manually detach device from driver.
- * When called for a USB interface, @dev->parent->sem must be held.
+ * When called for a USB interface, @dev->parent lock must be held.
*/
void device_release_driver(struct device *dev)
{
@@ -352,9 +352,9 @@ void device_release_driver(struct device *dev)
* within their ->remove callback for the same device, they
* will deadlock right here.
*/
- down(&dev->sem);
+ device_lock(dev);
__device_release_driver(dev);
- up(&dev->sem);
+ device_unlock(dev);
}
EXPORT_SYMBOL_GPL(device_release_driver);
@@ -381,13 +381,13 @@ void driver_detach(struct device_driver *drv)
spin_unlock(&drv->p->klist_devices.k_lock);
if (dev->parent) /* Needed for USB */
- down(&dev->parent->sem);
- down(&dev->sem);
+ device_lock(dev->parent);
+ device_lock(dev);
if (dev->driver == drv)
__device_release_driver(dev);
- up(&dev->sem);
+ device_unlock(dev);
if (dev->parent)
- up(&dev->parent->sem);
+ device_unlock(dev->parent);
put_device(dev);
}
}
diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c
index 42ae452b36b..dac478c6e46 100644
--- a/drivers/base/devtmpfs.c
+++ b/drivers/base/devtmpfs.c
@@ -301,6 +301,19 @@ int devtmpfs_delete_node(struct device *dev)
if (dentry->d_inode) {
err = vfs_getattr(nd.path.mnt, dentry, &stat);
if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
+ struct iattr newattrs;
+ /*
+ * before unlinking this node, reset permissions
+ * of possible references like hardlinks
+ */
+ newattrs.ia_uid = 0;
+ newattrs.ia_gid = 0;
+ newattrs.ia_mode = stat.mode & ~0777;
+ newattrs.ia_valid =
+ ATTR_UID|ATTR_GID|ATTR_MODE;
+ mutex_lock(&dentry->d_inode->i_mutex);
+ notify_change(dentry, &newattrs);
+ mutex_unlock(&dentry->d_inode->i_mutex);
err = vfs_unlink(nd.path.dentry->d_inode,
dentry);
if (!err || err == -ENOENT)
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index a95024166b6..d0dc26ad538 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -19,7 +19,6 @@
#include <linux/kthread.h>
#include <linux/highmem.h>
#include <linux/firmware.h>
-#include "base.h"
#define to_dev(obj) container_of(obj, struct device, kobj)
@@ -69,7 +68,9 @@ fw_load_abort(struct firmware_priv *fw_priv)
}
static ssize_t
-firmware_timeout_show(struct class *class, char *buf)
+firmware_timeout_show(struct class *class,
+ struct class_attribute *attr,
+ char *buf)
{
return sprintf(buf, "%d\n", loading_timeout);
}
@@ -87,7 +88,9 @@ firmware_timeout_show(struct class *class, char *buf)
* Note: zero means 'wait forever'.
**/
static ssize_t
-firmware_timeout_store(struct class *class, const char *buf, size_t count)
+firmware_timeout_store(struct class *class,
+ struct class_attribute *attr,
+ const char *buf, size_t count)
{
loading_timeout = simple_strtol(buf, NULL, 10);
if (loading_timeout < 0)
@@ -610,7 +613,7 @@ request_firmware_work_func(void *arg)
}
/**
- * request_firmware_nowait: asynchronous version of request_firmware
+ * request_firmware_nowait - asynchronous version of request_firmware
* @module: module requesting the firmware
* @uevent: sends uevent to copy the firmware image if this flag
* is non-zero else the firmware copy must be done manually.
diff --git a/drivers/base/memory.c b/drivers/base/memory.c
index bd025059711..2f869151119 100644
--- a/drivers/base/memory.c
+++ b/drivers/base/memory.c
@@ -44,7 +44,7 @@ static int memory_uevent(struct kset *kset, struct kobject *obj, struct kobj_uev
return retval;
}
-static struct kset_uevent_ops memory_uevent_ops = {
+static const struct kset_uevent_ops memory_uevent_ops = {
.name = memory_uevent_name,
.uevent = memory_uevent,
};
@@ -309,17 +309,18 @@ static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL);
* Block size attribute stuff
*/
static ssize_t
-print_block_size(struct class *class, char *buf)
+print_block_size(struct sysdev_class *class, struct sysdev_class_attribute *attr,
+ char *buf)
{
return sprintf(buf, "%#lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE);
}
-static CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL);
+static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL);
static int block_size_init(void)
{
return sysfs_create_file(&memory_sysdev_class.kset.kobj,
- &class_attr_block_size_bytes.attr);
+ &attr_block_size_bytes.attr);
}
/*
@@ -330,7 +331,8 @@ static int block_size_init(void)
*/
#ifdef CONFIG_ARCH_MEMORY_PROBE
static ssize_t
-memory_probe_store(struct class *class, const char *buf, size_t count)
+memory_probe_store(struct class *class, struct class_attribute *attr,
+ const char *buf, size_t count)
{
u64 phys_addr;
int nid;
@@ -367,7 +369,9 @@ static inline int memory_probe_init(void)
/* Soft offline a page */
static ssize_t
-store_soft_offline_page(struct class *class, const char *buf, size_t count)
+store_soft_offline_page(struct class *class,
+ struct class_attribute *attr,
+ const char *buf, size_t count)
{
int ret;
u64 pfn;
@@ -384,7 +388,9 @@ store_soft_offline_page(struct class *class, const char *buf, size_t count)
/* Forcibly offline a page, including killing processes. */
static ssize_t
-store_hard_offline_page(struct class *class, const char *buf, size_t count)
+store_hard_offline_page(struct class *class,
+ struct class_attribute *attr,
+ const char *buf, size_t count)
{
int ret;
u64 pfn;
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 70122791683..ad43185ec15 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -16,8 +16,11 @@
#include <linux/device.h>
#include <linux/swap.h>
+static struct sysdev_class_attribute *node_state_attrs[];
+
static struct sysdev_class node_class = {
.name = "node",
+ .attrs = node_state_attrs,
};
@@ -544,76 +547,52 @@ static ssize_t print_nodes_state(enum node_states state, char *buf)
return n;
}
-static ssize_t print_nodes_possible(struct sysdev_class *class, char *buf)
-{
- return print_nodes_state(N_POSSIBLE, buf);
-}
-
-static ssize_t print_nodes_online(struct sysdev_class *class, char *buf)
-{
- return print_nodes_state(N_ONLINE, buf);
-}
-
-static ssize_t print_nodes_has_normal_memory(struct sysdev_class *class,
- char *buf)
-{
- return print_nodes_state(N_NORMAL_MEMORY, buf);
-}
+struct node_attr {
+ struct sysdev_class_attribute attr;
+ enum node_states state;
+};
-static ssize_t print_nodes_has_cpu(struct sysdev_class *class, char *buf)
+static ssize_t show_node_state(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr, char *buf)
{
- return print_nodes_state(N_CPU, buf);
+ struct node_attr *na = container_of(attr, struct node_attr, attr);
+ return print_nodes_state(na->state, buf);
}
-static SYSDEV_CLASS_ATTR(possible, 0444, print_nodes_possible, NULL);
-static SYSDEV_CLASS_ATTR(online, 0444, print_nodes_online, NULL);
-static SYSDEV_CLASS_ATTR(has_normal_memory, 0444, print_nodes_has_normal_memory,
- NULL);
-static SYSDEV_CLASS_ATTR(has_cpu, 0444, print_nodes_has_cpu, NULL);
+#define _NODE_ATTR(name, state) \
+ { _SYSDEV_CLASS_ATTR(name, 0444, show_node_state, NULL), state }
+static struct node_attr node_state_attr[] = {
+ _NODE_ATTR(possible, N_POSSIBLE),
+ _NODE_ATTR(online, N_ONLINE),
+ _NODE_ATTR(has_normal_memory, N_NORMAL_MEMORY),
+ _NODE_ATTR(has_cpu, N_CPU),
#ifdef CONFIG_HIGHMEM
-static ssize_t print_nodes_has_high_memory(struct sysdev_class *class,
- char *buf)
-{
- return print_nodes_state(N_HIGH_MEMORY, buf);
-}
-
-static SYSDEV_CLASS_ATTR(has_high_memory, 0444, print_nodes_has_high_memory,
- NULL);
+ _NODE_ATTR(has_high_memory, N_HIGH_MEMORY),
#endif
+};
-struct sysdev_class_attribute *node_state_attr[] = {
- &attr_possible,
- &attr_online,
- &attr_has_normal_memory,
+static struct sysdev_class_attribute *node_state_attrs[] = {
+ &node_state_attr[0].attr,
+ &node_state_attr[1].attr,
+ &node_state_attr[2].attr,
+ &node_state_attr[3].attr,
#ifdef CONFIG_HIGHMEM
- &attr_has_high_memory,
+ &node_state_attr[4].attr,
#endif
- &attr_has_cpu,
+ NULL
};
-static int node_states_init(void)
-{
- int i;
- int err = 0;
-
- for (i = 0; i < NR_NODE_STATES; i++) {
- int ret;
- ret = sysdev_class_create_file(&node_class, node_state_attr[i]);
- if (!err)
- err = ret;
- }
- return err;
-}
-
#define NODE_CALLBACK_PRI 2 /* lower than SLAB */
static int __init register_node_type(void)
{
int ret;
+ BUILD_BUG_ON(ARRAY_SIZE(node_state_attr) != NR_NODE_STATES);
+ BUILD_BUG_ON(ARRAY_SIZE(node_state_attrs)-1 != NR_NODE_STATES);
+
ret = sysdev_class_register(&node_class);
if (!ret) {
- ret = node_states_init();
hotplug_memory_notifier(node_memory_callback,
NODE_CALLBACK_PRI);
}
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 58efaf2f125..1ba9d617d24 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -128,7 +128,7 @@ struct platform_object {
};
/**
- * platform_device_put
+ * platform_device_put - destroy a platform device
* @pdev: platform device to free
*
* Free all memory associated with a platform device. This function must
@@ -152,7 +152,7 @@ static void platform_device_release(struct device *dev)
}
/**
- * platform_device_alloc
+ * platform_device_alloc - create a platform device
* @name: base name of the device we're adding
* @id: instance id
*
@@ -177,7 +177,7 @@ struct platform_device *platform_device_alloc(const char *name, int id)
EXPORT_SYMBOL_GPL(platform_device_alloc);
/**
- * platform_device_add_resources
+ * platform_device_add_resources - add resources to a platform device
* @pdev: platform device allocated by platform_device_alloc to add resources to
* @res: set of resources that needs to be allocated for the device
* @num: number of resources
@@ -202,7 +202,7 @@ int platform_device_add_resources(struct platform_device *pdev,
EXPORT_SYMBOL_GPL(platform_device_add_resources);
/**
- * platform_device_add_data
+ * platform_device_add_data - add platform-specific data to a platform device
* @pdev: platform device allocated by platform_device_alloc to add resources to
* @data: platform specific data for this platform device
* @size: size of platform specific data
@@ -344,7 +344,7 @@ void platform_device_unregister(struct platform_device *pdev)
EXPORT_SYMBOL_GPL(platform_device_unregister);
/**
- * platform_device_register_simple
+ * platform_device_register_simple - add a platform-level device and its resources
* @name: base name of the device we're adding
* @id: instance id
* @res: set of resources that needs to be allocated for the device
@@ -396,7 +396,7 @@ error:
EXPORT_SYMBOL_GPL(platform_device_register_simple);
/**
- * platform_device_register_data
+ * platform_device_register_data - add a platform-level device with platform-specific data
* @parent: parent device for the device we're adding
* @name: base name of the device we're adding
* @id: instance id
@@ -473,7 +473,7 @@ static void platform_drv_shutdown(struct device *_dev)
}
/**
- * platform_driver_register
+ * platform_driver_register - register a driver for platform-level devices
* @drv: platform driver structure
*/
int platform_driver_register(struct platform_driver *drv)
@@ -491,7 +491,7 @@ int platform_driver_register(struct platform_driver *drv)
EXPORT_SYMBOL_GPL(platform_driver_register);
/**
- * platform_driver_unregister
+ * platform_driver_unregister - unregister a driver for platform-level devices
* @drv: platform driver structure
*/
void platform_driver_unregister(struct platform_driver *drv)
@@ -548,6 +548,64 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv,
}
EXPORT_SYMBOL_GPL(platform_driver_probe);
+/**
+ * platform_create_bundle - register driver and create corresponding device
+ * @driver: platform driver structure
+ * @probe: the driver probe routine, probably from an __init section
+ * @res: set of resources that needs to be allocated for the device
+ * @n_res: number of resources
+ * @data: platform specific data for this platform device
+ * @size: size of platform specific data
+ *
+ * Use this in legacy-style modules that probe hardware directly and
+ * register a single platform device and corresponding platform driver.
+ */
+struct platform_device * __init_or_module platform_create_bundle(
+ struct platform_driver *driver,
+ int (*probe)(struct platform_device *),
+ struct resource *res, unsigned int n_res,
+ const void *data, size_t size)
+{
+ struct platform_device *pdev;
+ int error;
+
+ pdev = platform_device_alloc(driver->driver.name, -1);
+ if (!pdev) {
+ error = -ENOMEM;
+ goto err_out;
+ }
+
+ if (res) {
+ error = platform_device_add_resources(pdev, res, n_res);
+ if (error)
+ goto err_pdev_put;
+ }
+
+ if (data) {
+ error = platform_device_add_data(pdev, data, size);
+ if (error)
+ goto err_pdev_put;
+ }
+
+ error = platform_device_add(pdev);
+ if (error)
+ goto err_pdev_put;
+
+ error = platform_driver_probe(driver, probe);
+ if (error)
+ goto err_pdev_del;
+
+ return pdev;
+
+err_pdev_del:
+ platform_device_del(pdev);
+err_pdev_put:
+ platform_device_put(pdev);
+err_out:
+ return ERR_PTR(error);
+}
+EXPORT_SYMBOL_GPL(platform_create_bundle);
+
/* modalias support enables more hands-off userspace setup:
* (a) environment variable lets new-style hotplug events work once system is
* fully running: "modprobe $MODALIAS"
@@ -578,7 +636,7 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
}
static const struct platform_device_id *platform_match_id(
- struct platform_device_id *id,
+ const struct platform_device_id *id,
struct platform_device *pdev)
{
while (id->name[0]) {
diff --git a/drivers/base/power/Makefile b/drivers/base/power/Makefile
index 3ce3519e8f3..89de75325ce 100644
--- a/drivers/base/power/Makefile
+++ b/drivers/base/power/Makefile
@@ -1,6 +1,7 @@
obj-$(CONFIG_PM) += sysfs.o
obj-$(CONFIG_PM_SLEEP) += main.o
obj-$(CONFIG_PM_RUNTIME) += runtime.o
+obj-$(CONFIG_PM_OPS) += generic_ops.o
obj-$(CONFIG_PM_TRACE_RTC) += trace.o
ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
diff --git a/drivers/base/power/generic_ops.c b/drivers/base/power/generic_ops.c
new file mode 100644
index 00000000000..4b29d498125
--- /dev/null
+++ b/drivers/base/power/generic_ops.c
@@ -0,0 +1,233 @@
+/*
+ * drivers/base/power/generic_ops.c - Generic PM callbacks for subsystems
+ *
+ * Copyright (c) 2010 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
+ *
+ * This file is released under the GPLv2.
+ */
+
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+
+#ifdef CONFIG_PM_RUNTIME
+/**
+ * pm_generic_runtime_idle - Generic runtime idle callback for subsystems.
+ * @dev: Device to handle.
+ *
+ * If PM operations are defined for the @dev's driver and they include
+ * ->runtime_idle(), execute it and return its error code, if nonzero.
+ * Otherwise, execute pm_runtime_suspend() for the device and return 0.
+ */
+int pm_generic_runtime_idle(struct device *dev)
+{
+ const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+ if (pm && pm->runtime_idle) {
+ int ret = pm->runtime_idle(dev);
+ if (ret)
+ return ret;
+ }
+
+ pm_runtime_suspend(dev);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pm_generic_runtime_idle);
+
+/**
+ * pm_generic_runtime_suspend - Generic runtime suspend callback for subsystems.
+ * @dev: Device to suspend.
+ *
+ * If PM operations are defined for the @dev's driver and they include
+ * ->runtime_suspend(), execute it and return its error code. Otherwise,
+ * return -EINVAL.
+ */
+int pm_generic_runtime_suspend(struct device *dev)
+{
+ const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+ int ret;
+
+ ret = pm && pm->runtime_suspend ? pm->runtime_suspend(dev) : -EINVAL;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pm_generic_runtime_suspend);
+
+/**
+ * pm_generic_runtime_resume - Generic runtime resume callback for subsystems.
+ * @dev: Device to resume.
+ *
+ * If PM operations are defined for the @dev's driver and they include
+ * ->runtime_resume(), execute it and return its error code. Otherwise,
+ * return -EINVAL.
+ */
+int pm_generic_runtime_resume(struct device *dev)
+{
+ const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+ int ret;
+
+ ret = pm && pm->runtime_resume ? pm->runtime_resume(dev) : -EINVAL;
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(pm_generic_runtime_resume);
+#endif /* CONFIG_PM_RUNTIME */
+
+#ifdef CONFIG_PM_SLEEP
+/**
+ * __pm_generic_call - Generic suspend/freeze/poweroff/thaw subsystem callback.
+ * @dev: Device to handle.
+ * @event: PM transition of the system under way.
+ *
+ * If the device has not been suspended at run time, execute the
+ * suspend/freeze/poweroff/thaw callback provided by its driver, if defined, and
+ * return its error code. Otherwise, return zero.
+ */
+static int __pm_generic_call(struct device *dev, int event)
+{
+ const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+ int (*callback)(struct device *);
+
+ if (!pm || pm_runtime_suspended(dev))
+ return 0;
+
+ switch (event) {
+ case PM_EVENT_SUSPEND:
+ callback = pm->suspend;
+ break;
+ case PM_EVENT_FREEZE:
+ callback = pm->freeze;
+ break;
+ case PM_EVENT_HIBERNATE:
+ callback = pm->poweroff;
+ break;
+ case PM_EVENT_THAW:
+ callback = pm->thaw;
+ break;
+ default:
+ callback = NULL;
+ break;
+ }
+
+ return callback ? callback(dev) : 0;
+}
+
+/**
+ * pm_generic_suspend - Generic suspend callback for subsystems.
+ * @dev: Device to suspend.
+ */
+int pm_generic_suspend(struct device *dev)
+{
+ return __pm_generic_call(dev, PM_EVENT_SUSPEND);
+}
+EXPORT_SYMBOL_GPL(pm_generic_suspend);
+
+/**
+ * pm_generic_freeze - Generic freeze callback for subsystems.
+ * @dev: Device to freeze.
+ */
+int pm_generic_freeze(struct device *dev)
+{
+ return __pm_generic_call(dev, PM_EVENT_FREEZE);
+}
+EXPORT_SYMBOL_GPL(pm_generic_freeze);
+
+/**
+ * pm_generic_poweroff - Generic poweroff callback for subsystems.
+ * @dev: Device to handle.
+ */
+int pm_generic_poweroff(struct device *dev)
+{
+ return __pm_generic_call(dev, PM_EVENT_HIBERNATE);
+}
+EXPORT_SYMBOL_GPL(pm_generic_poweroff);
+
+/**
+ * pm_generic_thaw - Generic thaw callback for subsystems.
+ * @dev: Device to thaw.
+ */
+int pm_generic_thaw(struct device *dev)
+{
+ return __pm_generic_call(dev, PM_EVENT_THAW);
+}
+EXPORT_SYMBOL_GPL(pm_generic_thaw);
+
+/**
+ * __pm_generic_resume - Generic resume/restore callback for subsystems.
+ * @dev: Device to handle.
+ * @event: PM transition of the system under way.
+ *
+ * Execute the resume/resotre callback provided by the @dev's driver, if
+ * defined. If it returns 0, change the device's runtime PM status to 'active'.
+ * Return the callback's error code.
+ */
+static int __pm_generic_resume(struct device *dev, int event)
+{
+ const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+ int (*callback)(struct device *);
+ int ret;
+
+ if (!pm)
+ return 0;
+
+ switch (event) {
+ case PM_EVENT_RESUME:
+ callback = pm->resume;
+ break;
+ case PM_EVENT_RESTORE:
+ callback = pm->restore;
+ break;
+ default:
+ callback = NULL;
+ break;
+ }
+
+ if (!callback)
+ return 0;
+
+ ret = callback(dev);
+ if (!ret) {
+ pm_runtime_disable(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+ }
+
+ return ret;
+}
+
+/**
+ * pm_generic_resume - Generic resume callback for subsystems.
+ * @dev: Device to resume.
+ */
+int pm_generic_resume(struct device *dev)
+{
+ return __pm_generic_resume(dev, PM_EVENT_RESUME);
+}
+EXPORT_SYMBOL_GPL(pm_generic_resume);
+
+/**
+ * pm_generic_restore - Generic restore callback for subsystems.
+ * @dev: Device to restore.
+ */
+int pm_generic_restore(struct device *dev)
+{
+ return __pm_generic_resume(dev, PM_EVENT_RESTORE);
+}
+EXPORT_SYMBOL_GPL(pm_generic_restore);
+#endif /* CONFIG_PM_SLEEP */
+
+struct dev_pm_ops generic_subsys_pm_ops = {
+#ifdef CONFIG_PM_SLEEP
+ .suspend = pm_generic_suspend,
+ .resume = pm_generic_resume,
+ .freeze = pm_generic_freeze,
+ .thaw = pm_generic_thaw,
+ .poweroff = pm_generic_poweroff,
+ .restore = pm_generic_restore,
+#endif
+#ifdef CONFIG_PM_RUNTIME
+ .runtime_suspend = pm_generic_runtime_suspend,
+ .runtime_resume = pm_generic_runtime_resume,
+ .runtime_idle = pm_generic_runtime_idle,
+#endif
+};
+EXPORT_SYMBOL_GPL(generic_subsys_pm_ops);
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 0e26a6f6fd4..d477f4dc5e5 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -35,8 +35,8 @@
* because children are guaranteed to be discovered after parents, and
* are inserted at the back of the list on discovery.
*
- * Since device_pm_add() may be called with a device semaphore held,
- * we must never try to acquire a device semaphore while holding
+ * Since device_pm_add() may be called with a device lock held,
+ * we must never try to acquire a device lock while holding
* dpm_list_mutex.
*/
@@ -508,7 +508,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
TRACE_RESUME(0);
dpm_wait(dev->parent, async);
- down(&dev->sem);
+ device_lock(dev);
dev->power.status = DPM_RESUMING;
@@ -543,7 +543,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
}
}
End:
- up(&dev->sem);
+ device_unlock(dev);
complete_all(&dev->power.completion);
TRACE_RESUME(error);
@@ -629,7 +629,7 @@ static void dpm_resume(pm_message_t state)
*/
static void device_complete(struct device *dev, pm_message_t state)
{
- down(&dev->sem);
+ device_lock(dev);
if (dev->class && dev->class->pm && dev->class->pm->complete) {
pm_dev_dbg(dev, state, "completing class ");
@@ -646,7 +646,7 @@ static void device_complete(struct device *dev, pm_message_t state)
dev->bus->pm->complete(dev);
}
- up(&dev->sem);
+ device_unlock(dev);
}
/**
@@ -809,7 +809,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
int error = 0;
dpm_wait_for_children(dev, async);
- down(&dev->sem);
+ device_lock(dev);
if (async_error)
goto End;
@@ -849,7 +849,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
dev->power.status = DPM_OFF;
End:
- up(&dev->sem);
+ device_unlock(dev);
complete_all(&dev->power.completion);
return error;
@@ -938,7 +938,7 @@ static int device_prepare(struct device *dev, pm_message_t state)
{
int error = 0;
- down(&dev->sem);
+ device_lock(dev);
if (dev->bus && dev->bus->pm && dev->bus->pm->prepare) {
pm_dev_dbg(dev, state, "preparing ");
@@ -962,7 +962,7 @@ static int device_prepare(struct device *dev, pm_message_t state)
suspend_report_result(dev->class->pm->prepare, error);
}
End:
- up(&dev->sem);
+ device_unlock(dev);
return error;
}
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 0d903909af7..8980feec5d1 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -54,7 +54,7 @@ sysdev_store(struct kobject *kobj, struct attribute *attr,
return -EIO;
}
-static struct sysfs_ops sysfs_ops = {
+static const struct sysfs_ops sysfs_ops = {
.show = sysdev_show,
.store = sysdev_store,
};
@@ -89,7 +89,7 @@ static ssize_t sysdev_class_show(struct kobject *kobj, struct attribute *attr,
struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr);
if (class_attr->show)
- return class_attr->show(class, buffer);
+ return class_attr->show(class, class_attr, buffer);
return -EIO;
}
@@ -100,11 +100,11 @@ static ssize_t sysdev_class_store(struct kobject *kobj, struct attribute *attr,
struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr);
if (class_attr->store)
- return class_attr->store(class, buffer, count);
+ return class_attr->store(class, class_attr, buffer, count);
return -EIO;
}
-static struct sysfs_ops sysfs_class_ops = {
+static const struct sysfs_ops sysfs_class_ops = {
.show = sysdev_class_show,
.store = sysdev_class_store,
};
@@ -145,13 +145,20 @@ int sysdev_class_register(struct sysdev_class *cls)
if (retval)
return retval;
- return kset_register(&cls->kset);
+ retval = kset_register(&cls->kset);
+ if (!retval && cls->attrs)
+ retval = sysfs_create_files(&cls->kset.kobj,
+ (const struct attribute **)cls->attrs);
+ return retval;
}
void sysdev_class_unregister(struct sysdev_class *cls)
{
pr_debug("Unregistering sysdev class '%s'\n",
kobject_name(&cls->kset.kobj));
+ if (cls->attrs)
+ sysfs_remove_files(&cls->kset.kobj,
+ (const struct attribute **)cls->attrs);
kset_unregister(&cls->kset);
}
diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c
index a808b1530b3..eb2091aa1c1 100644
--- a/drivers/block/osdblk.c
+++ b/drivers/block/osdblk.c
@@ -476,7 +476,9 @@ static void class_osdblk_release(struct class *cls)
kfree(cls);
}
-static ssize_t class_osdblk_list(struct class *c, char *data)
+static ssize_t class_osdblk_list(struct class *c,
+ struct class_attribute *attr,
+ char *data)
{
int n = 0;
struct list_head *tmp;
@@ -500,7 +502,9 @@ static ssize_t class_osdblk_list(struct class *c, char *data)
return n;
}
-static ssize_t class_osdblk_add(struct class *c, const char *buf, size_t count)
+static ssize_t class_osdblk_add(struct class *c,
+ struct class_attribute *attr,
+ const char *buf, size_t count)
{
struct osdblk_device *osdev;
ssize_t rc;
@@ -592,7 +596,9 @@ err_out_mod:
return rc;
}
-static ssize_t class_osdblk_remove(struct class *c, const char *buf,
+static ssize_t class_osdblk_remove(struct class *c,
+ struct class_attribute *attr,
+ const char *buf,
size_t count)
{
struct osdblk_device *osdev = NULL;
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index b72935b8f20..39c8514442e 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -284,7 +284,7 @@ static ssize_t kobj_pkt_store(struct kobject *kobj,
return len;
}
-static struct sysfs_ops kobj_pkt_ops = {
+static const struct sysfs_ops kobj_pkt_ops = {
.show = kobj_pkt_show,
.store = kobj_pkt_store
};
@@ -337,7 +337,9 @@ static void class_pktcdvd_release(struct class *cls)
{
kfree(cls);
}
-static ssize_t class_pktcdvd_show_map(struct class *c, char *data)
+static ssize_t class_pktcdvd_show_map(struct class *c,
+ struct class_attribute *attr,
+ char *data)
{
int n = 0;
int idx;
@@ -356,7 +358,9 @@ static ssize_t class_pktcdvd_show_map(struct class *c, char *data)
return n;
}
-static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf,
+static ssize_t class_pktcdvd_store_add(struct class *c,
+ struct class_attribute *attr,
+ const char *buf,
size_t count)
{
unsigned int major, minor;
@@ -376,7 +380,9 @@ static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf,
return -EINVAL;
}
-static ssize_t class_pktcdvd_store_remove(struct class *c, const char *buf,
+static ssize_t class_pktcdvd_store_remove(struct class *c,
+ struct class_attribute *attr,
+ const char *buf,
size_t count)
{
unsigned int major, minor;
diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c
index 21681a81cc3..37b0542a4ee 100644
--- a/drivers/char/hvc_iucv.c
+++ b/drivers/char/hvc_iucv.c
@@ -139,6 +139,8 @@ struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num)
*
* This function allocates a new struct iucv_tty_buffer element and, optionally,
* allocates an internal data buffer with the specified size @size.
+ * The internal data buffer is always allocated with GFP_DMA which is
+ * required for receiving and sending data with IUCV.
* Note: The total message size arises from the internal buffer size and the
* members of the iucv_tty_msg structure.
* The function returns NULL if memory allocation has failed.
@@ -154,7 +156,7 @@ static struct iucv_tty_buffer *alloc_tty_buffer(size_t size, gfp_t flags)
if (size > 0) {
bufp->msg.length = MSG_SIZE(size);
- bufp->mbuf = kmalloc(bufp->msg.length, flags);
+ bufp->mbuf = kmalloc(bufp->msg.length, flags | GFP_DMA);
if (!bufp->mbuf) {
mempool_free(bufp, hvc_iucv_mempool);
return NULL;
@@ -237,7 +239,7 @@ static int hvc_iucv_write(struct hvc_iucv_private *priv,
if (!rb->mbuf) { /* message not yet received ... */
/* allocate mem to store msg data; if no memory is available
* then leave the buffer on the list and re-try later */
- rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC);
+ rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC | GFP_DMA);
if (!rb->mbuf)
return -ENOMEM;
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 213373b5f17..f404ccfc9c2 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -379,7 +379,7 @@ static ssize_t send_control_msg(struct port *port, unsigned int event,
struct scatterlist sg[1];
struct virtio_console_control cpkt;
struct virtqueue *vq;
- int len;
+ unsigned int len;
if (!use_multiport(port->portdev))
return 0;
@@ -1071,27 +1071,27 @@ static void config_intr(struct virtio_device *vdev)
static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock)
{
struct port_buffer *buf;
- unsigned int ret;
- int err;
+ unsigned int nr_added_bufs;
+ int ret;
- ret = 0;
+ nr_added_bufs = 0;
do {
buf = alloc_buf(PAGE_SIZE);
if (!buf)
break;
spin_lock_irq(lock);
- err = add_inbuf(vq, buf);
- if (err < 0) {
+ ret = add_inbuf(vq, buf);
+ if (ret < 0) {
spin_unlock_irq(lock);
free_buf(buf);
break;
}
- ret++;
+ nr_added_bufs++;
spin_unlock_irq(lock);
- } while (err > 0);
+ } while (ret > 0);
- return ret;
+ return nr_added_bufs;
}
static int add_port(struct ports_device *portdev, u32 id)
@@ -1100,6 +1100,7 @@ static int add_port(struct ports_device *portdev, u32 id)
struct port *port;
struct port_buffer *buf;
dev_t devt;
+ unsigned int nr_added_bufs;
int err;
port = kmalloc(sizeof(*port), GFP_KERNEL);
@@ -1144,8 +1145,8 @@ static int add_port(struct ports_device *portdev, u32 id)
init_waitqueue_head(&port->waitqueue);
/* Fill the in_vq with buffers so the host can send us data. */
- err = fill_queue(port->in_vq, &port->inbuf_lock);
- if (!err) {
+ nr_added_bufs = fill_queue(port->in_vq, &port->inbuf_lock);
+ if (!nr_added_bufs) {
dev_err(port->dev, "Error allocating inbufs\n");
err = -ENOMEM;
goto free_device;
@@ -1442,12 +1443,14 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
INIT_LIST_HEAD(&portdev->ports);
if (multiport) {
+ unsigned int nr_added_bufs;
+
spin_lock_init(&portdev->cvq_lock);
INIT_WORK(&portdev->control_work, &control_work_handler);
INIT_WORK(&portdev->config_work, &config_work_handler);
- err = fill_queue(portdev->c_ivq, &portdev->cvq_lock);
- if (!err) {
+ nr_added_bufs = fill_queue(portdev->c_ivq, &portdev->cvq_lock);
+ if (!nr_added_bufs) {
dev_err(&vdev->dev,
"Error allocating buffers for control queue\n");
err = -ENOMEM;
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
deleted file mode 100644
index 08f726c5fee..00000000000
--- a/drivers/clocksource/Kconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-config CS5535_CLOCK_EVENT_SRC
- tristate "CS5535/CS5536 high-res timer (MFGPT) events"
- depends on GENERIC_TIME && GENERIC_CLOCKEVENTS && CS5535_MFGPT
- help
- This driver provides a clock event source based on the MFGPT
- timer(s) in the CS5535 and CS5536 companion chips.
- MFGPTs have a better resolution and max interval than the
- generic PIT, and are suitable for use as high-res timers.
-
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 67bc2ece7b4..2d5d575e889 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -766,7 +766,7 @@ static void cpufreq_sysfs_release(struct kobject *kobj)
complete(&policy->kobj_unregister);
}
-static struct sysfs_ops sysfs_ops = {
+static const struct sysfs_ops sysfs_ops = {
.show = show,
.store = store,
};
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 73655aeb3a6..1aea7157d8f 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -100,8 +100,8 @@ struct menu_device {
int needs_update;
unsigned int expected_us;
- u64 predicted_us;
unsigned int measured_us;
+ u64 predicted_us;
unsigned int exit_us;
unsigned int bucket;
u64 correction_factor[BUCKETS];
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index 97b003839fb..8719b36e1a4 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -22,6 +22,7 @@ static int __init cpuidle_sysfs_setup(char *unused)
__setup("cpuidle_sysfs_switch", cpuidle_sysfs_setup);
static ssize_t show_available_governors(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
char *buf)
{
ssize_t i = 0;
@@ -41,6 +42,7 @@ out:
}
static ssize_t show_current_driver(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
char *buf)
{
ssize_t ret;
@@ -56,6 +58,7 @@ static ssize_t show_current_driver(struct sysdev_class *class,
}
static ssize_t show_current_governor(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
char *buf)
{
ssize_t ret;
@@ -71,6 +74,7 @@ static ssize_t show_current_governor(struct sysdev_class *class,
}
static ssize_t store_current_governor(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
const char *buf, size_t count)
{
char gov_name[CPUIDLE_NAME_LEN];
@@ -191,7 +195,7 @@ static ssize_t cpuidle_store(struct kobject * kobj, struct attribute * attr,
return ret;
}
-static struct sysfs_ops cpuidle_sysfs_ops = {
+static const struct sysfs_ops cpuidle_sysfs_ops = {
.show = cpuidle_show,
.store = cpuidle_store,
};
@@ -277,7 +281,7 @@ static ssize_t cpuidle_state_show(struct kobject * kobj,
return ret;
}
-static struct sysfs_ops cpuidle_state_sysfs_ops = {
+static const struct sysfs_ops cpuidle_state_sysfs_ops = {
.show = cpuidle_state_show,
};
diff --git a/drivers/dma/ioat/dma.c b/drivers/dma/ioat/dma.c
index 5d0e42b263d..0099340b961 100644
--- a/drivers/dma/ioat/dma.c
+++ b/drivers/dma/ioat/dma.c
@@ -71,7 +71,7 @@ static irqreturn_t ioat_dma_do_interrupt(int irq, void *data)
}
attnstatus = readl(instance->reg_base + IOAT_ATTNSTATUS_OFFSET);
- for_each_bit(bit, &attnstatus, BITS_PER_LONG) {
+ for_each_set_bit(bit, &attnstatus, BITS_PER_LONG) {
chan = ioat_chan_by_index(instance, bit);
tasklet_schedule(&chan->cleanup_task);
}
@@ -1138,7 +1138,7 @@ ioat_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
return entry->show(&chan->common, page);
}
-struct sysfs_ops ioat_sysfs_ops = {
+const struct sysfs_ops ioat_sysfs_ops = {
.show = ioat_attr_show,
};
diff --git a/drivers/dma/ioat/dma.h b/drivers/dma/ioat/dma.h
index 4f747a25407..86b97ac8774 100644
--- a/drivers/dma/ioat/dma.h
+++ b/drivers/dma/ioat/dma.h
@@ -346,7 +346,7 @@ bool ioat_cleanup_preamble(struct ioat_chan_common *chan,
unsigned long *phys_complete);
void ioat_kobject_add(struct ioatdma_device *device, struct kobj_type *type);
void ioat_kobject_del(struct ioatdma_device *device);
-extern struct sysfs_ops ioat_sysfs_ops;
+extern const struct sysfs_ops ioat_sysfs_ops;
extern struct ioat_sysfs_entry ioat_version_attr;
extern struct ioat_sysfs_entry ioat_cap_attr;
#endif /* IOATDMA_H */
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c
index b75ce8b84c4..5d17e09cb62 100644
--- a/drivers/dma/shdma.c
+++ b/drivers/dma/shdma.c
@@ -24,8 +24,10 @@
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
-#include <cpu/dma.h>
-#include <asm/dma-sh.h>
+#include <linux/pm_runtime.h>
+
+#include <asm/dmaengine.h>
+
#include "shdma.h"
/* DMA descriptor control */
@@ -38,30 +40,32 @@ enum sh_dmae_desc_status {
};
#define NR_DESCS_PER_CHANNEL 32
-/*
- * Define the default configuration for dual address memory-memory transfer.
- * The 0x400 value represents auto-request, external->external.
- *
- * And this driver set 4byte burst mode.
- * If you want to change mode, you need to change RS_DEFAULT of value.
- * (ex 1byte burst mode -> (RS_DUAL & ~TS_32)
- */
-#define RS_DEFAULT (RS_DUAL)
+/* Default MEMCPY transfer size = 2^2 = 4 bytes */
+#define LOG2_DEFAULT_XFER_SIZE 2
/* A bitmask with bits enough for enum sh_dmae_slave_chan_id */
static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SHDMA_SLAVE_NUMBER)];
static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all);
-#define SH_DMAC_CHAN_BASE(id) (dma_base_addr[id])
static void sh_dmae_writel(struct sh_dmae_chan *sh_dc, u32 data, u32 reg)
{
- ctrl_outl(data, SH_DMAC_CHAN_BASE(sh_dc->id) + reg);
+ __raw_writel(data, sh_dc->base + reg / sizeof(u32));
}
static u32 sh_dmae_readl(struct sh_dmae_chan *sh_dc, u32 reg)
{
- return ctrl_inl(SH_DMAC_CHAN_BASE(sh_dc->id) + reg);
+ return __raw_readl(sh_dc->base + reg / sizeof(u32));
+}
+
+static u16 dmaor_read(struct sh_dmae_device *shdev)
+{
+ return __raw_readw(shdev->chan_reg + DMAOR / sizeof(u32));
+}
+
+static void dmaor_write(struct sh_dmae_device *shdev, u16 data)
+{
+ __raw_writew(data, shdev->chan_reg + DMAOR / sizeof(u32));
}
/*
@@ -69,24 +73,23 @@ static u32 sh_dmae_readl(struct sh_dmae_chan *sh_dc, u32 reg)
*
* SH7780 has two DMAOR register
*/
-static void sh_dmae_ctl_stop(int id)
+static void sh_dmae_ctl_stop(struct sh_dmae_device *shdev)
{
- unsigned short dmaor = dmaor_read_reg(id);
+ unsigned short dmaor = dmaor_read(shdev);
- dmaor &= ~(DMAOR_NMIF | DMAOR_AE);
- dmaor_write_reg(id, dmaor);
+ dmaor_write(shdev, dmaor & ~(DMAOR_NMIF | DMAOR_AE | DMAOR_DME));
}
-static int sh_dmae_rst(int id)
+static int sh_dmae_rst(struct sh_dmae_device *shdev)
{
unsigned short dmaor;
- sh_dmae_ctl_stop(id);
- dmaor = dmaor_read_reg(id) | DMAOR_INIT;
+ sh_dmae_ctl_stop(shdev);
+ dmaor = dmaor_read(shdev) | shdev->pdata->dmaor_init;
- dmaor_write_reg(id, dmaor);
- if (dmaor_read_reg(id) & (DMAOR_AE | DMAOR_NMIF)) {
- pr_warning(KERN_ERR "dma-sh: Can't initialize DMAOR.\n");
+ dmaor_write(shdev, dmaor);
+ if (dmaor_read(shdev) & (DMAOR_AE | DMAOR_NMIF)) {
+ pr_warning("dma-sh: Can't initialize DMAOR.\n");
return -EINVAL;
}
return 0;
@@ -102,13 +105,36 @@ static bool dmae_is_busy(struct sh_dmae_chan *sh_chan)
return false; /* waiting */
}
-static unsigned int ts_shift[] = TS_SHIFT;
-static inline unsigned int calc_xmit_shift(u32 chcr)
+static unsigned int calc_xmit_shift(struct sh_dmae_chan *sh_chan, u32 chcr)
{
- int cnt = ((chcr & CHCR_TS_LOW_MASK) >> CHCR_TS_LOW_SHIFT) |
- ((chcr & CHCR_TS_HIGH_MASK) >> CHCR_TS_HIGH_SHIFT);
+ struct sh_dmae_device *shdev = container_of(sh_chan->common.device,
+ struct sh_dmae_device, common);
+ struct sh_dmae_pdata *pdata = shdev->pdata;
+ int cnt = ((chcr & pdata->ts_low_mask) >> pdata->ts_low_shift) |
+ ((chcr & pdata->ts_high_mask) >> pdata->ts_high_shift);
+
+ if (cnt >= pdata->ts_shift_num)
+ cnt = 0;
- return ts_shift[cnt];
+ return pdata->ts_shift[cnt];
+}
+
+static u32 log2size_to_chcr(struct sh_dmae_chan *sh_chan, int l2size)
+{
+ struct sh_dmae_device *shdev = container_of(sh_chan->common.device,
+ struct sh_dmae_device, common);
+ struct sh_dmae_pdata *pdata = shdev->pdata;
+ int i;
+
+ for (i = 0; i < pdata->ts_shift_num; i++)
+ if (pdata->ts_shift[i] == l2size)
+ break;
+
+ if (i == pdata->ts_shift_num)
+ i = 0;
+
+ return ((i << pdata->ts_low_shift) & pdata->ts_low_mask) |
+ ((i << pdata->ts_high_shift) & pdata->ts_high_mask);
}
static void dmae_set_reg(struct sh_dmae_chan *sh_chan, struct sh_dmae_regs *hw)
@@ -136,8 +162,13 @@ static void dmae_halt(struct sh_dmae_chan *sh_chan)
static void dmae_init(struct sh_dmae_chan *sh_chan)
{
- u32 chcr = RS_DEFAULT; /* default is DUAL mode */
- sh_chan->xmit_shift = calc_xmit_shift(chcr);
+ /*
+ * Default configuration for dual address memory-memory transfer.
+ * 0x400 represents auto-request.
+ */
+ u32 chcr = DM_INC | SM_INC | 0x400 | log2size_to_chcr(sh_chan,
+ LOG2_DEFAULT_XFER_SIZE);
+ sh_chan->xmit_shift = calc_xmit_shift(sh_chan, chcr);
sh_dmae_writel(sh_chan, chcr, CHCR);
}
@@ -147,37 +178,26 @@ static int dmae_set_chcr(struct sh_dmae_chan *sh_chan, u32 val)
if (dmae_is_busy(sh_chan))
return -EBUSY;
- sh_chan->xmit_shift = calc_xmit_shift(val);
+ sh_chan->xmit_shift = calc_xmit_shift(sh_chan, val);
sh_dmae_writel(sh_chan, val, CHCR);
return 0;
}
-#define DMARS_SHIFT 8
-#define DMARS_CHAN_MSK 0x01
static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)
{
- u32 addr;
- int shift = 0;
+ struct sh_dmae_device *shdev = container_of(sh_chan->common.device,
+ struct sh_dmae_device, common);
+ struct sh_dmae_pdata *pdata = shdev->pdata;
+ struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id];
+ u16 __iomem *addr = shdev->dmars + chan_pdata->dmars / sizeof(u16);
+ int shift = chan_pdata->dmars_bit;
if (dmae_is_busy(sh_chan))
return -EBUSY;
- if (sh_chan->id & DMARS_CHAN_MSK)
- shift = DMARS_SHIFT;
-
- if (sh_chan->id < 6)
- /* DMA0RS0 - DMA0RS2 */
- addr = SH_DMARS_BASE0 + (sh_chan->id / 2) * 4;
-#ifdef SH_DMARS_BASE1
- else if (sh_chan->id < 12)
- /* DMA1RS0 - DMA1RS2 */
- addr = SH_DMARS_BASE1 + ((sh_chan->id - 6) / 2) * 4;
-#endif
- else
- return -EINVAL;
-
- ctrl_outw((val << shift) | (ctrl_inw(addr) & (0xFF00 >> shift)), addr);
+ __raw_writew((__raw_readw(addr) & (0xff00 >> shift)) | (val << shift),
+ addr);
return 0;
}
@@ -251,15 +271,15 @@ static struct sh_dmae_slave_config *sh_dmae_find_slave(
struct dma_device *dma_dev = sh_chan->common.device;
struct sh_dmae_device *shdev = container_of(dma_dev,
struct sh_dmae_device, common);
- struct sh_dmae_pdata *pdata = &shdev->pdata;
+ struct sh_dmae_pdata *pdata = shdev->pdata;
int i;
if ((unsigned)slave_id >= SHDMA_SLAVE_NUMBER)
return NULL;
- for (i = 0; i < pdata->config_num; i++)
- if (pdata->config[i].slave_id == slave_id)
- return pdata->config + i;
+ for (i = 0; i < pdata->slave_num; i++)
+ if (pdata->slave[i].slave_id == slave_id)
+ return pdata->slave + i;
return NULL;
}
@@ -270,6 +290,8 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan)
struct sh_desc *desc;
struct sh_dmae_slave *param = chan->private;
+ pm_runtime_get_sync(sh_chan->dev);
+
/*
* This relies on the guarantee from dmaengine that alloc_chan_resources
* never runs concurrently with itself or free_chan_resources.
@@ -288,9 +310,8 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan)
dmae_set_dmars(sh_chan, cfg->mid_rid);
dmae_set_chcr(sh_chan, cfg->chcr);
- } else {
- if ((sh_dmae_readl(sh_chan, CHCR) & 0x700) != 0x400)
- dmae_set_chcr(sh_chan, RS_DEFAULT);
+ } else if ((sh_dmae_readl(sh_chan, CHCR) & 0xf00) != 0x400) {
+ dmae_init(sh_chan);
}
spin_lock_bh(&sh_chan->desc_lock);
@@ -312,6 +333,9 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan)
}
spin_unlock_bh(&sh_chan->desc_lock);
+ if (!sh_chan->descs_allocated)
+ pm_runtime_put(sh_chan->dev);
+
return sh_chan->descs_allocated;
}
@@ -323,6 +347,7 @@ static void sh_dmae_free_chan_resources(struct dma_chan *chan)
struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
struct sh_desc *desc, *_desc;
LIST_HEAD(list);
+ int descs = sh_chan->descs_allocated;
dmae_halt(sh_chan);
@@ -343,6 +368,9 @@ static void sh_dmae_free_chan_resources(struct dma_chan *chan)
spin_unlock_bh(&sh_chan->desc_lock);
+ if (descs > 0)
+ pm_runtime_put(sh_chan->dev);
+
list_for_each_entry_safe(desc, _desc, &list, node)
kfree(desc);
}
@@ -559,6 +587,19 @@ static void sh_dmae_terminate_all(struct dma_chan *chan)
if (!chan)
return;
+ dmae_halt(sh_chan);
+
+ spin_lock_bh(&sh_chan->desc_lock);
+ if (!list_empty(&sh_chan->ld_queue)) {
+ /* Record partial transfer */
+ struct sh_desc *desc = list_entry(sh_chan->ld_queue.next,
+ struct sh_desc, node);
+ desc->partial = (desc->hw.tcr - sh_dmae_readl(sh_chan, TCR)) <<
+ sh_chan->xmit_shift;
+
+ }
+ spin_unlock_bh(&sh_chan->desc_lock);
+
sh_dmae_chan_ld_cleanup(sh_chan, true);
}
@@ -661,7 +702,7 @@ static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all)
static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan)
{
- struct sh_desc *sd;
+ struct sh_desc *desc;
spin_lock_bh(&sh_chan->desc_lock);
/* DMA work check */
@@ -671,10 +712,13 @@ static void sh_chan_xfer_ld_queue(struct sh_dmae_chan *sh_chan)
}
/* Find the first not transferred desciptor */
- list_for_each_entry(sd, &sh_chan->ld_queue, node)
- if (sd->mark == DESC_SUBMITTED) {
+ list_for_each_entry(desc, &sh_chan->ld_queue, node)
+ if (desc->mark == DESC_SUBMITTED) {
+ dev_dbg(sh_chan->dev, "Queue #%d to %d: %u@%x -> %x\n",
+ desc->async_tx.cookie, sh_chan->id,
+ desc->hw.tcr, desc->hw.sar, desc->hw.dar);
/* Get the ld start address from ld_queue */
- dmae_set_reg(sh_chan, &sd->hw);
+ dmae_set_reg(sh_chan, &desc->hw);
dmae_start(sh_chan);
break;
}
@@ -696,6 +740,7 @@ static enum dma_status sh_dmae_is_complete(struct dma_chan *chan,
struct sh_dmae_chan *sh_chan = to_sh_chan(chan);
dma_cookie_t last_used;
dma_cookie_t last_complete;
+ enum dma_status status;
sh_dmae_chan_ld_cleanup(sh_chan, false);
@@ -709,7 +754,27 @@ static enum dma_status sh_dmae_is_complete(struct dma_chan *chan,
if (used)
*used = last_used;
- return dma_async_is_complete(cookie, last_complete, last_used);
+ spin_lock_bh(&sh_chan->desc_lock);
+
+ status = dma_async_is_complete(cookie, last_complete, last_used);
+
+ /*
+ * If we don't find cookie on the queue, it has been aborted and we have
+ * to report error
+ */
+ if (status != DMA_SUCCESS) {
+ struct sh_desc *desc;
+ status = DMA_ERROR;
+ list_for_each_entry(desc, &sh_chan->ld_queue, node)
+ if (desc->cookie == cookie) {
+ status = DMA_IN_PROGRESS;
+ break;
+ }
+ }
+
+ spin_unlock_bh(&sh_chan->desc_lock);
+
+ return status;
}
static irqreturn_t sh_dmae_interrupt(int irq, void *data)
@@ -732,40 +797,32 @@ static irqreturn_t sh_dmae_interrupt(int irq, void *data)
#if defined(CONFIG_CPU_SH4)
static irqreturn_t sh_dmae_err(int irq, void *data)
{
- int err = 0;
struct sh_dmae_device *shdev = (struct sh_dmae_device *)data;
+ int i;
- /* IRQ Multi */
- if (shdev->pdata.mode & SHDMA_MIX_IRQ) {
- int __maybe_unused cnt = 0;
- switch (irq) {
-#if defined(DMTE6_IRQ) && defined(DMAE1_IRQ)
- case DMTE6_IRQ:
- cnt++;
-#endif
- case DMTE0_IRQ:
- if (dmaor_read_reg(cnt) & (DMAOR_NMIF | DMAOR_AE)) {
- disable_irq(irq);
- return IRQ_HANDLED;
+ /* halt the dma controller */
+ sh_dmae_ctl_stop(shdev);
+
+ /* We cannot detect, which channel caused the error, have to reset all */
+ for (i = 0; i < SH_DMAC_MAX_CHANNELS; i++) {
+ struct sh_dmae_chan *sh_chan = shdev->chan[i];
+ if (sh_chan) {
+ struct sh_desc *desc;
+ /* Stop the channel */
+ dmae_halt(sh_chan);
+ /* Complete all */
+ list_for_each_entry(desc, &sh_chan->ld_queue, node) {
+ struct dma_async_tx_descriptor *tx = &desc->async_tx;
+ desc->mark = DESC_IDLE;
+ if (tx->callback)
+ tx->callback(tx->callback_param);
}
- default:
- return IRQ_NONE;
+ list_splice_init(&sh_chan->ld_queue, &sh_chan->ld_free);
}
- } else {
- /* reset dma controller */
- err = sh_dmae_rst(0);
- if (err)
- return err;
-#ifdef SH_DMAC_BASE1
- if (shdev->pdata.mode & SHDMA_DMAOR1) {
- err = sh_dmae_rst(1);
- if (err)
- return err;
- }
-#endif
- disable_irq(irq);
- return IRQ_HANDLED;
}
+ sh_dmae_rst(shdev);
+
+ return IRQ_HANDLED;
}
#endif
@@ -796,19 +853,12 @@ static void dmae_do_tasklet(unsigned long data)
sh_dmae_chan_ld_cleanup(sh_chan, false);
}
-static unsigned int get_dmae_irq(unsigned int id)
-{
- unsigned int irq = 0;
- if (id < ARRAY_SIZE(dmte_irq_map))
- irq = dmte_irq_map[id];
- return irq;
-}
-
-static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id)
+static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id,
+ int irq, unsigned long flags)
{
int err;
- unsigned int irq = get_dmae_irq(id);
- unsigned long irqflags = IRQF_DISABLED;
+ struct sh_dmae_channel *chan_pdata = &shdev->pdata->channel[id];
+ struct platform_device *pdev = to_platform_device(shdev->common.dev);
struct sh_dmae_chan *new_sh_chan;
/* alloc channel */
@@ -819,8 +869,13 @@ static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id)
return -ENOMEM;
}
+ /* copy struct dma_device */
+ new_sh_chan->common.device = &shdev->common;
+
new_sh_chan->dev = shdev->common.dev;
new_sh_chan->id = id;
+ new_sh_chan->irq = irq;
+ new_sh_chan->base = shdev->chan_reg + chan_pdata->offset / sizeof(u32);
/* Init DMA tasklet */
tasklet_init(&new_sh_chan->tasklet, dmae_do_tasklet,
@@ -835,29 +890,20 @@ static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id)
INIT_LIST_HEAD(&new_sh_chan->ld_queue);
INIT_LIST_HEAD(&new_sh_chan->ld_free);
- /* copy struct dma_device */
- new_sh_chan->common.device = &shdev->common;
-
/* Add the channel to DMA device channel list */
list_add_tail(&new_sh_chan->common.device_node,
&shdev->common.channels);
shdev->common.chancnt++;
- if (shdev->pdata.mode & SHDMA_MIX_IRQ) {
- irqflags = IRQF_SHARED;
-#if defined(DMTE6_IRQ)
- if (irq >= DMTE6_IRQ)
- irq = DMTE6_IRQ;
- else
-#endif
- irq = DMTE0_IRQ;
- }
-
- snprintf(new_sh_chan->dev_id, sizeof(new_sh_chan->dev_id),
- "sh-dmae%d", new_sh_chan->id);
+ if (pdev->id >= 0)
+ snprintf(new_sh_chan->dev_id, sizeof(new_sh_chan->dev_id),
+ "sh-dmae%d.%d", pdev->id, new_sh_chan->id);
+ else
+ snprintf(new_sh_chan->dev_id, sizeof(new_sh_chan->dev_id),
+ "sh-dma%d", new_sh_chan->id);
/* set up channel irq */
- err = request_irq(irq, &sh_dmae_interrupt, irqflags,
+ err = request_irq(irq, &sh_dmae_interrupt, flags,
new_sh_chan->dev_id, new_sh_chan);
if (err) {
dev_err(shdev->common.dev, "DMA channel %d request_irq error "
@@ -881,12 +927,12 @@ static void sh_dmae_chan_remove(struct sh_dmae_device *shdev)
for (i = shdev->common.chancnt - 1 ; i >= 0 ; i--) {
if (shdev->chan[i]) {
- struct sh_dmae_chan *shchan = shdev->chan[i];
- if (!(shdev->pdata.mode & SHDMA_MIX_IRQ))
- free_irq(dmte_irq_map[i], shchan);
+ struct sh_dmae_chan *sh_chan = shdev->chan[i];
- list_del(&shchan->common.device_node);
- kfree(shchan);
+ free_irq(sh_chan->irq, sh_chan);
+
+ list_del(&sh_chan->common.device_node);
+ kfree(sh_chan);
shdev->chan[i] = NULL;
}
}
@@ -895,47 +941,84 @@ static void sh_dmae_chan_remove(struct sh_dmae_device *shdev)
static int __init sh_dmae_probe(struct platform_device *pdev)
{
- int err = 0, cnt, ecnt;
- unsigned long irqflags = IRQF_DISABLED;
-#if defined(CONFIG_CPU_SH4)
- int eirq[] = { DMAE0_IRQ,
-#if defined(DMAE1_IRQ)
- DMAE1_IRQ
-#endif
- };
-#endif
+ struct sh_dmae_pdata *pdata = pdev->dev.platform_data;
+ unsigned long irqflags = IRQF_DISABLED,
+ chan_flag[SH_DMAC_MAX_CHANNELS] = {};
+ int errirq, chan_irq[SH_DMAC_MAX_CHANNELS];
+ int err, i, irq_cnt = 0, irqres = 0;
struct sh_dmae_device *shdev;
+ struct resource *chan, *dmars, *errirq_res, *chanirq_res;
/* get platform data */
- if (!pdev->dev.platform_data)
+ if (!pdata || !pdata->channel_num)
return -ENODEV;
+ chan = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ /* DMARS area is optional, if absent, this controller cannot do slave DMA */
+ dmars = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ /*
+ * IRQ resources:
+ * 1. there always must be at least one IRQ IO-resource. On SH4 it is
+ * the error IRQ, in which case it is the only IRQ in this resource:
+ * start == end. If it is the only IRQ resource, all channels also
+ * use the same IRQ.
+ * 2. DMA channel IRQ resources can be specified one per resource or in
+ * ranges (start != end)
+ * 3. iff all events (channels and, optionally, error) on this
+ * controller use the same IRQ, only one IRQ resource can be
+ * specified, otherwise there must be one IRQ per channel, even if
+ * some of them are equal
+ * 4. if all IRQs on this controller are equal or if some specific IRQs
+ * specify IORESOURCE_IRQ_SHAREABLE in their resources, they will be
+ * requested with the IRQF_SHARED flag
+ */
+ errirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!chan || !errirq_res)
+ return -ENODEV;
+
+ if (!request_mem_region(chan->start, resource_size(chan), pdev->name)) {
+ dev_err(&pdev->dev, "DMAC register region already claimed\n");
+ return -EBUSY;
+ }
+
+ if (dmars && !request_mem_region(dmars->start, resource_size(dmars), pdev->name)) {
+ dev_err(&pdev->dev, "DMAC DMARS region already claimed\n");
+ err = -EBUSY;
+ goto ermrdmars;
+ }
+
+ err = -ENOMEM;
shdev = kzalloc(sizeof(struct sh_dmae_device), GFP_KERNEL);
if (!shdev) {
- dev_err(&pdev->dev, "No enough memory\n");
- return -ENOMEM;
+ dev_err(&pdev->dev, "Not enough memory\n");
+ goto ealloc;
+ }
+
+ shdev->chan_reg = ioremap(chan->start, resource_size(chan));
+ if (!shdev->chan_reg)
+ goto emapchan;
+ if (dmars) {
+ shdev->dmars = ioremap(dmars->start, resource_size(dmars));
+ if (!shdev->dmars)
+ goto emapdmars;
}
/* platform data */
- memcpy(&shdev->pdata, pdev->dev.platform_data,
- sizeof(struct sh_dmae_pdata));
+ shdev->pdata = pdata;
+
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
/* reset dma controller */
- err = sh_dmae_rst(0);
+ err = sh_dmae_rst(shdev);
if (err)
goto rst_err;
- /* SH7780/85/23 has DMAOR1 */
- if (shdev->pdata.mode & SHDMA_DMAOR1) {
- err = sh_dmae_rst(1);
- if (err)
- goto rst_err;
- }
-
INIT_LIST_HEAD(&shdev->common.channels);
dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask);
- dma_cap_set(DMA_SLAVE, shdev->common.cap_mask);
+ if (dmars)
+ dma_cap_set(DMA_SLAVE, shdev->common.cap_mask);
shdev->common.device_alloc_chan_resources
= sh_dmae_alloc_chan_resources;
@@ -950,37 +1033,72 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
shdev->common.dev = &pdev->dev;
/* Default transfer size of 32 bytes requires 32-byte alignment */
- shdev->common.copy_align = 5;
+ shdev->common.copy_align = LOG2_DEFAULT_XFER_SIZE;
#if defined(CONFIG_CPU_SH4)
- /* Non Mix IRQ mode SH7722/SH7730 etc... */
- if (shdev->pdata.mode & SHDMA_MIX_IRQ) {
+ chanirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+
+ if (!chanirq_res)
+ chanirq_res = errirq_res;
+ else
+ irqres++;
+
+ if (chanirq_res == errirq_res ||
+ (errirq_res->flags & IORESOURCE_BITS) == IORESOURCE_IRQ_SHAREABLE)
irqflags = IRQF_SHARED;
- eirq[0] = DMTE0_IRQ;
-#if defined(DMTE6_IRQ) && defined(DMAE1_IRQ)
- eirq[1] = DMTE6_IRQ;
-#endif
+
+ errirq = errirq_res->start;
+
+ err = request_irq(errirq, sh_dmae_err, irqflags,
+ "DMAC Address Error", shdev);
+ if (err) {
+ dev_err(&pdev->dev,
+ "DMA failed requesting irq #%d, error %d\n",
+ errirq, err);
+ goto eirq_err;
}
- for (ecnt = 0 ; ecnt < ARRAY_SIZE(eirq); ecnt++) {
- err = request_irq(eirq[ecnt], sh_dmae_err, irqflags,
- "DMAC Address Error", shdev);
- if (err) {
- dev_err(&pdev->dev, "DMA device request_irq"
- "error (irq %d) with return %d\n",
- eirq[ecnt], err);
- goto eirq_err;
+#else
+ chanirq_res = errirq_res;
+#endif /* CONFIG_CPU_SH4 */
+
+ if (chanirq_res->start == chanirq_res->end &&
+ !platform_get_resource(pdev, IORESOURCE_IRQ, 1)) {
+ /* Special case - all multiplexed */
+ for (; irq_cnt < pdata->channel_num; irq_cnt++) {
+ chan_irq[irq_cnt] = chanirq_res->start;
+ chan_flag[irq_cnt] = IRQF_SHARED;
}
+ } else {
+ do {
+ for (i = chanirq_res->start; i <= chanirq_res->end; i++) {
+ if ((errirq_res->flags & IORESOURCE_BITS) ==
+ IORESOURCE_IRQ_SHAREABLE)
+ chan_flag[irq_cnt] = IRQF_SHARED;
+ else
+ chan_flag[irq_cnt] = IRQF_DISABLED;
+ dev_dbg(&pdev->dev,
+ "Found IRQ %d for channel %d\n",
+ i, irq_cnt);
+ chan_irq[irq_cnt++] = i;
+ }
+ chanirq_res = platform_get_resource(pdev,
+ IORESOURCE_IRQ, ++irqres);
+ } while (irq_cnt < pdata->channel_num && chanirq_res);
}
-#endif /* CONFIG_CPU_SH4 */
+
+ if (irq_cnt < pdata->channel_num)
+ goto eirqres;
/* Create DMA Channel */
- for (cnt = 0 ; cnt < MAX_DMA_CHANNELS ; cnt++) {
- err = sh_dmae_chan_probe(shdev, cnt);
+ for (i = 0; i < pdata->channel_num; i++) {
+ err = sh_dmae_chan_probe(shdev, i, chan_irq[i], chan_flag[i]);
if (err)
goto chan_probe_err;
}
+ pm_runtime_put(&pdev->dev);
+
platform_set_drvdata(pdev, shdev);
dma_async_device_register(&shdev->common);
@@ -988,13 +1106,24 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
chan_probe_err:
sh_dmae_chan_remove(shdev);
-
+eirqres:
+#if defined(CONFIG_CPU_SH4)
+ free_irq(errirq, shdev);
eirq_err:
- for (ecnt-- ; ecnt >= 0; ecnt--)
- free_irq(eirq[ecnt], shdev);
-
+#endif
rst_err:
+ pm_runtime_put(&pdev->dev);
+ if (dmars)
+ iounmap(shdev->dmars);
+emapdmars:
+ iounmap(shdev->chan_reg);
+emapchan:
kfree(shdev);
+ealloc:
+ if (dmars)
+ release_mem_region(dmars->start, resource_size(dmars));
+ermrdmars:
+ release_mem_region(chan->start, resource_size(chan));
return err;
}
@@ -1002,36 +1131,39 @@ rst_err:
static int __exit sh_dmae_remove(struct platform_device *pdev)
{
struct sh_dmae_device *shdev = platform_get_drvdata(pdev);
+ struct resource *res;
+ int errirq = platform_get_irq(pdev, 0);
dma_async_device_unregister(&shdev->common);
- if (shdev->pdata.mode & SHDMA_MIX_IRQ) {
- free_irq(DMTE0_IRQ, shdev);
-#if defined(DMTE6_IRQ)
- free_irq(DMTE6_IRQ, shdev);
-#endif
- }
+ if (errirq > 0)
+ free_irq(errirq, shdev);
/* channel data remove */
sh_dmae_chan_remove(shdev);
- if (!(shdev->pdata.mode & SHDMA_MIX_IRQ)) {
- free_irq(DMAE0_IRQ, shdev);
-#if defined(DMAE1_IRQ)
- free_irq(DMAE1_IRQ, shdev);
-#endif
- }
+ pm_runtime_disable(&pdev->dev);
+
+ if (shdev->dmars)
+ iounmap(shdev->dmars);
+ iounmap(shdev->chan_reg);
+
kfree(shdev);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res)
+ release_mem_region(res->start, resource_size(res));
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (res)
+ release_mem_region(res->start, resource_size(res));
+
return 0;
}
static void sh_dmae_shutdown(struct platform_device *pdev)
{
struct sh_dmae_device *shdev = platform_get_drvdata(pdev);
- sh_dmae_ctl_stop(0);
- if (shdev->pdata.mode & SHDMA_DMAOR1)
- sh_dmae_ctl_stop(1);
+ sh_dmae_ctl_stop(shdev);
}
static struct platform_driver sh_dmae_driver = {
diff --git a/drivers/dma/shdma.h b/drivers/dma/shdma.h
index 7e227f3c87c..153609a1e96 100644
--- a/drivers/dma/shdma.h
+++ b/drivers/dma/shdma.h
@@ -17,23 +17,9 @@
#include <linux/interrupt.h>
#include <linux/list.h>
-#define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */
-
-struct sh_dmae_regs {
- u32 sar; /* SAR / source address */
- u32 dar; /* DAR / destination address */
- u32 tcr; /* TCR / transfer count */
-};
+#include <asm/dmaengine.h>
-struct sh_desc {
- struct sh_dmae_regs hw;
- struct list_head node;
- struct dma_async_tx_descriptor async_tx;
- enum dma_data_direction direction;
- dma_cookie_t cookie;
- int chunks;
- int mark;
-};
+#define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */
struct device;
@@ -47,14 +33,18 @@ struct sh_dmae_chan {
struct tasklet_struct tasklet; /* Tasklet */
int descs_allocated; /* desc count */
int xmit_shift; /* log_2(bytes_per_xfer) */
+ int irq;
int id; /* Raw id of this channel */
+ u32 __iomem *base;
char dev_id[16]; /* unique name per DMAC of channel */
};
struct sh_dmae_device {
struct dma_device common;
- struct sh_dmae_chan *chan[MAX_DMA_CHANNELS];
- struct sh_dmae_pdata pdata;
+ struct sh_dmae_chan *chan[SH_DMAC_MAX_CHANNELS];
+ struct sh_dmae_pdata *pdata;
+ u32 __iomem *chan_reg;
+ u16 __iomem *dmars;
};
#define to_sh_chan(chan) container_of(chan, struct sh_dmae_chan, common)
diff --git a/drivers/edac/edac_device_sysfs.c b/drivers/edac/edac_device_sysfs.c
index 53764577035..5fdedbc0f54 100644
--- a/drivers/edac/edac_device_sysfs.c
+++ b/drivers/edac/edac_device_sysfs.c
@@ -137,7 +137,7 @@ static ssize_t edac_dev_ctl_info_store(struct kobject *kobj,
}
/* edac_dev file operations for an 'ctl_info' */
-static struct sysfs_ops device_ctl_info_ops = {
+static const struct sysfs_ops device_ctl_info_ops = {
.show = edac_dev_ctl_info_show,
.store = edac_dev_ctl_info_store
};
@@ -373,7 +373,7 @@ static ssize_t edac_dev_instance_store(struct kobject *kobj,
}
/* edac_dev file operations for an 'instance' */
-static struct sysfs_ops device_instance_ops = {
+static const struct sysfs_ops device_instance_ops = {
.show = edac_dev_instance_show,
.store = edac_dev_instance_store
};
@@ -476,7 +476,7 @@ static ssize_t edac_dev_block_store(struct kobject *kobj,
}
/* edac_dev file operations for a 'block' */
-static struct sysfs_ops device_block_ops = {
+static const struct sysfs_ops device_block_ops = {
.show = edac_dev_block_show,
.store = edac_dev_block_store
};
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index e1d4ce08348..88840e9fa3e 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -245,7 +245,7 @@ static ssize_t csrowdev_store(struct kobject *kobj, struct attribute *attr,
return -EIO;
}
-static struct sysfs_ops csrowfs_ops = {
+static const struct sysfs_ops csrowfs_ops = {
.show = csrowdev_show,
.store = csrowdev_store
};
@@ -575,7 +575,7 @@ static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr,
}
/* Intermediate show/store table */
-static struct sysfs_ops mci_ops = {
+static const struct sysfs_ops mci_ops = {
.show = mcidev_show,
.store = mcidev_store
};
diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c
index fb60a877d76..bef94e3d994 100644
--- a/drivers/edac/edac_pci_sysfs.c
+++ b/drivers/edac/edac_pci_sysfs.c
@@ -121,7 +121,7 @@ static ssize_t edac_pci_instance_store(struct kobject *kobj,
}
/* fs_ops table */
-static struct sysfs_ops pci_instance_ops = {
+static const struct sysfs_ops pci_instance_ops = {
.show = edac_pci_instance_show,
.store = edac_pci_instance_store
};
@@ -261,7 +261,7 @@ static ssize_t edac_pci_dev_store(struct kobject *kobj,
return -EIO;
}
-static struct sysfs_ops edac_pci_sysfs_ops = {
+static const struct sysfs_ops edac_pci_sysfs_ops = {
.show = edac_pci_dev_show,
.store = edac_pci_dev_store
};
diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c
index 66958b3f10b..806c77bfd43 100644
--- a/drivers/eisa/eisa-bus.c
+++ b/drivers/eisa/eisa-bus.c
@@ -39,10 +39,10 @@ static unsigned int enable_dev_count;
static int disable_dev[EISA_MAX_FORCED_DEV];
static unsigned int disable_dev_count;
-static int is_forced_dev (int *forced_tab,
- int forced_count,
- struct eisa_root_device *root,
- struct eisa_device *edev)
+static int is_forced_dev(int *forced_tab,
+ int forced_count,
+ struct eisa_root_device *root,
+ struct eisa_device *edev)
{
int i, x;
@@ -55,21 +55,21 @@ static int is_forced_dev (int *forced_tab,
return 0;
}
-static void __init eisa_name_device (struct eisa_device *edev)
+static void __init eisa_name_device(struct eisa_device *edev)
{
#ifdef CONFIG_EISA_NAMES
int i;
for (i = 0; i < EISA_INFOS; i++) {
- if (!strcmp (edev->id.sig, eisa_table[i].id.sig)) {
- strlcpy (edev->pretty_name,
- eisa_table[i].name,
- sizeof(edev->pretty_name));
+ if (!strcmp(edev->id.sig, eisa_table[i].id.sig)) {
+ strlcpy(edev->pretty_name,
+ eisa_table[i].name,
+ sizeof(edev->pretty_name));
return;
}
}
/* No name was found */
- sprintf (edev->pretty_name, "EISA device %.7s", edev->id.sig);
+ sprintf(edev->pretty_name, "EISA device %.7s", edev->id.sig);
#endif
}
@@ -91,7 +91,7 @@ static char __init *decode_eisa_sig(unsigned long addr)
*/
outb(0x80 + i, addr);
#endif
- sig[i] = inb (addr + i);
+ sig[i] = inb(addr + i);
if (!i && (sig[0] & 0x80))
return NULL;
@@ -106,17 +106,17 @@ static char __init *decode_eisa_sig(unsigned long addr)
return sig_str;
}
-static int eisa_bus_match (struct device *dev, struct device_driver *drv)
+static int eisa_bus_match(struct device *dev, struct device_driver *drv)
{
- struct eisa_device *edev = to_eisa_device (dev);
- struct eisa_driver *edrv = to_eisa_driver (drv);
+ struct eisa_device *edev = to_eisa_device(dev);
+ struct eisa_driver *edrv = to_eisa_driver(drv);
const struct eisa_device_id *eids = edrv->id_table;
if (!eids)
return 0;
- while (strlen (eids->sig)) {
- if (!strcmp (eids->sig, edev->id.sig) &&
+ while (strlen(eids->sig)) {
+ if (!strcmp(eids->sig, edev->id.sig) &&
edev->state & EISA_CONFIG_ENABLED) {
edev->id.driver_data = eids->driver_data;
return 1;
@@ -141,61 +141,71 @@ struct bus_type eisa_bus_type = {
.match = eisa_bus_match,
.uevent = eisa_bus_uevent,
};
+EXPORT_SYMBOL(eisa_bus_type);
-int eisa_driver_register (struct eisa_driver *edrv)
+int eisa_driver_register(struct eisa_driver *edrv)
{
edrv->driver.bus = &eisa_bus_type;
- return driver_register (&edrv->driver);
+ return driver_register(&edrv->driver);
}
+EXPORT_SYMBOL(eisa_driver_register);
-void eisa_driver_unregister (struct eisa_driver *edrv)
+void eisa_driver_unregister(struct eisa_driver *edrv)
{
- driver_unregister (&edrv->driver);
+ driver_unregister(&edrv->driver);
}
+EXPORT_SYMBOL(eisa_driver_unregister);
-static ssize_t eisa_show_sig (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t eisa_show_sig(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
- struct eisa_device *edev = to_eisa_device (dev);
- return sprintf (buf,"%s\n", edev->id.sig);
+ struct eisa_device *edev = to_eisa_device(dev);
+ return sprintf(buf, "%s\n", edev->id.sig);
}
static DEVICE_ATTR(signature, S_IRUGO, eisa_show_sig, NULL);
-static ssize_t eisa_show_state (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t eisa_show_state(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
- struct eisa_device *edev = to_eisa_device (dev);
- return sprintf (buf,"%d\n", edev->state & EISA_CONFIG_ENABLED);
+ struct eisa_device *edev = to_eisa_device(dev);
+ return sprintf(buf, "%d\n", edev->state & EISA_CONFIG_ENABLED);
}
static DEVICE_ATTR(enabled, S_IRUGO, eisa_show_state, NULL);
-static ssize_t eisa_show_modalias (struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t eisa_show_modalias(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
{
- struct eisa_device *edev = to_eisa_device (dev);
- return sprintf (buf, EISA_DEVICE_MODALIAS_FMT "\n", edev->id.sig);
+ struct eisa_device *edev = to_eisa_device(dev);
+ return sprintf(buf, EISA_DEVICE_MODALIAS_FMT "\n", edev->id.sig);
}
static DEVICE_ATTR(modalias, S_IRUGO, eisa_show_modalias, NULL);
-static int __init eisa_init_device (struct eisa_root_device *root,
- struct eisa_device *edev,
- int slot)
+static int __init eisa_init_device(struct eisa_root_device *root,
+ struct eisa_device *edev,
+ int slot)
{
char *sig;
- unsigned long sig_addr;
+ unsigned long sig_addr;
int i;
- sig_addr = SLOT_ADDRESS (root, slot) + EISA_VENDOR_ID_OFFSET;
+ sig_addr = SLOT_ADDRESS(root, slot) + EISA_VENDOR_ID_OFFSET;
- if (!(sig = decode_eisa_sig (sig_addr)))
+ sig = decode_eisa_sig(sig_addr);
+ if (!sig)
return -1; /* No EISA device here */
- memcpy (edev->id.sig, sig, EISA_SIG_LEN);
+ memcpy(edev->id.sig, sig, EISA_SIG_LEN);
edev->slot = slot;
- edev->state = inb (SLOT_ADDRESS (root, slot) + EISA_CONFIG_OFFSET) & EISA_CONFIG_ENABLED;
- edev->base_addr = SLOT_ADDRESS (root, slot);
+ edev->state = inb(SLOT_ADDRESS(root, slot) + EISA_CONFIG_OFFSET)
+ & EISA_CONFIG_ENABLED;
+ edev->base_addr = SLOT_ADDRESS(root, slot);
edev->dma_mask = root->dma_mask; /* Default DMA mask */
- eisa_name_device (edev);
+ eisa_name_device(edev);
edev->dev.parent = root->dev;
edev->dev.bus = &eisa_bus_type;
edev->dev.dma_mask = &edev->dma_mask;
@@ -210,42 +220,45 @@ static int __init eisa_init_device (struct eisa_root_device *root,
#endif
}
- if (is_forced_dev (enable_dev, enable_dev_count, root, edev))
+ if (is_forced_dev(enable_dev, enable_dev_count, root, edev))
edev->state = EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED;
- if (is_forced_dev (disable_dev, disable_dev_count, root, edev))
+ if (is_forced_dev(disable_dev, disable_dev_count, root, edev))
edev->state = EISA_CONFIG_FORCED;
return 0;
}
-static int __init eisa_register_device (struct eisa_device *edev)
+static int __init eisa_register_device(struct eisa_device *edev)
{
- int rc = device_register (&edev->dev);
+ int rc = device_register(&edev->dev);
if (rc)
return rc;
- rc = device_create_file (&edev->dev, &dev_attr_signature);
- if (rc) goto err_devreg;
- rc = device_create_file (&edev->dev, &dev_attr_enabled);
- if (rc) goto err_sig;
- rc = device_create_file (&edev->dev, &dev_attr_modalias);
- if (rc) goto err_enab;
+ rc = device_create_file(&edev->dev, &dev_attr_signature);
+ if (rc)
+ goto err_devreg;
+ rc = device_create_file(&edev->dev, &dev_attr_enabled);
+ if (rc)
+ goto err_sig;
+ rc = device_create_file(&edev->dev, &dev_attr_modalias);
+ if (rc)
+ goto err_enab;
return 0;
err_enab:
- device_remove_file (&edev->dev, &dev_attr_enabled);
+ device_remove_file(&edev->dev, &dev_attr_enabled);
err_sig:
- device_remove_file (&edev->dev, &dev_attr_signature);
+ device_remove_file(&edev->dev, &dev_attr_signature);
err_devreg:
device_unregister(&edev->dev);
return rc;
}
-static int __init eisa_request_resources (struct eisa_root_device *root,
- struct eisa_device *edev,
- int slot)
+static int __init eisa_request_resources(struct eisa_root_device *root,
+ struct eisa_device *edev,
+ int slot)
{
int i;
@@ -263,17 +276,19 @@ static int __init eisa_request_resources (struct eisa_root_device *root,
if (slot) {
edev->res[i].name = NULL;
- edev->res[i].start = SLOT_ADDRESS (root, slot) + (i * 0x400);
+ edev->res[i].start = SLOT_ADDRESS(root, slot)
+ + (i * 0x400);
edev->res[i].end = edev->res[i].start + 0xff;
edev->res[i].flags = IORESOURCE_IO;
} else {
edev->res[i].name = NULL;
- edev->res[i].start = SLOT_ADDRESS (root, slot) + EISA_VENDOR_ID_OFFSET;
+ edev->res[i].start = SLOT_ADDRESS(root, slot)
+ + EISA_VENDOR_ID_OFFSET;
edev->res[i].end = edev->res[i].start + 3;
edev->res[i].flags = IORESOURCE_BUSY;
}
- if (request_resource (root->res, &edev->res[i]))
+ if (request_resource(root->res, &edev->res[i]))
goto failed;
}
@@ -281,99 +296,100 @@ static int __init eisa_request_resources (struct eisa_root_device *root,
failed:
while (--i >= 0)
- release_resource (&edev->res[i]);
+ release_resource(&edev->res[i]);
return -1;
}
-static void __init eisa_release_resources (struct eisa_device *edev)
+static void __init eisa_release_resources(struct eisa_device *edev)
{
int i;
for (i = 0; i < EISA_MAX_RESOURCES; i++)
if (edev->res[i].start || edev->res[i].end)
- release_resource (&edev->res[i]);
+ release_resource(&edev->res[i]);
}
-static int __init eisa_probe (struct eisa_root_device *root)
+static int __init eisa_probe(struct eisa_root_device *root)
{
int i, c;
struct eisa_device *edev;
- printk (KERN_INFO "EISA: Probing bus %d at %s\n",
- root->bus_nr, dev_name(root->dev));
+ printk(KERN_INFO "EISA: Probing bus %d at %s\n",
+ root->bus_nr, dev_name(root->dev));
/* First try to get hold of slot 0. If there is no device
* here, simply fail, unless root->force_probe is set. */
- if (!(edev = kzalloc (sizeof (*edev), GFP_KERNEL))) {
- printk (KERN_ERR "EISA: Couldn't allocate mainboard slot\n");
+ edev = kzalloc(sizeof(*edev), GFP_KERNEL);
+ if (!edev) {
+ printk(KERN_ERR "EISA: Couldn't allocate mainboard slot\n");
return -ENOMEM;
}
- if (eisa_request_resources (root, edev, 0)) {
- printk (KERN_WARNING \
- "EISA: Cannot allocate resource for mainboard\n");
- kfree (edev);
+ if (eisa_request_resources(root, edev, 0)) {
+ printk(KERN_WARNING \
+ "EISA: Cannot allocate resource for mainboard\n");
+ kfree(edev);
if (!root->force_probe)
return -EBUSY;
goto force_probe;
}
- if (eisa_init_device (root, edev, 0)) {
- eisa_release_resources (edev);
- kfree (edev);
+ if (eisa_init_device(root, edev, 0)) {
+ eisa_release_resources(edev);
+ kfree(edev);
if (!root->force_probe)
return -ENODEV;
goto force_probe;
}
- printk (KERN_INFO "EISA: Mainboard %s detected.\n", edev->id.sig);
+ printk(KERN_INFO "EISA: Mainboard %s detected.\n", edev->id.sig);
- if (eisa_register_device (edev)) {
- printk (KERN_ERR "EISA: Failed to register %s\n",
- edev->id.sig);
- eisa_release_resources (edev);
- kfree (edev);
+ if (eisa_register_device(edev)) {
+ printk(KERN_ERR "EISA: Failed to register %s\n",
+ edev->id.sig);
+ eisa_release_resources(edev);
+ kfree(edev);
}
force_probe:
for (c = 0, i = 1; i <= root->slots; i++) {
- if (!(edev = kzalloc (sizeof (*edev), GFP_KERNEL))) {
- printk (KERN_ERR "EISA: Out of memory for slot %d\n",
- i);
+ edev = kzalloc(sizeof(*edev), GFP_KERNEL);
+ if (!edev) {
+ printk(KERN_ERR "EISA: Out of memory for slot %d\n", i);
continue;
}
- if (eisa_request_resources (root, edev, i)) {
- printk (KERN_WARNING \
- "Cannot allocate resource for EISA slot %d\n",
- i);
- kfree (edev);
+ if (eisa_request_resources(root, edev, i)) {
+ printk(KERN_WARNING \
+ "Cannot allocate resource for EISA slot %d\n",
+ i);
+ kfree(edev);
continue;
}
- if (eisa_init_device (root, edev, i)) {
- eisa_release_resources (edev);
- kfree (edev);
+ if (eisa_init_device(root, edev, i)) {
+ eisa_release_resources(edev);
+ kfree(edev);
continue;
}
- printk (KERN_INFO "EISA: slot %d : %s detected",
- i, edev->id.sig);
+ printk(KERN_INFO "EISA: slot %d : %s detected",
+ i, edev->id.sig);
switch (edev->state) {
case EISA_CONFIG_ENABLED | EISA_CONFIG_FORCED:
- printk (" (forced enabled)");
+ printk(" (forced enabled)");
break;
case EISA_CONFIG_FORCED:
- printk (" (forced disabled)");
+ printk(" (forced disabled)");
break;
case 0:
- printk (" (disabled)");
+ printk(" (disabled)");
break;
}
@@ -381,15 +397,15 @@ static int __init eisa_probe (struct eisa_root_device *root)
c++;
- if (eisa_register_device (edev)) {
- printk (KERN_ERR "EISA: Failed to register %s\n",
- edev->id.sig);
- eisa_release_resources (edev);
- kfree (edev);
+ if (eisa_register_device(edev)) {
+ printk(KERN_ERR "EISA: Failed to register %s\n",
+ edev->id.sig);
+ eisa_release_resources(edev);
+ kfree(edev);
}
}
- printk (KERN_INFO "EISA: Detected %d card%s.\n", c, c == 1 ? "" : "s");
+ printk(KERN_INFO "EISA: Detected %d card%s.\n", c, c == 1 ? "" : "s");
return 0;
}
@@ -403,7 +419,7 @@ static struct resource eisa_root_res = {
static int eisa_bus_count;
-int __init eisa_root_register (struct eisa_root_device *root)
+int __init eisa_root_register(struct eisa_root_device *root)
{
int err;
@@ -417,35 +433,35 @@ int __init eisa_root_register (struct eisa_root_device *root)
root->eisa_root_res.end = root->res->end;
root->eisa_root_res.flags = IORESOURCE_BUSY;
- if ((err = request_resource (&eisa_root_res, &root->eisa_root_res)))
+ err = request_resource(&eisa_root_res, &root->eisa_root_res);
+ if (err)
return err;
root->bus_nr = eisa_bus_count++;
- if ((err = eisa_probe (root)))
- release_resource (&root->eisa_root_res);
+ err = eisa_probe(root);
+ if (err)
+ release_resource(&root->eisa_root_res);
return err;
}
-static int __init eisa_init (void)
+static int __init eisa_init(void)
{
int r;
- if ((r = bus_register (&eisa_bus_type)))
+ r = bus_register(&eisa_bus_type);
+ if (r)
return r;
- printk (KERN_INFO "EISA bus registered\n");
+ printk(KERN_INFO "EISA bus registered\n");
return 0;
}
module_param_array(enable_dev, int, &enable_dev_count, 0444);
module_param_array(disable_dev, int, &disable_dev_count, 0444);
-postcore_initcall (eisa_init);
+postcore_initcall(eisa_init);
int EISA_bus; /* for legacy drivers */
-EXPORT_SYMBOL (EISA_bus);
-EXPORT_SYMBOL (eisa_bus_type);
-EXPORT_SYMBOL (eisa_driver_register);
-EXPORT_SYMBOL (eisa_driver_unregister);
+EXPORT_SYMBOL(EISA_bus);
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c
index 014cabd3afd..5db0518c66d 100644
--- a/drivers/firewire/core-device.c
+++ b/drivers/firewire/core-device.c
@@ -33,7 +33,6 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/rwsem.h>
-#include <linux/semaphore.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/workqueue.h>
@@ -828,9 +827,9 @@ static int update_unit(struct device *dev, void *data)
struct fw_driver *driver = (struct fw_driver *)dev->driver;
if (is_fw_unit(dev) && driver != NULL && driver->update != NULL) {
- down(&dev->sem);
+ device_lock(dev);
driver->update(unit);
- up(&dev->sem);
+ device_unlock(dev);
}
return 0;
diff --git a/drivers/firmware/edd.c b/drivers/firmware/edd.c
index 9e4f59dc7f1..110e24e5088 100644
--- a/drivers/firmware/edd.c
+++ b/drivers/firmware/edd.c
@@ -122,7 +122,7 @@ edd_attr_show(struct kobject * kobj, struct attribute *attr, char *buf)
return ret;
}
-static struct sysfs_ops edd_attr_ops = {
+static const struct sysfs_ops edd_attr_ops = {
.show = edd_attr_show,
};
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index f4f709d1370..082f06ecd32 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -362,7 +362,7 @@ static ssize_t efivar_attr_store(struct kobject *kobj, struct attribute *attr,
return ret;
}
-static struct sysfs_ops efivar_attr_ops = {
+static const struct sysfs_ops efivar_attr_ops = {
.show = efivar_attr_show,
.store = efivar_attr_store,
};
diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c
index a3600e3ed0f..ed2801c378d 100644
--- a/drivers/firmware/iscsi_ibft.c
+++ b/drivers/firmware/iscsi_ibft.c
@@ -519,7 +519,7 @@ static ssize_t ibft_show_attribute(struct kobject *kobj,
return ret;
}
-static struct sysfs_ops ibft_attr_ops = {
+static const struct sysfs_ops ibft_attr_ops = {
.show = ibft_show_attribute,
};
diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c
index 56f9234781f..d59f7cad226 100644
--- a/drivers/firmware/memmap.c
+++ b/drivers/firmware/memmap.c
@@ -74,7 +74,7 @@ static struct attribute *def_attrs[] = {
NULL
};
-static struct sysfs_ops memmap_attr_ops = {
+static const struct sysfs_ops memmap_attr_ops = {
.show = memmap_attr_show,
};
@@ -122,29 +122,53 @@ static int firmware_map_add_entry(u64 start, u64 end,
return 0;
}
+/*
+ * Add memmap entry on sysfs
+ */
+static int add_sysfs_fw_map_entry(struct firmware_map_entry *entry)
+{
+ static int map_entries_nr;
+ static struct kset *mmap_kset;
+
+ if (!mmap_kset) {
+ mmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj);
+ if (!mmap_kset)
+ return -ENOMEM;
+ }
+
+ entry->kobj.kset = mmap_kset;
+ if (kobject_add(&entry->kobj, NULL, "%d", map_entries_nr++))
+ kobject_put(&entry->kobj);
+
+ return 0;
+}
+
/**
- * firmware_map_add() - Adds a firmware mapping entry.
+ * firmware_map_add_hotplug() - Adds a firmware mapping entry when we do
+ * memory hotplug.
* @start: Start of the memory range.
* @end: End of the memory range (inclusive).
* @type: Type of the memory range.
*
- * This function uses kmalloc() for memory
- * allocation. Use firmware_map_add_early() if you want to use the bootmem
- * allocator.
- *
- * That function must be called before late_initcall.
+ * Adds a firmware mapping entry. This function is for memory hotplug, it is
+ * similar to function firmware_map_add_early(). The only difference is that
+ * it will create the syfs entry dynamically.
*
* Returns 0 on success, or -ENOMEM if no memory could be allocated.
**/
-int firmware_map_add(u64 start, u64 end, const char *type)
+int __meminit firmware_map_add_hotplug(u64 start, u64 end, const char *type)
{
struct firmware_map_entry *entry;
- entry = kmalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC);
+ entry = kzalloc(sizeof(struct firmware_map_entry), GFP_ATOMIC);
if (!entry)
return -ENOMEM;
- return firmware_map_add_entry(start, end, type, entry);
+ firmware_map_add_entry(start, end, type, entry);
+ /* create the memmap entry */
+ add_sysfs_fw_map_entry(entry);
+
+ return 0;
}
/**
@@ -154,7 +178,7 @@ int firmware_map_add(u64 start, u64 end, const char *type)
* @type: Type of the memory range.
*
* Adds a firmware mapping entry. This function uses the bootmem allocator
- * for memory allocation. Use firmware_map_add() if you want to use kmalloc().
+ * for memory allocation.
*
* That function must be called before late_initcall.
*
@@ -214,19 +238,10 @@ static ssize_t memmap_attr_show(struct kobject *kobj,
*/
static int __init memmap_init(void)
{
- int i = 0;
struct firmware_map_entry *entry;
- struct kset *memmap_kset;
-
- memmap_kset = kset_create_and_add("memmap", NULL, firmware_kobj);
- if (WARN_ON(!memmap_kset))
- return -ENOMEM;
- list_for_each_entry(entry, &map_entries, list) {
- entry->kobj.kset = memmap_kset;
- if (kobject_add(&entry->kobj, NULL, "%d", i++))
- kobject_put(&entry->kobj);
- }
+ list_for_each_entry(entry, &map_entries, list)
+ add_sysfs_fw_map_entry(entry);
return 0;
}
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 1f1d88ae68d..fee678f74a1 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -65,8 +65,17 @@ config GPIO_SYSFS
# put expanders in the right section, in alphabetical order
+config GPIO_MAX730X
+ tristate
+
comment "Memory mapped GPIO expanders:"
+config GPIO_IT8761E
+ tristate "IT8761E GPIO support"
+ depends on GPIOLIB
+ help
+ Say yes here to support GPIO functionality of IT8761E super I/O chip.
+
config GPIO_PL061
bool "PrimeCell PL061 GPIO support"
depends on ARM_AMBA
@@ -85,8 +94,32 @@ config GPIO_VR41XX
help
Say yes here to support the NEC VR4100 series General-purpose I/O Uint
+config GPIO_SCH
+ tristate "Intel SCH GPIO"
+ depends on GPIOLIB && PCI
+ select MFD_CORE
+ select LPC_SCH
+ help
+ Say yes here to support GPIO interface on Intel Poulsbo SCH.
+ The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are
+ powered by the core power rail and are turned off during sleep
+ modes (S3 and higher). The remaining four GPIOs are powered by
+ the Intel SCH suspend power supply. These GPIOs remain
+ active during S3. The suspend powered GPIOs can be used to wake the
+ system from the Suspend-to-RAM state.
+
+ This driver can also be built as a module. If so, the module
+ will be called sch-gpio.
+
comment "I2C GPIO expanders:"
+config GPIO_MAX7300
+ tristate "Maxim MAX7300 GPIO expander"
+ depends on I2C
+ select GPIO_MAX730X
+ help
+ GPIO driver for Maxim MAX7301 I2C-based GPIO expander.
+
config GPIO_MAX732X
tristate "MAX7319, MAX7320-7327 I2C Port Expanders"
depends on I2C
@@ -124,6 +157,13 @@ config GPIO_PCA953X
This driver can also be built as a module. If so, the module
will be called pca953x.
+config GPIO_PCA953X_IRQ
+ bool "Interrupt controller support for PCA953x"
+ depends on GPIO_PCA953X=y
+ help
+ Say yes here to enable the pca953x to be used as an interrupt
+ controller. It requires the driver to be built in the kernel.
+
config GPIO_PCF857X
tristate "PCF857x, PCA{85,96}7x, and MAX732[89] I2C GPIO expanders"
depends on I2C
@@ -162,6 +202,20 @@ config GPIO_WM831X
Say yes here to access the GPIO signals of WM831x power management
chips from Wolfson Microelectronics.
+config GPIO_WM8350
+ tristate "WM8350 GPIOs"
+ depends on MFD_WM8350
+ help
+ Say yes here to access the GPIO signals of WM8350 power management
+ chips from Wolfson Microelectronics.
+
+config GPIO_WM8994
+ tristate "WM8994 GPIOs"
+ depends on MFD_WM8994
+ help
+ Say yes here to access the GPIO signals of WM8994 audio hub
+ CODECs from Wolfson Microelectronics.
+
config GPIO_ADP5520
tristate "GPIO Support for ADP5520 PMIC"
depends on PMIC_ADP5520
@@ -226,8 +280,9 @@ comment "SPI GPIO expanders:"
config GPIO_MAX7301
tristate "Maxim MAX7301 GPIO expander"
depends on SPI_MASTER
+ select GPIO_MAX730X
help
- gpio driver for Maxim MAX7301 SPI GPIO expander.
+ GPIO driver for Maxim MAX7301 SPI-based GPIO expander.
config GPIO_MCP23S08
tristate "Microchip MCP23S08 I/O expander"
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 48687238edb..10f3f8d958b 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -7,6 +7,8 @@ obj-$(CONFIG_GPIOLIB) += gpiolib.o
obj-$(CONFIG_GPIO_ADP5520) += adp5520-gpio.o
obj-$(CONFIG_GPIO_ADP5588) += adp5588-gpio.o
obj-$(CONFIG_GPIO_LANGWELL) += langwell_gpio.o
+obj-$(CONFIG_GPIO_MAX730X) += max730x.o
+obj-$(CONFIG_GPIO_MAX7300) += max7300.o
obj-$(CONFIG_GPIO_MAX7301) += max7301.o
obj-$(CONFIG_GPIO_MAX732X) += max732x.o
obj-$(CONFIG_GPIO_MC33880) += mc33880.o
@@ -20,5 +22,9 @@ obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o
obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o
obj-$(CONFIG_GPIO_CS5535) += cs5535-gpio.o
obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o
+obj-$(CONFIG_GPIO_IT8761E) += it8761e_gpio.o
obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o
+obj-$(CONFIG_GPIO_WM8350) += wm8350-gpiolib.o
+obj-$(CONFIG_GPIO_WM8994) += wm8994-gpio.o
+obj-$(CONFIG_GPIO_SCH) += sch_gpio.o \ No newline at end of file
diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c
index 0fdbe94f24a..0c3c498f226 100644
--- a/drivers/gpio/cs5535-gpio.c
+++ b/drivers/gpio/cs5535-gpio.c
@@ -154,7 +154,7 @@ static int chip_gpio_request(struct gpio_chip *c, unsigned offset)
static int chip_gpio_get(struct gpio_chip *chip, unsigned offset)
{
- return cs5535_gpio_isset(offset, GPIO_OUTPUT_VAL);
+ return cs5535_gpio_isset(offset, GPIO_READ_BACK);
}
static void chip_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
@@ -172,6 +172,7 @@ static int chip_direction_input(struct gpio_chip *c, unsigned offset)
spin_lock_irqsave(&chip->lock, flags);
__cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
+ __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_ENABLE);
spin_unlock_irqrestore(&chip->lock, flags);
return 0;
@@ -184,6 +185,7 @@ static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val)
spin_lock_irqsave(&chip->lock, flags);
+ __cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE);
__cs5535_gpio_set(chip, offset, GPIO_OUTPUT_ENABLE);
if (val)
__cs5535_gpio_set(chip, offset, GPIO_OUTPUT_VAL);
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 350842ad363..6d1b86661e6 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -623,7 +623,9 @@ static const struct attribute_group gpiochip_attr_group = {
* /sys/class/gpio/unexport ... write-only
* integer N ... number of GPIO to unexport
*/
-static ssize_t export_store(struct class *class, const char *buf, size_t len)
+static ssize_t export_store(struct class *class,
+ struct class_attribute *attr,
+ const char *buf, size_t len)
{
long gpio;
int status;
@@ -653,7 +655,9 @@ done:
return status ? : len;
}
-static ssize_t unexport_store(struct class *class, const char *buf, size_t len)
+static ssize_t unexport_store(struct class *class,
+ struct class_attribute *attr,
+ const char *buf, size_t len)
{
long gpio;
int status;
@@ -1237,6 +1241,64 @@ void gpio_free(unsigned gpio)
}
EXPORT_SYMBOL_GPL(gpio_free);
+/**
+ * gpio_request_one - request a single GPIO with initial configuration
+ * @gpio: the GPIO number
+ * @flags: GPIO configuration as specified by GPIOF_*
+ * @label: a literal description string of this GPIO
+ */
+int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
+{
+ int err;
+
+ err = gpio_request(gpio, label);
+ if (err)
+ return err;
+
+ if (flags & GPIOF_DIR_IN)
+ err = gpio_direction_input(gpio);
+ else
+ err = gpio_direction_output(gpio,
+ (flags & GPIOF_INIT_HIGH) ? 1 : 0);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(gpio_request_one);
+
+/**
+ * gpio_request_array - request multiple GPIOs in a single call
+ * @array: array of the 'struct gpio'
+ * @num: how many GPIOs in the array
+ */
+int gpio_request_array(struct gpio *array, size_t num)
+{
+ int i, err;
+
+ for (i = 0; i < num; i++, array++) {
+ err = gpio_request_one(array->gpio, array->flags, array->label);
+ if (err)
+ goto err_free;
+ }
+ return 0;
+
+err_free:
+ while (i--)
+ gpio_free((--array)->gpio);
+ return err;
+}
+EXPORT_SYMBOL_GPL(gpio_request_array);
+
+/**
+ * gpio_free_array - release multiple GPIOs in a single call
+ * @array: array of the 'struct gpio'
+ * @num: how many GPIOs in the array
+ */
+void gpio_free_array(struct gpio *array, size_t num)
+{
+ while (num--)
+ gpio_free((array++)->gpio);
+}
+EXPORT_SYMBOL_GPL(gpio_free_array);
/**
* gpiochip_is_requested - return string iff signal was requested
diff --git a/drivers/gpio/it8761e_gpio.c b/drivers/gpio/it8761e_gpio.c
new file mode 100644
index 00000000000..753219cf993
--- /dev/null
+++ b/drivers/gpio/it8761e_gpio.c
@@ -0,0 +1,231 @@
+/*
+ * it8761_gpio.c - GPIO interface for IT8761E Super I/O chip
+ *
+ * Author: Denis Turischev <denis@compulab.co.il>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+
+#include <linux/gpio.h>
+
+#define SIO_CHIP_ID 0x8761
+#define CHIP_ID_HIGH_BYTE 0x20
+#define CHIP_ID_LOW_BYTE 0x21
+
+static u8 ports[2] = { 0x2e, 0x4e };
+static u8 port;
+
+static DEFINE_SPINLOCK(sio_lock);
+
+#define GPIO_NAME "it8761-gpio"
+#define GPIO_BA_HIGH_BYTE 0x60
+#define GPIO_BA_LOW_BYTE 0x61
+#define GPIO_IOSIZE 4
+#define GPIO1X_IO 0xf0
+#define GPIO2X_IO 0xf1
+
+static u16 gpio_ba;
+
+static u8 read_reg(u8 addr, u8 port)
+{
+ outb(addr, port);
+ return inb(port + 1);
+}
+
+static void write_reg(u8 data, u8 addr, u8 port)
+{
+ outb(addr, port);
+ outb(data, port + 1);
+}
+
+static void enter_conf_mode(u8 port)
+{
+ outb(0x87, port);
+ outb(0x61, port);
+ outb(0x55, port);
+ outb((port == 0x2e) ? 0x55 : 0xaa, port);
+}
+
+static void exit_conf_mode(u8 port)
+{
+ outb(0x2, port);
+ outb(0x2, port + 1);
+}
+
+static void enter_gpio_mode(u8 port)
+{
+ write_reg(0x2, 0x7, port);
+}
+
+static int it8761e_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
+{
+ u16 reg;
+ u8 bit;
+
+ bit = gpio_num % 7;
+ reg = (gpio_num >= 7) ? gpio_ba + 1 : gpio_ba;
+
+ return !!(inb(reg) & (1 << bit));
+}
+
+static int it8761e_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num)
+{
+ u8 curr_dirs;
+ u8 io_reg, bit;
+
+ bit = gpio_num % 7;
+ io_reg = (gpio_num >= 7) ? GPIO2X_IO : GPIO1X_IO;
+
+ spin_lock(&sio_lock);
+
+ enter_conf_mode(port);
+ enter_gpio_mode(port);
+
+ curr_dirs = read_reg(io_reg, port);
+
+ if (curr_dirs & (1 << bit))
+ write_reg(curr_dirs & ~(1 << bit), io_reg, port);
+
+ exit_conf_mode(port);
+
+ spin_unlock(&sio_lock);
+ return 0;
+}
+
+static void it8761e_gpio_set(struct gpio_chip *gc,
+ unsigned gpio_num, int val)
+{
+ u8 curr_vals, bit;
+ u16 reg;
+
+ bit = gpio_num % 7;
+ reg = (gpio_num >= 7) ? gpio_ba + 1 : gpio_ba;
+
+ spin_lock(&sio_lock);
+
+ curr_vals = inb(reg);
+ if (val)
+ outb(curr_vals | (1 << bit) , reg);
+ else
+ outb(curr_vals & ~(1 << bit), reg);
+
+ spin_unlock(&sio_lock);
+}
+
+static int it8761e_gpio_direction_out(struct gpio_chip *gc,
+ unsigned gpio_num, int val)
+{
+ u8 curr_dirs, io_reg, bit;
+
+ bit = gpio_num % 7;
+ io_reg = (gpio_num >= 7) ? GPIO2X_IO : GPIO1X_IO;
+
+ it8761e_gpio_set(gc, gpio_num, val);
+
+ spin_lock(&sio_lock);
+
+ enter_conf_mode(port);
+ enter_gpio_mode(port);
+
+ curr_dirs = read_reg(io_reg, port);
+
+ if (!(curr_dirs & (1 << bit)))
+ write_reg(curr_dirs | (1 << bit), io_reg, port);
+
+ exit_conf_mode(port);
+
+ spin_unlock(&sio_lock);
+ return 0;
+}
+
+static struct gpio_chip it8761e_gpio_chip = {
+ .label = GPIO_NAME,
+ .owner = THIS_MODULE,
+ .get = it8761e_gpio_get,
+ .direction_input = it8761e_gpio_direction_in,
+ .set = it8761e_gpio_set,
+ .direction_output = it8761e_gpio_direction_out,
+};
+
+static int __init it8761e_gpio_init(void)
+{
+ int i, id, err;
+
+ /* chip and port detection */
+ for (i = 0; i < ARRAY_SIZE(ports); i++) {
+ spin_lock(&sio_lock);
+ enter_conf_mode(ports[i]);
+
+ id = (read_reg(CHIP_ID_HIGH_BYTE, ports[i]) << 8) +
+ read_reg(CHIP_ID_LOW_BYTE, ports[i]);
+
+ exit_conf_mode(ports[i]);
+ spin_unlock(&sio_lock);
+
+ if (id == SIO_CHIP_ID) {
+ port = ports[i];
+ break;
+ }
+ }
+
+ if (!port)
+ return -ENODEV;
+
+ /* fetch GPIO base address */
+ enter_conf_mode(port);
+ enter_gpio_mode(port);
+ gpio_ba = (read_reg(GPIO_BA_HIGH_BYTE, port) << 8) +
+ read_reg(GPIO_BA_LOW_BYTE, port);
+ exit_conf_mode(port);
+
+ if (!request_region(gpio_ba, GPIO_IOSIZE, GPIO_NAME))
+ return -EBUSY;
+
+ it8761e_gpio_chip.base = -1;
+ it8761e_gpio_chip.ngpio = 14;
+
+ err = gpiochip_add(&it8761e_gpio_chip);
+ if (err < 0)
+ goto gpiochip_add_err;
+
+ return 0;
+
+gpiochip_add_err:
+ release_region(gpio_ba, GPIO_IOSIZE);
+ gpio_ba = 0;
+ return err;
+}
+
+static void __exit it8761e_gpio_exit(void)
+{
+ if (gpio_ba) {
+ gpiochip_remove(&it8761e_gpio_chip);
+
+ release_region(gpio_ba, GPIO_IOSIZE);
+ gpio_ba = 0;
+ }
+}
+module_init(it8761e_gpio_init);
+module_exit(it8761e_gpio_exit);
+
+MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
+MODULE_DESCRIPTION("GPIO interface for IT8761E Super I/O chip");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpio/max7300.c b/drivers/gpio/max7300.c
new file mode 100644
index 00000000000..9d74eef1157
--- /dev/null
+++ b/drivers/gpio/max7300.c
@@ -0,0 +1,94 @@
+/*
+ * drivers/gpio/max7300.c
+ *
+ * Copyright (C) 2009 Wolfram Sang, Pengutronix
+ *
+ * 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.
+ *
+ * Check max730x.c for further details.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include <linux/spi/max7301.h>
+
+static int max7300_i2c_write(struct device *dev, unsigned int reg,
+ unsigned int val)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+
+ return i2c_smbus_write_byte_data(client, reg, val);
+}
+
+static int max7300_i2c_read(struct device *dev, unsigned int reg)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+
+ return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int __devinit max7300_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct max7301 *ts;
+ int ret;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_BYTE_DATA))
+ return -EIO;
+
+ ts = kzalloc(sizeof(struct max7301), GFP_KERNEL);
+ if (!ts)
+ return -ENOMEM;
+
+ ts->read = max7300_i2c_read;
+ ts->write = max7300_i2c_write;
+ ts->dev = &client->dev;
+
+ ret = __max730x_probe(ts);
+ if (ret)
+ kfree(ts);
+ return ret;
+}
+
+static int __devexit max7300_remove(struct i2c_client *client)
+{
+ return __max730x_remove(&client->dev);
+}
+
+static const struct i2c_device_id max7300_id[] = {
+ { "max7300", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, max7300_id);
+
+static struct i2c_driver max7300_driver = {
+ .driver = {
+ .name = "max7300",
+ .owner = THIS_MODULE,
+ },
+ .probe = max7300_probe,
+ .remove = __devexit_p(max7300_remove),
+ .id_table = max7300_id,
+};
+
+static int __init max7300_init(void)
+{
+ return i2c_add_driver(&max7300_driver);
+}
+subsys_initcall(max7300_init);
+
+static void __exit max7300_exit(void)
+{
+ i2c_del_driver(&max7300_driver);
+}
+module_exit(max7300_exit);
+
+MODULE_AUTHOR("Wolfram Sang");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MAX7300 GPIO-Expander");
diff --git a/drivers/gpio/max7301.c b/drivers/gpio/max7301.c
index 480956f1ca5..965d9b1ea13 100644
--- a/drivers/gpio/max7301.c
+++ b/drivers/gpio/max7301.c
@@ -1,98 +1,41 @@
-/**
+/*
* drivers/gpio/max7301.c
*
* Copyright (C) 2006 Juergen Beisert, Pengutronix
* Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
+ * Copyright (C) 2009 Wolfram Sang, Pengutronix
*
* 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.
*
- * The Maxim's MAX7301 device is an SPI driven GPIO expander. There are
- * 28 GPIOs. 8 of them can trigger an interrupt. See datasheet for more
- * details
- * Note:
- * - DIN must be stable at the rising edge of clock.
- * - when writing:
- * - always clock in 16 clocks at once
- * - at DIN: D15 first, D0 last
- * - D0..D7 = databyte, D8..D14 = commandbyte
- * - D15 = low -> write command
- * - when reading
- * - always clock in 16 clocks at once
- * - at DIN: D15 first, D0 last
- * - D0..D7 = dummy, D8..D14 = register address
- * - D15 = high -> read command
- * - raise CS and assert it again
- * - always clock in 16 clocks at once
- * - at DOUT: D15 first, D0 last
- * - D0..D7 contains the data from the first cycle
- *
- * The driver exports a standard gpiochip interface
+ * Check max730x.c for further details.
*/
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
#include <linux/spi/spi.h>
#include <linux/spi/max7301.h>
-#include <linux/gpio.h>
-
-#define DRIVER_NAME "max7301"
-
-/*
- * Pin configurations, see MAX7301 datasheet page 6
- */
-#define PIN_CONFIG_MASK 0x03
-#define PIN_CONFIG_IN_PULLUP 0x03
-#define PIN_CONFIG_IN_WO_PULLUP 0x02
-#define PIN_CONFIG_OUT 0x01
-
-#define PIN_NUMBER 28
-
-
-/*
- * Some registers must be read back to modify.
- * To save time we cache them here in memory
- */
-struct max7301 {
- struct mutex lock;
- u8 port_config[8]; /* field 0 is unused */
- u32 out_level; /* cached output levels */
- struct gpio_chip chip;
- struct spi_device *spi;
-};
-/**
- * max7301_write - Write a new register content
- * @spi: The SPI device
- * @reg: Register offset
- * @val: Value to write
- *
- * A write to the MAX7301 means one message with one transfer
- *
- * Returns 0 if successful or a negative value on error
- */
-static int max7301_write(struct spi_device *spi, unsigned int reg, unsigned int val)
+/* A write to the MAX7301 means one message with one transfer */
+static int max7301_spi_write(struct device *dev, unsigned int reg,
+ unsigned int val)
{
+ struct spi_device *spi = to_spi_device(dev);
u16 word = ((reg & 0x7F) << 8) | (val & 0xFF);
+
return spi_write(spi, (const u8 *)&word, sizeof(word));
}
-/**
- * max7301_read - Read back register content
- * @spi: The SPI device
- * @reg: Register offset
- *
- * A read from the MAX7301 means two transfers; here, one message each
- *
- * Returns positive 8 bit value from device if successful or a
- * negative value on error
- */
-static int max7301_read(struct spi_device *spi, unsigned int reg)
+/* A read from the MAX7301 means two transfers; here, one message each */
+
+static int max7301_spi_read(struct device *dev, unsigned int reg)
{
int ret;
u16 word;
+ struct spi_device *spi = to_spi_device(dev);
word = 0x8000 | (reg << 8);
ret = spi_write(spi, (const u8 *)&word, sizeof(word));
@@ -108,125 +51,13 @@ static int max7301_read(struct spi_device *spi, unsigned int reg)
return word & 0xff;
}
-static int max7301_direction_input(struct gpio_chip *chip, unsigned offset)
-{
- struct max7301 *ts = container_of(chip, struct max7301, chip);
- u8 *config;
- int ret;
-
- /* First 4 pins are unused in the controller */
- offset += 4;
-
- config = &ts->port_config[offset >> 2];
-
- mutex_lock(&ts->lock);
-
- /* Standard GPIO API doesn't support pull-ups, has to be extended.
- * Hard-coding no pollup for now. */
- *config = (*config & ~(3 << (offset & 3))) | (1 << (offset & 3));
-
- ret = max7301_write(ts->spi, 0x08 + (offset >> 2), *config);
-
- mutex_unlock(&ts->lock);
-
- return ret;
-}
-
-static int __max7301_set(struct max7301 *ts, unsigned offset, int value)
-{
- if (value) {
- ts->out_level |= 1 << offset;
- return max7301_write(ts->spi, 0x20 + offset, 0x01);
- } else {
- ts->out_level &= ~(1 << offset);
- return max7301_write(ts->spi, 0x20 + offset, 0x00);
- }
-}
-
-static int max7301_direction_output(struct gpio_chip *chip, unsigned offset,
- int value)
-{
- struct max7301 *ts = container_of(chip, struct max7301, chip);
- u8 *config;
- int ret;
-
- /* First 4 pins are unused in the controller */
- offset += 4;
-
- config = &ts->port_config[offset >> 2];
-
- mutex_lock(&ts->lock);
-
- *config = (*config & ~(3 << (offset & 3))) | (1 << (offset & 3));
-
- ret = __max7301_set(ts, offset, value);
-
- if (!ret)
- ret = max7301_write(ts->spi, 0x08 + (offset >> 2), *config);
-
- mutex_unlock(&ts->lock);
-
- return ret;
-}
-
-static int max7301_get(struct gpio_chip *chip, unsigned offset)
-{
- struct max7301 *ts = container_of(chip, struct max7301, chip);
- int config, level = -EINVAL;
-
- /* First 4 pins are unused in the controller */
- offset += 4;
-
- mutex_lock(&ts->lock);
-
- config = (ts->port_config[offset >> 2] >> ((offset & 3) * 2)) & 3;
-
- switch (config) {
- case 1:
- /* Output: return cached level */
- level = !!(ts->out_level & (1 << offset));
- break;
- case 2:
- case 3:
- /* Input: read out */
- level = max7301_read(ts->spi, 0x20 + offset) & 0x01;
- }
- mutex_unlock(&ts->lock);
-
- return level;
-}
-
-static void max7301_set(struct gpio_chip *chip, unsigned offset, int value)
-{
- struct max7301 *ts = container_of(chip, struct max7301, chip);
-
- /* First 4 pins are unused in the controller */
- offset += 4;
-
- mutex_lock(&ts->lock);
-
- __max7301_set(ts, offset, value);
-
- mutex_unlock(&ts->lock);
-}
-
static int __devinit max7301_probe(struct spi_device *spi)
{
struct max7301 *ts;
- struct max7301_platform_data *pdata;
- int i, ret;
-
- pdata = spi->dev.platform_data;
- if (!pdata || !pdata->base) {
- dev_dbg(&spi->dev, "incorrect or missing platform data\n");
- return -EINVAL;
- }
+ int ret;
- /*
- * bits_per_word cannot be configured in platform data
- */
+ /* bits_per_word cannot be configured in platform data */
spi->bits_per_word = 16;
-
ret = spi_setup(spi);
if (ret < 0)
return ret;
@@ -235,90 +66,35 @@ static int __devinit max7301_probe(struct spi_device *spi)
if (!ts)
return -ENOMEM;
- mutex_init(&ts->lock);
-
- dev_set_drvdata(&spi->dev, ts);
+ ts->read = max7301_spi_read;
+ ts->write = max7301_spi_write;
+ ts->dev = &spi->dev;
- /* Power up the chip and disable IRQ output */
- max7301_write(spi, 0x04, 0x01);
-
- ts->spi = spi;
-
- ts->chip.label = DRIVER_NAME,
-
- ts->chip.direction_input = max7301_direction_input;
- ts->chip.get = max7301_get;
- ts->chip.direction_output = max7301_direction_output;
- ts->chip.set = max7301_set;
-
- ts->chip.base = pdata->base;
- ts->chip.ngpio = PIN_NUMBER;
- ts->chip.can_sleep = 1;
- ts->chip.dev = &spi->dev;
- ts->chip.owner = THIS_MODULE;
-
- /*
- * tristate all pins in hardware and cache the
- * register values for later use.
- */
- for (i = 1; i < 8; i++) {
- int j;
- /* 0xAA means input with internal pullup disabled */
- max7301_write(spi, 0x08 + i, 0xAA);
- ts->port_config[i] = 0xAA;
- for (j = 0; j < 4; j++) {
- int offset = (i - 1) * 4 + j;
- ret = max7301_direction_input(&ts->chip, offset);
- if (ret)
- goto exit_destroy;
- }
- }
-
- ret = gpiochip_add(&ts->chip);
+ ret = __max730x_probe(ts);
if (ret)
- goto exit_destroy;
-
- return ret;
-
-exit_destroy:
- dev_set_drvdata(&spi->dev, NULL);
- mutex_destroy(&ts->lock);
- kfree(ts);
+ kfree(ts);
return ret;
}
static int __devexit max7301_remove(struct spi_device *spi)
{
- struct max7301 *ts;
- int ret;
-
- ts = dev_get_drvdata(&spi->dev);
- if (ts == NULL)
- return -ENODEV;
-
- dev_set_drvdata(&spi->dev, NULL);
-
- /* Power down the chip and disable IRQ output */
- max7301_write(spi, 0x04, 0x00);
-
- ret = gpiochip_remove(&ts->chip);
- if (!ret) {
- mutex_destroy(&ts->lock);
- kfree(ts);
- } else
- dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n",
- ret);
-
- return ret;
+ return __max730x_remove(&spi->dev);
}
+static const struct spi_device_id max7301_id[] = {
+ { "max7301", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, max7301_id);
+
static struct spi_driver max7301_driver = {
.driver = {
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
+ .name = "max7301",
+ .owner = THIS_MODULE,
},
- .probe = max7301_probe,
- .remove = __devexit_p(max7301_remove),
+ .probe = max7301_probe,
+ .remove = __devexit_p(max7301_remove),
+ .id_table = max7301_id,
};
static int __init max7301_init(void)
@@ -336,7 +112,6 @@ static void __exit max7301_exit(void)
}
module_exit(max7301_exit);
-MODULE_AUTHOR("Juergen Beisert");
+MODULE_AUTHOR("Juergen Beisert, Wolfram Sang");
MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("MAX7301 SPI based GPIO-Expander");
-MODULE_ALIAS("spi:" DRIVER_NAME);
+MODULE_DESCRIPTION("MAX7301 GPIO-Expander");
diff --git a/drivers/gpio/max730x.c b/drivers/gpio/max730x.c
new file mode 100644
index 00000000000..c9bced55f82
--- /dev/null
+++ b/drivers/gpio/max730x.c
@@ -0,0 +1,244 @@
+/**
+ * drivers/gpio/max7301.c
+ *
+ * Copyright (C) 2006 Juergen Beisert, Pengutronix
+ * Copyright (C) 2008 Guennadi Liakhovetski, Pengutronix
+ * Copyright (C) 2009 Wolfram Sang, Pengutronix
+ *
+ * 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.
+ *
+ * The Maxim MAX7300/1 device is an I2C/SPI driven GPIO expander. There are
+ * 28 GPIOs. 8 of them can trigger an interrupt. See datasheet for more
+ * details
+ * Note:
+ * - DIN must be stable at the rising edge of clock.
+ * - when writing:
+ * - always clock in 16 clocks at once
+ * - at DIN: D15 first, D0 last
+ * - D0..D7 = databyte, D8..D14 = commandbyte
+ * - D15 = low -> write command
+ * - when reading
+ * - always clock in 16 clocks at once
+ * - at DIN: D15 first, D0 last
+ * - D0..D7 = dummy, D8..D14 = register address
+ * - D15 = high -> read command
+ * - raise CS and assert it again
+ * - always clock in 16 clocks at once
+ * - at DOUT: D15 first, D0 last
+ * - D0..D7 contains the data from the first cycle
+ *
+ * The driver exports a standard gpiochip interface
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/spi/max7301.h>
+#include <linux/gpio.h>
+
+/*
+ * Pin configurations, see MAX7301 datasheet page 6
+ */
+#define PIN_CONFIG_MASK 0x03
+#define PIN_CONFIG_IN_PULLUP 0x03
+#define PIN_CONFIG_IN_WO_PULLUP 0x02
+#define PIN_CONFIG_OUT 0x01
+
+#define PIN_NUMBER 28
+
+static int max7301_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+ struct max7301 *ts = container_of(chip, struct max7301, chip);
+ u8 *config;
+ u8 offset_bits;
+ int ret;
+
+ /* First 4 pins are unused in the controller */
+ offset += 4;
+ offset_bits = (offset & 3) << 1;
+
+ config = &ts->port_config[offset >> 2];
+
+ mutex_lock(&ts->lock);
+
+ /* Standard GPIO API doesn't support pull-ups, has to be extended.
+ * Hard-coding no pollup for now. */
+ *config = (*config & ~(PIN_CONFIG_MASK << offset_bits))
+ | (PIN_CONFIG_IN_WO_PULLUP << offset_bits);
+
+ ret = ts->write(ts->dev, 0x08 + (offset >> 2), *config);
+
+ mutex_unlock(&ts->lock);
+
+ return ret;
+}
+
+static int __max7301_set(struct max7301 *ts, unsigned offset, int value)
+{
+ if (value) {
+ ts->out_level |= 1 << offset;
+ return ts->write(ts->dev, 0x20 + offset, 0x01);
+ } else {
+ ts->out_level &= ~(1 << offset);
+ return ts->write(ts->dev, 0x20 + offset, 0x00);
+ }
+}
+
+static int max7301_direction_output(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ struct max7301 *ts = container_of(chip, struct max7301, chip);
+ u8 *config;
+ u8 offset_bits;
+ int ret;
+
+ /* First 4 pins are unused in the controller */
+ offset += 4;
+ offset_bits = (offset & 3) << 1;
+
+ config = &ts->port_config[offset >> 2];
+
+ mutex_lock(&ts->lock);
+
+ *config = (*config & ~(PIN_CONFIG_MASK << offset_bits))
+ | (PIN_CONFIG_OUT << offset_bits);
+
+ ret = __max7301_set(ts, offset, value);
+
+ if (!ret)
+ ret = ts->write(ts->dev, 0x08 + (offset >> 2), *config);
+
+ mutex_unlock(&ts->lock);
+
+ return ret;
+}
+
+static int max7301_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct max7301 *ts = container_of(chip, struct max7301, chip);
+ int config, level = -EINVAL;
+
+ /* First 4 pins are unused in the controller */
+ offset += 4;
+
+ mutex_lock(&ts->lock);
+
+ config = (ts->port_config[offset >> 2] >> ((offset & 3) << 1))
+ & PIN_CONFIG_MASK;
+
+ switch (config) {
+ case PIN_CONFIG_OUT:
+ /* Output: return cached level */
+ level = !!(ts->out_level & (1 << offset));
+ break;
+ case PIN_CONFIG_IN_WO_PULLUP:
+ case PIN_CONFIG_IN_PULLUP:
+ /* Input: read out */
+ level = ts->read(ts->dev, 0x20 + offset) & 0x01;
+ }
+ mutex_unlock(&ts->lock);
+
+ return level;
+}
+
+static void max7301_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct max7301 *ts = container_of(chip, struct max7301, chip);
+
+ /* First 4 pins are unused in the controller */
+ offset += 4;
+
+ mutex_lock(&ts->lock);
+
+ __max7301_set(ts, offset, value);
+
+ mutex_unlock(&ts->lock);
+}
+
+int __devinit __max730x_probe(struct max7301 *ts)
+{
+ struct device *dev = ts->dev;
+ struct max7301_platform_data *pdata;
+ int i, ret;
+
+ pdata = dev->platform_data;
+ if (!pdata || !pdata->base) {
+ dev_err(dev, "incorrect or missing platform data\n");
+ return -EINVAL;
+ }
+
+ mutex_init(&ts->lock);
+ dev_set_drvdata(dev, ts);
+
+ /* Power up the chip and disable IRQ output */
+ ts->write(dev, 0x04, 0x01);
+
+ ts->chip.label = dev->driver->name;
+
+ ts->chip.direction_input = max7301_direction_input;
+ ts->chip.get = max7301_get;
+ ts->chip.direction_output = max7301_direction_output;
+ ts->chip.set = max7301_set;
+
+ ts->chip.base = pdata->base;
+ ts->chip.ngpio = PIN_NUMBER;
+ ts->chip.can_sleep = 1;
+ ts->chip.dev = dev;
+ ts->chip.owner = THIS_MODULE;
+
+ /*
+ * tristate all pins in hardware and cache the
+ * register values for later use.
+ */
+ for (i = 1; i < 8; i++) {
+ int j;
+ /* 0xAA means input with internal pullup disabled */
+ ts->write(dev, 0x08 + i, 0xAA);
+ ts->port_config[i] = 0xAA;
+ for (j = 0; j < 4; j++) {
+ int offset = (i - 1) * 4 + j;
+ ret = max7301_direction_input(&ts->chip, offset);
+ if (ret)
+ goto exit_destroy;
+ }
+ }
+
+ ret = gpiochip_add(&ts->chip);
+ if (ret)
+ goto exit_destroy;
+
+ return ret;
+
+exit_destroy:
+ dev_set_drvdata(dev, NULL);
+ mutex_destroy(&ts->lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(__max730x_probe);
+
+int __devexit __max730x_remove(struct device *dev)
+{
+ struct max7301 *ts = dev_get_drvdata(dev);
+ int ret;
+
+ if (ts == NULL)
+ return -ENODEV;
+
+ dev_set_drvdata(dev, NULL);
+
+ /* Power down the chip and disable IRQ output */
+ ts->write(dev, 0x04, 0x00);
+
+ ret = gpiochip_remove(&ts->chip);
+ if (!ret) {
+ mutex_destroy(&ts->lock);
+ kfree(ts);
+ } else
+ dev_err(dev, "Failed to remove GPIO controller: %d\n", ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(__max730x_remove);
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c
index 6a2fb3fbb3d..ab5daab14bc 100644
--- a/drivers/gpio/pca953x.c
+++ b/drivers/gpio/pca953x.c
@@ -14,6 +14,8 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/i2c.h>
#include <linux/i2c/pca953x.h>
#ifdef CONFIG_OF_GPIO
@@ -26,23 +28,28 @@
#define PCA953X_INVERT 2
#define PCA953X_DIRECTION 3
+#define PCA953X_GPIOS 0x00FF
+#define PCA953X_INT 0x0100
+
static const struct i2c_device_id pca953x_id[] = {
- { "pca9534", 8, },
- { "pca9535", 16, },
+ { "pca9534", 8 | PCA953X_INT, },
+ { "pca9535", 16 | PCA953X_INT, },
{ "pca9536", 4, },
- { "pca9537", 4, },
- { "pca9538", 8, },
- { "pca9539", 16, },
- { "pca9554", 8, },
- { "pca9555", 16, },
+ { "pca9537", 4 | PCA953X_INT, },
+ { "pca9538", 8 | PCA953X_INT, },
+ { "pca9539", 16 | PCA953X_INT, },
+ { "pca9554", 8 | PCA953X_INT, },
+ { "pca9555", 16 | PCA953X_INT, },
{ "pca9556", 8, },
{ "pca9557", 8, },
{ "max7310", 8, },
- { "max7315", 8, },
- { "pca6107", 8, },
- { "tca6408", 8, },
- { "tca6416", 16, },
+ { "max7312", 16 | PCA953X_INT, },
+ { "max7313", 16 | PCA953X_INT, },
+ { "max7315", 8 | PCA953X_INT, },
+ { "pca6107", 8 | PCA953X_INT, },
+ { "tca6408", 8 | PCA953X_INT, },
+ { "tca6416", 16 | PCA953X_INT, },
/* NYET: { "tca6424", 24, }, */
{ }
};
@@ -53,6 +60,15 @@ struct pca953x_chip {
uint16_t reg_output;
uint16_t reg_direction;
+#ifdef CONFIG_GPIO_PCA953X_IRQ
+ struct mutex irq_lock;
+ uint16_t irq_mask;
+ uint16_t irq_stat;
+ uint16_t irq_trig_raise;
+ uint16_t irq_trig_fall;
+ int irq_base;
+#endif
+
struct i2c_client *client;
struct pca953x_platform_data *dyn_pdata;
struct gpio_chip gpio_chip;
@@ -202,6 +218,210 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
gc->names = chip->names;
}
+#ifdef CONFIG_GPIO_PCA953X_IRQ
+static int pca953x_gpio_to_irq(struct gpio_chip *gc, unsigned off)
+{
+ struct pca953x_chip *chip;
+
+ chip = container_of(gc, struct pca953x_chip, gpio_chip);
+ return chip->irq_base + off;
+}
+
+static void pca953x_irq_mask(unsigned int irq)
+{
+ struct pca953x_chip *chip = get_irq_chip_data(irq);
+
+ chip->irq_mask &= ~(1 << (irq - chip->irq_base));
+}
+
+static void pca953x_irq_unmask(unsigned int irq)
+{
+ struct pca953x_chip *chip = get_irq_chip_data(irq);
+
+ chip->irq_mask |= 1 << (irq - chip->irq_base);
+}
+
+static void pca953x_irq_bus_lock(unsigned int irq)
+{
+ struct pca953x_chip *chip = get_irq_chip_data(irq);
+
+ mutex_lock(&chip->irq_lock);
+}
+
+static void pca953x_irq_bus_sync_unlock(unsigned int irq)
+{
+ struct pca953x_chip *chip = get_irq_chip_data(irq);
+
+ mutex_unlock(&chip->irq_lock);
+}
+
+static int pca953x_irq_set_type(unsigned int irq, unsigned int type)
+{
+ struct pca953x_chip *chip = get_irq_chip_data(irq);
+ uint16_t level = irq - chip->irq_base;
+ uint16_t mask = 1 << level;
+
+ if (!(type & IRQ_TYPE_EDGE_BOTH)) {
+ dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
+ irq, type);
+ return -EINVAL;
+ }
+
+ if (type & IRQ_TYPE_EDGE_FALLING)
+ chip->irq_trig_fall |= mask;
+ else
+ chip->irq_trig_fall &= ~mask;
+
+ if (type & IRQ_TYPE_EDGE_RISING)
+ chip->irq_trig_raise |= mask;
+ else
+ chip->irq_trig_raise &= ~mask;
+
+ return pca953x_gpio_direction_input(&chip->gpio_chip, level);
+}
+
+static struct irq_chip pca953x_irq_chip = {
+ .name = "pca953x",
+ .mask = pca953x_irq_mask,
+ .unmask = pca953x_irq_unmask,
+ .bus_lock = pca953x_irq_bus_lock,
+ .bus_sync_unlock = pca953x_irq_bus_sync_unlock,
+ .set_type = pca953x_irq_set_type,
+};
+
+static uint16_t pca953x_irq_pending(struct pca953x_chip *chip)
+{
+ uint16_t cur_stat;
+ uint16_t old_stat;
+ uint16_t pending;
+ uint16_t trigger;
+ int ret;
+
+ ret = pca953x_read_reg(chip, PCA953X_INPUT, &cur_stat);
+ if (ret)
+ return 0;
+
+ /* Remove output pins from the equation */
+ cur_stat &= chip->reg_direction;
+
+ old_stat = chip->irq_stat;
+ trigger = (cur_stat ^ old_stat) & chip->irq_mask;
+
+ if (!trigger)
+ return 0;
+
+ chip->irq_stat = cur_stat;
+
+ pending = (old_stat & chip->irq_trig_fall) |
+ (cur_stat & chip->irq_trig_raise);
+ pending &= trigger;
+
+ return pending;
+}
+
+static irqreturn_t pca953x_irq_handler(int irq, void *devid)
+{
+ struct pca953x_chip *chip = devid;
+ uint16_t pending;
+ uint16_t level;
+
+ pending = pca953x_irq_pending(chip);
+
+ if (!pending)
+ return IRQ_HANDLED;
+
+ do {
+ level = __ffs(pending);
+ handle_nested_irq(level + chip->irq_base);
+
+ pending &= ~(1 << level);
+ } while (pending);
+
+ return IRQ_HANDLED;
+}
+
+static int pca953x_irq_setup(struct pca953x_chip *chip,
+ const struct i2c_device_id *id)
+{
+ struct i2c_client *client = chip->client;
+ struct pca953x_platform_data *pdata = client->dev.platform_data;
+ int ret;
+
+ if (pdata->irq_base && (id->driver_data & PCA953X_INT)) {
+ int lvl;
+
+ ret = pca953x_read_reg(chip, PCA953X_INPUT,
+ &chip->irq_stat);
+ if (ret)
+ goto out_failed;
+
+ /*
+ * There is no way to know which GPIO line generated the
+ * interrupt. We have to rely on the previous read for
+ * this purpose.
+ */
+ chip->irq_stat &= chip->reg_direction;
+ chip->irq_base = pdata->irq_base;
+ mutex_init(&chip->irq_lock);
+
+ for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
+ int irq = lvl + chip->irq_base;
+
+ set_irq_chip_data(irq, chip);
+ set_irq_chip_and_handler(irq, &pca953x_irq_chip,
+ handle_edge_irq);
+ set_irq_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+ set_irq_flags(irq, IRQF_VALID);
+#else
+ set_irq_noprobe(irq);
+#endif
+ }
+
+ ret = request_threaded_irq(client->irq,
+ NULL,
+ pca953x_irq_handler,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ dev_name(&client->dev), chip);
+ if (ret) {
+ dev_err(&client->dev, "failed to request irq %d\n",
+ client->irq);
+ goto out_failed;
+ }
+
+ chip->gpio_chip.to_irq = pca953x_gpio_to_irq;
+ }
+
+ return 0;
+
+out_failed:
+ chip->irq_base = 0;
+ return ret;
+}
+
+static void pca953x_irq_teardown(struct pca953x_chip *chip)
+{
+ if (chip->irq_base)
+ free_irq(chip->client->irq, chip);
+}
+#else /* CONFIG_GPIO_PCA953X_IRQ */
+static int pca953x_irq_setup(struct pca953x_chip *chip,
+ const struct i2c_device_id *id)
+{
+ struct i2c_client *client = chip->client;
+ struct pca953x_platform_data *pdata = client->dev.platform_data;
+
+ if (pdata->irq_base && (id->driver_data & PCA953X_INT))
+ dev_warn(&client->dev, "interrupt support not compiled in\n");
+
+ return 0;
+}
+
+static void pca953x_irq_teardown(struct pca953x_chip *chip)
+{
+}
+#endif
+
/*
* Handlers for alternative sources of platform_data
*/
@@ -286,7 +506,7 @@ static int __devinit pca953x_probe(struct i2c_client *client,
/* initialize cached registers from their original values.
* we can't share this chip with another i2c master.
*/
- pca953x_setup_gpio(chip, id->driver_data);
+ pca953x_setup_gpio(chip, id->driver_data & PCA953X_GPIOS);
ret = pca953x_read_reg(chip, PCA953X_OUTPUT, &chip->reg_output);
if (ret)
@@ -301,6 +521,9 @@ static int __devinit pca953x_probe(struct i2c_client *client,
if (ret)
goto out_failed;
+ ret = pca953x_irq_setup(chip, id);
+ if (ret)
+ goto out_failed;
ret = gpiochip_add(&chip->gpio_chip);
if (ret)
@@ -317,6 +540,7 @@ static int __devinit pca953x_probe(struct i2c_client *client,
return 0;
out_failed:
+ pca953x_irq_teardown(chip);
kfree(chip->dyn_pdata);
kfree(chip);
return ret;
@@ -345,6 +569,7 @@ static int pca953x_remove(struct i2c_client *client)
return ret;
}
+ pca953x_irq_teardown(chip);
kfree(chip->dyn_pdata);
kfree(chip);
return 0;
diff --git a/drivers/gpio/pl061.c b/drivers/gpio/pl061.c
index 4ee4c8367a3..3ad1eeb4960 100644
--- a/drivers/gpio/pl061.c
+++ b/drivers/gpio/pl061.c
@@ -219,7 +219,7 @@ static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
if (pending == 0)
continue;
- for_each_bit(offset, &pending, PL061_GPIO_NR)
+ for_each_set_bit(offset, &pending, PL061_GPIO_NR)
generic_handle_irq(pl061_to_irq(&chip->gc, offset));
}
desc->chip->unmask(irq);
diff --git a/drivers/gpio/sch_gpio.c b/drivers/gpio/sch_gpio.c
new file mode 100644
index 00000000000..583521352c1
--- /dev/null
+++ b/drivers/gpio/sch_gpio.c
@@ -0,0 +1,295 @@
+/*
+ * sch_gpio.c - GPIO interface for Intel Poulsbo SCH
+ *
+ * Copyright (c) 2010 CompuLab Ltd
+ * Author: Denis Turischev <denis@compulab.co.il>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/acpi.h>
+#include <linux/platform_device.h>
+
+#include <linux/gpio.h>
+
+static DEFINE_SPINLOCK(gpio_lock);
+
+#define CGEN (0x00)
+#define CGIO (0x04)
+#define CGLV (0x08)
+
+#define RGEN (0x20)
+#define RGIO (0x24)
+#define RGLV (0x28)
+
+static unsigned short gpio_ba;
+
+static int sch_gpio_core_direction_in(struct gpio_chip *gc, unsigned gpio_num)
+{
+ u8 curr_dirs;
+ unsigned short offset, bit;
+
+ spin_lock(&gpio_lock);
+
+ offset = CGIO + gpio_num / 8;
+ bit = gpio_num % 8;
+
+ curr_dirs = inb(gpio_ba + offset);
+
+ if (!(curr_dirs & (1 << bit)))
+ outb(curr_dirs | (1 << bit), gpio_ba + offset);
+
+ spin_unlock(&gpio_lock);
+ return 0;
+}
+
+static int sch_gpio_core_get(struct gpio_chip *gc, unsigned gpio_num)
+{
+ int res;
+ unsigned short offset, bit;
+
+ offset = CGLV + gpio_num / 8;
+ bit = gpio_num % 8;
+
+ res = !!(inb(gpio_ba + offset) & (1 << bit));
+ return res;
+}
+
+static void sch_gpio_core_set(struct gpio_chip *gc, unsigned gpio_num, int val)
+{
+ u8 curr_vals;
+ unsigned short offset, bit;
+
+ spin_lock(&gpio_lock);
+
+ offset = CGLV + gpio_num / 8;
+ bit = gpio_num % 8;
+
+ curr_vals = inb(gpio_ba + offset);
+
+ if (val)
+ outb(curr_vals | (1 << bit), gpio_ba + offset);
+ else
+ outb((curr_vals & ~(1 << bit)), gpio_ba + offset);
+ spin_unlock(&gpio_lock);
+}
+
+static int sch_gpio_core_direction_out(struct gpio_chip *gc,
+ unsigned gpio_num, int val)
+{
+ u8 curr_dirs;
+ unsigned short offset, bit;
+
+ sch_gpio_core_set(gc, gpio_num, val);
+
+ spin_lock(&gpio_lock);
+
+ offset = CGIO + gpio_num / 8;
+ bit = gpio_num % 8;
+
+ curr_dirs = inb(gpio_ba + offset);
+ if (curr_dirs & (1 << bit))
+ outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
+
+ spin_unlock(&gpio_lock);
+ return 0;
+}
+
+static struct gpio_chip sch_gpio_core = {
+ .label = "sch_gpio_core",
+ .owner = THIS_MODULE,
+ .direction_input = sch_gpio_core_direction_in,
+ .get = sch_gpio_core_get,
+ .direction_output = sch_gpio_core_direction_out,
+ .set = sch_gpio_core_set,
+};
+
+static int sch_gpio_resume_direction_in(struct gpio_chip *gc,
+ unsigned gpio_num)
+{
+ u8 curr_dirs;
+
+ spin_lock(&gpio_lock);
+
+ curr_dirs = inb(gpio_ba + RGIO);
+
+ if (!(curr_dirs & (1 << gpio_num)))
+ outb(curr_dirs | (1 << gpio_num) , gpio_ba + RGIO);
+
+ spin_unlock(&gpio_lock);
+ return 0;
+}
+
+static int sch_gpio_resume_get(struct gpio_chip *gc, unsigned gpio_num)
+{
+ return !!(inb(gpio_ba + RGLV) & (1 << gpio_num));
+}
+
+static void sch_gpio_resume_set(struct gpio_chip *gc,
+ unsigned gpio_num, int val)
+{
+ u8 curr_vals;
+
+ spin_lock(&gpio_lock);
+
+ curr_vals = inb(gpio_ba + RGLV);
+
+ if (val)
+ outb(curr_vals | (1 << gpio_num), gpio_ba + RGLV);
+ else
+ outb((curr_vals & ~(1 << gpio_num)), gpio_ba + RGLV);
+
+ spin_unlock(&gpio_lock);
+}
+
+static int sch_gpio_resume_direction_out(struct gpio_chip *gc,
+ unsigned gpio_num, int val)
+{
+ u8 curr_dirs;
+
+ sch_gpio_resume_set(gc, gpio_num, val);
+
+ spin_lock(&gpio_lock);
+
+ curr_dirs = inb(gpio_ba + RGIO);
+ if (curr_dirs & (1 << gpio_num))
+ outb(curr_dirs & ~(1 << gpio_num), gpio_ba + RGIO);
+
+ spin_unlock(&gpio_lock);
+ return 0;
+}
+
+static struct gpio_chip sch_gpio_resume = {
+ .label = "sch_gpio_resume",
+ .owner = THIS_MODULE,
+ .direction_input = sch_gpio_resume_direction_in,
+ .get = sch_gpio_resume_get,
+ .direction_output = sch_gpio_resume_direction_out,
+ .set = sch_gpio_resume_set,
+};
+
+static int __devinit sch_gpio_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int err;
+
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (!res)
+ return -EBUSY;
+
+ if (!request_region(res->start, resource_size(res), pdev->name))
+ return -EBUSY;
+
+ gpio_ba = res->start;
+
+ sch_gpio_core.base = 0;
+ sch_gpio_core.ngpio = 10;
+ sch_gpio_core.dev = &pdev->dev;
+
+ sch_gpio_resume.base = 10;
+ sch_gpio_resume.ngpio = 4;
+ sch_gpio_resume.dev = &pdev->dev;
+
+ err = gpiochip_add(&sch_gpio_core);
+ if (err < 0)
+ goto err_sch_gpio_core;
+
+ err = gpiochip_add(&sch_gpio_resume);
+ if (err < 0)
+ goto err_sch_gpio_resume;
+
+ /*
+ * GPIO[6:0] enabled by default
+ * GPIO7 is configured by the CMC as SLPIOVR
+ * Enable GPIO[9:8] core powered gpios explicitly
+ */
+ outb(0x3, gpio_ba + CGEN + 1);
+ /*
+ * SUS_GPIO[2:0] enabled by default
+ * Enable SUS_GPIO3 resume powered gpio explicitly
+ */
+ outb(0x8, gpio_ba + RGEN);
+
+ return 0;
+
+err_sch_gpio_resume:
+ err = gpiochip_remove(&sch_gpio_core);
+ if (err)
+ dev_err(&pdev->dev, "%s failed, %d\n",
+ "gpiochip_remove()", err);
+
+err_sch_gpio_core:
+ release_region(res->start, resource_size(res));
+ gpio_ba = 0;
+
+ return err;
+}
+
+static int __devexit sch_gpio_remove(struct platform_device *pdev)
+{
+ struct resource *res;
+ if (gpio_ba) {
+ int err;
+
+ err = gpiochip_remove(&sch_gpio_core);
+ if (err)
+ dev_err(&pdev->dev, "%s failed, %d\n",
+ "gpiochip_remove()", err);
+ err = gpiochip_remove(&sch_gpio_resume);
+ if (err)
+ dev_err(&pdev->dev, "%s failed, %d\n",
+ "gpiochip_remove()", err);
+
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+
+ release_region(res->start, resource_size(res));
+ gpio_ba = 0;
+
+ return err;
+ }
+
+ return 0;
+}
+
+static struct platform_driver sch_gpio_driver = {
+ .driver = {
+ .name = "sch_gpio",
+ .owner = THIS_MODULE,
+ },
+ .probe = sch_gpio_probe,
+ .remove = __devexit_p(sch_gpio_remove),
+};
+
+static int __init sch_gpio_init(void)
+{
+ return platform_driver_register(&sch_gpio_driver);
+}
+
+static void __exit sch_gpio_exit(void)
+{
+ platform_driver_unregister(&sch_gpio_driver);
+}
+
+module_init(sch_gpio_init);
+module_exit(sch_gpio_exit);
+
+MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
+MODULE_DESCRIPTION("GPIO interface for Intel Poulsbo SCH");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:sch_gpio");
diff --git a/drivers/gpio/timbgpio.c b/drivers/gpio/timbgpio.c
index a4d344ba8e5..d4295fa5369 100644
--- a/drivers/gpio/timbgpio.c
+++ b/drivers/gpio/timbgpio.c
@@ -23,6 +23,7 @@
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
+#include <linux/irq.h>
#include <linux/io.h>
#include <linux/timb_gpio.h>
#include <linux/interrupt.h>
@@ -37,6 +38,8 @@
#define TGPIO_ICR 0x14
#define TGPIO_FLR 0x18
#define TGPIO_LVR 0x1c
+#define TGPIO_VER 0x20
+#define TGPIO_BFLR 0x24
struct timbgpio {
void __iomem *membase;
@@ -125,17 +128,23 @@ static int timbgpio_irq_type(unsigned irq, unsigned trigger)
struct timbgpio *tgpio = get_irq_chip_data(irq);
int offset = irq - tgpio->irq_base;
unsigned long flags;
- u32 lvr, flr;
+ u32 lvr, flr, bflr = 0;
+ u32 ver;
if (offset < 0 || offset > tgpio->gpio.ngpio)
return -EINVAL;
+ ver = ioread32(tgpio->membase + TGPIO_VER);
+
spin_lock_irqsave(&tgpio->lock, flags);
lvr = ioread32(tgpio->membase + TGPIO_LVR);
flr = ioread32(tgpio->membase + TGPIO_FLR);
+ if (ver > 2)
+ bflr = ioread32(tgpio->membase + TGPIO_BFLR);
if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
+ bflr &= ~(1 << offset);
flr &= ~(1 << offset);
if (trigger & IRQ_TYPE_LEVEL_HIGH)
lvr |= 1 << offset;
@@ -143,21 +152,27 @@ static int timbgpio_irq_type(unsigned irq, unsigned trigger)
lvr &= ~(1 << offset);
}
- if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
- return -EINVAL;
- else {
+ if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
+ if (ver < 3)
+ return -EINVAL;
+ else {
+ flr |= 1 << offset;
+ bflr |= 1 << offset;
+ }
+ } else {
+ bflr &= ~(1 << offset);
flr |= 1 << offset;
- /* opposite compared to the datasheet, but it mirrors the
- * reality
- */
if (trigger & IRQ_TYPE_EDGE_FALLING)
- lvr |= 1 << offset;
- else
lvr &= ~(1 << offset);
+ else
+ lvr |= 1 << offset;
}
iowrite32(lvr, tgpio->membase + TGPIO_LVR);
iowrite32(flr, tgpio->membase + TGPIO_FLR);
+ if (ver > 2)
+ iowrite32(bflr, tgpio->membase + TGPIO_BFLR);
+
iowrite32(1 << offset, tgpio->membase + TGPIO_ICR);
spin_unlock_irqrestore(&tgpio->lock, flags);
@@ -174,7 +189,7 @@ static void timbgpio_irq(unsigned int irq, struct irq_desc *desc)
ipr = ioread32(tgpio->membase + TGPIO_IPR);
iowrite32(ipr, tgpio->membase + TGPIO_ICR);
- for_each_bit(offset, &ipr, tgpio->gpio.ngpio)
+ for_each_set_bit(offset, &ipr, tgpio->gpio.ngpio)
generic_handle_irq(timbgpio_to_irq(&tgpio->gpio, offset));
}
diff --git a/drivers/gpio/wm831x-gpio.c b/drivers/gpio/wm831x-gpio.c
index b4468b61689..d09021f4a7d 100644
--- a/drivers/gpio/wm831x-gpio.c
+++ b/drivers/gpio/wm831x-gpio.c
@@ -38,10 +38,14 @@ static int wm831x_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
{
struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
struct wm831x *wm831x = wm831x_gpio->wm831x;
+ int val = WM831X_GPN_DIR;
+
+ if (wm831x->has_gpio_ena)
+ val |= WM831X_GPN_TRI;
return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
- WM831X_GPN_DIR | WM831X_GPN_TRI,
- WM831X_GPN_DIR);
+ WM831X_GPN_DIR | WM831X_GPN_TRI |
+ WM831X_GPN_FN_MASK, val);
}
static int wm831x_gpio_get(struct gpio_chip *chip, unsigned offset)
@@ -60,23 +64,36 @@ static int wm831x_gpio_get(struct gpio_chip *chip, unsigned offset)
return 0;
}
-static int wm831x_gpio_direction_out(struct gpio_chip *chip,
- unsigned offset, int value)
+static void wm831x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
struct wm831x *wm831x = wm831x_gpio->wm831x;
- return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
- WM831X_GPN_DIR | WM831X_GPN_TRI, 0);
+ wm831x_set_bits(wm831x, WM831X_GPIO_LEVEL, 1 << offset,
+ value << offset);
}
-static void wm831x_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+static int wm831x_gpio_direction_out(struct gpio_chip *chip,
+ unsigned offset, int value)
{
struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
struct wm831x *wm831x = wm831x_gpio->wm831x;
+ int val = 0;
+ int ret;
- wm831x_set_bits(wm831x, WM831X_GPIO_LEVEL, 1 << offset,
- value << offset);
+ if (wm831x->has_gpio_ena)
+ val |= WM831X_GPN_TRI;
+
+ ret = wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + offset,
+ WM831X_GPN_DIR | WM831X_GPN_TRI |
+ WM831X_GPN_FN_MASK, val);
+ if (ret < 0)
+ return ret;
+
+ /* Can only set GPIO state once it's in output mode */
+ wm831x_gpio_set(chip, offset, value);
+
+ return 0;
}
static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
@@ -95,7 +112,7 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{
struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
struct wm831x *wm831x = wm831x_gpio->wm831x;
- int i;
+ int i, tristated;
for (i = 0; i < chip->ngpio; i++) {
int gpio = i + chip->base;
@@ -162,15 +179,19 @@ static void wm831x_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
break;
}
+ tristated = reg & WM831X_GPN_TRI;
+ if (wm831x->has_gpio_ena)
+ tristated = !tristated;
+
seq_printf(s, " %s %s %s %s%s\n"
" %s%s (0x%4x)\n",
reg & WM831X_GPN_DIR ? "in" : "out",
wm831x_gpio_get(chip, i) ? "high" : "low",
pull,
powerdomain,
- reg & WM831X_GPN_POL ? " inverted" : "",
+ reg & WM831X_GPN_POL ? "" : " inverted",
reg & WM831X_GPN_OD ? "open-drain" : "CMOS",
- reg & WM831X_GPN_TRI ? " tristated" : "",
+ tristated ? " tristated" : "",
reg);
}
}
diff --git a/drivers/gpio/wm8350-gpiolib.c b/drivers/gpio/wm8350-gpiolib.c
new file mode 100644
index 00000000000..511840d1c7b
--- /dev/null
+++ b/drivers/gpio/wm8350-gpiolib.c
@@ -0,0 +1,181 @@
+/*
+ * wm835x-gpiolib.c -- gpiolib support for Wolfson WM835x PMICs
+ *
+ * Copyright 2009 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/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/mfd/core.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+
+#include <linux/mfd/wm8350/core.h>
+#include <linux/mfd/wm8350/gpio.h>
+
+struct wm8350_gpio_data {
+ struct wm8350 *wm8350;
+ struct gpio_chip gpio_chip;
+};
+
+static inline struct wm8350_gpio_data *to_wm8350_gpio(struct gpio_chip *chip)
+{
+ return container_of(chip, struct wm8350_gpio_data, gpio_chip);
+}
+
+static int wm8350_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+ struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
+ struct wm8350 *wm8350 = wm8350_gpio->wm8350;
+
+ return wm8350_set_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
+ 1 << offset);
+}
+
+static int wm8350_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
+ struct wm8350 *wm8350 = wm8350_gpio->wm8350;
+ int ret;
+
+ ret = wm8350_reg_read(wm8350, WM8350_GPIO_LEVEL);
+ if (ret < 0)
+ return ret;
+
+ if (ret & (1 << offset))
+ return 1;
+ else
+ return 0;
+}
+
+static void wm8350_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
+ struct wm8350 *wm8350 = wm8350_gpio->wm8350;
+
+ if (value)
+ wm8350_set_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
+ else
+ wm8350_clear_bits(wm8350, WM8350_GPIO_LEVEL, 1 << offset);
+}
+
+static int wm8350_gpio_direction_out(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
+ struct wm8350 *wm8350 = wm8350_gpio->wm8350;
+ int ret;
+
+ ret = wm8350_clear_bits(wm8350, WM8350_GPIO_CONFIGURATION_I_O,
+ 1 << offset);
+ if (ret < 0)
+ return ret;
+
+ /* Don't have an atomic direction/value setup */
+ wm8350_gpio_set(chip, offset, value);
+
+ return 0;
+}
+
+static int wm8350_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ struct wm8350_gpio_data *wm8350_gpio = to_wm8350_gpio(chip);
+ struct wm8350 *wm8350 = wm8350_gpio->wm8350;
+
+ if (!wm8350->irq_base)
+ return -EINVAL;
+
+ return wm8350->irq_base + WM8350_IRQ_GPIO(offset);
+}
+
+static struct gpio_chip template_chip = {
+ .label = "wm8350",
+ .owner = THIS_MODULE,
+ .direction_input = wm8350_gpio_direction_in,
+ .get = wm8350_gpio_get,
+ .direction_output = wm8350_gpio_direction_out,
+ .set = wm8350_gpio_set,
+ .to_irq = wm8350_gpio_to_irq,
+ .can_sleep = 1,
+};
+
+static int __devinit wm8350_gpio_probe(struct platform_device *pdev)
+{
+ struct wm8350 *wm8350 = dev_get_drvdata(pdev->dev.parent);
+ struct wm8350_platform_data *pdata = wm8350->dev->platform_data;
+ struct wm8350_gpio_data *wm8350_gpio;
+ int ret;
+
+ wm8350_gpio = kzalloc(sizeof(*wm8350_gpio), GFP_KERNEL);
+ if (wm8350_gpio == NULL)
+ return -ENOMEM;
+
+ wm8350_gpio->wm8350 = wm8350;
+ wm8350_gpio->gpio_chip = template_chip;
+ wm8350_gpio->gpio_chip.ngpio = 13;
+ wm8350_gpio->gpio_chip.dev = &pdev->dev;
+ if (pdata && pdata->gpio_base)
+ wm8350_gpio->gpio_chip.base = pdata->gpio_base;
+ else
+ wm8350_gpio->gpio_chip.base = -1;
+
+ ret = gpiochip_add(&wm8350_gpio->gpio_chip);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
+ ret);
+ goto err;
+ }
+
+ platform_set_drvdata(pdev, wm8350_gpio);
+
+ return ret;
+
+err:
+ kfree(wm8350_gpio);
+ return ret;
+}
+
+static int __devexit wm8350_gpio_remove(struct platform_device *pdev)
+{
+ struct wm8350_gpio_data *wm8350_gpio = platform_get_drvdata(pdev);
+ int ret;
+
+ ret = gpiochip_remove(&wm8350_gpio->gpio_chip);
+ if (ret == 0)
+ kfree(wm8350_gpio);
+
+ return ret;
+}
+
+static struct platform_driver wm8350_gpio_driver = {
+ .driver.name = "wm8350-gpio",
+ .driver.owner = THIS_MODULE,
+ .probe = wm8350_gpio_probe,
+ .remove = __devexit_p(wm8350_gpio_remove),
+};
+
+static int __init wm8350_gpio_init(void)
+{
+ return platform_driver_register(&wm8350_gpio_driver);
+}
+subsys_initcall(wm8350_gpio_init);
+
+static void __exit wm8350_gpio_exit(void)
+{
+ platform_driver_unregister(&wm8350_gpio_driver);
+}
+module_exit(wm8350_gpio_exit);
+
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("GPIO interface for WM8350 PMICs");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm8350-gpio");
diff --git a/drivers/gpio/wm8994-gpio.c b/drivers/gpio/wm8994-gpio.c
new file mode 100644
index 00000000000..de28b4a470e
--- /dev/null
+++ b/drivers/gpio/wm8994-gpio.c
@@ -0,0 +1,204 @@
+/*
+ * wm8994-gpio.c -- gpiolib support for Wolfson WM8994
+ *
+ * Copyright 2009 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/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/mfd/core.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+
+#include <linux/mfd/wm8994/core.h>
+#include <linux/mfd/wm8994/pdata.h>
+#include <linux/mfd/wm8994/gpio.h>
+#include <linux/mfd/wm8994/registers.h>
+
+struct wm8994_gpio {
+ struct wm8994 *wm8994;
+ struct gpio_chip gpio_chip;
+};
+
+static inline struct wm8994_gpio *to_wm8994_gpio(struct gpio_chip *chip)
+{
+ return container_of(chip, struct wm8994_gpio, gpio_chip);
+}
+
+static int wm8994_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+ struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+ struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+
+ return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
+ WM8994_GPN_DIR, WM8994_GPN_DIR);
+}
+
+static int wm8994_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+ struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+ int ret;
+
+ ret = wm8994_reg_read(wm8994, WM8994_GPIO_1 + offset);
+ if (ret < 0)
+ return ret;
+
+ if (ret & WM8994_GPN_LVL)
+ return 1;
+ else
+ return 0;
+}
+
+static int wm8994_gpio_direction_out(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+ struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+
+ return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset,
+ WM8994_GPN_DIR, 0);
+}
+
+static void wm8994_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+ struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+
+ if (value)
+ value = WM8994_GPN_LVL;
+
+ wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, WM8994_GPN_LVL, value);
+}
+
+#ifdef CONFIG_DEBUG_FS
+static void wm8994_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+ struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip);
+ struct wm8994 *wm8994 = wm8994_gpio->wm8994;
+ int i;
+
+ for (i = 0; i < chip->ngpio; i++) {
+ int gpio = i + chip->base;
+ int reg;
+ const char *label;
+
+ /* We report the GPIO even if it's not requested since
+ * we're also reporting things like alternate
+ * functions which apply even when the GPIO is not in
+ * use as a GPIO.
+ */
+ label = gpiochip_is_requested(chip, i);
+ if (!label)
+ label = "Unrequested";
+
+ seq_printf(s, " gpio-%-3d (%-20.20s) ", gpio, label);
+
+ reg = wm8994_reg_read(wm8994, WM8994_GPIO_1 + i);
+ if (reg < 0) {
+ dev_err(wm8994->dev,
+ "GPIO control %d read failed: %d\n",
+ gpio, reg);
+ seq_printf(s, "\n");
+ continue;
+ }
+
+ /* No decode yet; note that GPIO2 is special */
+ seq_printf(s, "(%x)\n", reg);
+ }
+}
+#else
+#define wm8994_gpio_dbg_show NULL
+#endif
+
+static struct gpio_chip template_chip = {
+ .label = "wm8994",
+ .owner = THIS_MODULE,
+ .direction_input = wm8994_gpio_direction_in,
+ .get = wm8994_gpio_get,
+ .direction_output = wm8994_gpio_direction_out,
+ .set = wm8994_gpio_set,
+ .dbg_show = wm8994_gpio_dbg_show,
+ .can_sleep = 1,
+};
+
+static int __devinit wm8994_gpio_probe(struct platform_device *pdev)
+{
+ struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
+ struct wm8994_pdata *pdata = wm8994->dev->platform_data;
+ struct wm8994_gpio *wm8994_gpio;
+ int ret;
+
+ wm8994_gpio = kzalloc(sizeof(*wm8994_gpio), GFP_KERNEL);
+ if (wm8994_gpio == NULL)
+ return -ENOMEM;
+
+ wm8994_gpio->wm8994 = wm8994;
+ wm8994_gpio->gpio_chip = template_chip;
+ wm8994_gpio->gpio_chip.ngpio = WM8994_GPIO_MAX;
+ wm8994_gpio->gpio_chip.dev = &pdev->dev;
+ if (pdata && pdata->gpio_base)
+ wm8994_gpio->gpio_chip.base = pdata->gpio_base;
+ else
+ wm8994_gpio->gpio_chip.base = -1;
+
+ ret = gpiochip_add(&wm8994_gpio->gpio_chip);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Could not register gpiochip, %d\n",
+ ret);
+ goto err;
+ }
+
+ platform_set_drvdata(pdev, wm8994_gpio);
+
+ return ret;
+
+err:
+ kfree(wm8994_gpio);
+ return ret;
+}
+
+static int __devexit wm8994_gpio_remove(struct platform_device *pdev)
+{
+ struct wm8994_gpio *wm8994_gpio = platform_get_drvdata(pdev);
+ int ret;
+
+ ret = gpiochip_remove(&wm8994_gpio->gpio_chip);
+ if (ret == 0)
+ kfree(wm8994_gpio);
+
+ return ret;
+}
+
+static struct platform_driver wm8994_gpio_driver = {
+ .driver.name = "wm8994-gpio",
+ .driver.owner = THIS_MODULE,
+ .probe = wm8994_gpio_probe,
+ .remove = __devexit_p(wm8994_gpio_remove),
+};
+
+static int __init wm8994_gpio_init(void)
+{
+ return platform_driver_register(&wm8994_gpio_driver);
+}
+subsys_initcall(wm8994_gpio_init);
+
+static void __exit wm8994_gpio_exit(void)
+{
+ platform_driver_unregister(&wm8994_gpio_driver);
+}
+module_exit(wm8994_gpio_exit);
+
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("GPIO interface for WM8994");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm8994-gpio");
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 7e42b7e9d43..014ce24761b 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -70,19 +70,17 @@ static int drm_class_resume(struct device *dev)
return 0;
}
-/* Display the version of drm_core. This doesn't work right in current design */
-static ssize_t version_show(struct class *dev, char *buf)
-{
- return sprintf(buf, "%s %d.%d.%d %s\n", CORE_NAME, CORE_MAJOR,
- CORE_MINOR, CORE_PATCHLEVEL, CORE_DATE);
-}
-
static char *drm_devnode(struct device *dev, mode_t *mode)
{
return kasprintf(GFP_KERNEL, "dri/%s", dev_name(dev));
}
-static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
+static CLASS_ATTR_STRING(version, S_IRUGO,
+ CORE_NAME " "
+ __stringify(CORE_MAJOR) "."
+ __stringify(CORE_MINOR) "."
+ __stringify(CORE_PATCHLEVEL) " "
+ CORE_DATE);
/**
* drm_sysfs_create - create a struct drm_sysfs_class structure
@@ -109,7 +107,7 @@ struct class *drm_sysfs_create(struct module *owner, char *name)
class->suspend = drm_class_suspend;
class->resume = drm_class_resume;
- err = class_create_file(class, &class_attr_version);
+ err = class_create_file(class, &class_attr_version.attr);
if (err)
goto err_out_class;
@@ -132,7 +130,7 @@ void drm_sysfs_destroy(void)
{
if ((drm_class == NULL) || (IS_ERR(drm_class)))
return;
- class_remove_file(drm_class, &class_attr_version);
+ class_remove_file(drm_class, &class_attr_version.attr);
class_destroy(drm_class);
}
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index c7320ce4567..89c38c49066 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -128,7 +128,7 @@ static struct attribute *ttm_bo_global_attrs[] = {
NULL
};
-static struct sysfs_ops ttm_bo_global_ops = {
+static const struct sysfs_ops ttm_bo_global_ops = {
.show = &ttm_bo_global_show
};
diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c
index f5245c02b8f..eb143e04d40 100644
--- a/drivers/gpu/drm/ttm/ttm_memory.c
+++ b/drivers/gpu/drm/ttm/ttm_memory.c
@@ -152,7 +152,7 @@ static struct attribute *ttm_mem_zone_attrs[] = {
NULL
};
-static struct sysfs_ops ttm_mem_zone_ops = {
+static const struct sysfs_ops ttm_mem_zone_ops = {
.show = &ttm_mem_zone_show,
.store = &ttm_mem_zone_store
};
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 68cf87749a4..e4595e6147b 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -170,6 +170,16 @@ config SENSORS_ADM9240
This driver can also be built as a module. If so, the module
will be called adm9240.
+config SENSORS_ADT7411
+ tristate "Analog Devices ADT7411"
+ depends on I2C && EXPERIMENTAL
+ help
+ If you say yes here you get support for the Analog Devices
+ ADT7411 voltage and temperature monitoring chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called adt7411.
+
config SENSORS_ADT7462
tristate "Analog Devices ADT7462"
depends on I2C && EXPERIMENTAL
@@ -190,20 +200,6 @@ config SENSORS_ADT7470
This driver can also be built as a module. If so, the module
will be called adt7470.
-config SENSORS_ADT7473
- tristate "Analog Devices ADT7473 (DEPRECATED)"
- depends on I2C && EXPERIMENTAL
- select SENSORS_ADT7475
- help
- If you say yes here you get support for the Analog Devices
- ADT7473 temperature monitoring chips.
-
- This driver is deprecated, you should use the adt7475 driver
- instead.
-
- This driver can also be built as a module. If so, the module
- will be called adt7473.
-
config SENSORS_ADT7475
tristate "Analog Devices ADT7473, ADT7475, ADT7476 and ADT7490"
depends on I2C && EXPERIMENTAL
@@ -216,6 +212,19 @@ config SENSORS_ADT7475
This driver can also be build as a module. If so, the module
will be called adt7475.
+config SENSORS_ASC7621
+ tristate "Andigilog aSC7621"
+ depends on HWMON && I2C
+ help
+ If you say yes here you get support for the aSC7621
+ family of SMBus sensors chip found on most Intel X48, X38, 975,
+ 965 and 945 desktop boards. Currently supported chips:
+ aSC7621
+ aSC7621a
+
+ This driver can also be built as a module. If so, the module
+ will be called asc7621.
+
config SENSORS_K8TEMP
tristate "AMD Athlon64/FX or Opteron temperature sensor"
depends on X86 && PCI && EXPERIMENTAL
@@ -563,9 +572,10 @@ config SENSORS_LM90
depends on I2C
help
If you say yes here you get support for National Semiconductor LM90,
- LM86, LM89 and LM99, Analog Devices ADM1032 and ADT7461, and Maxim
+ LM86, LM89 and LM99, Analog Devices ADM1032 and ADT7461, Maxim
MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659,
- MAX6680, MAX6681 and MAX6692 sensor chips.
+ MAX6680, MAX6681 and MAX6692, and Winbond/Nuvoton W83L771AWG/ASG
+ sensor chips.
This driver can also be built as a module. If so, the module
will be called lm90.
@@ -909,7 +919,8 @@ config SENSORS_W83793
select HWMON_VID
help
If you say yes here you get support for the Winbond W83793
- hardware monitoring chip.
+ hardware monitoring chip, including support for the integrated
+ watchdog.
This driver can also be built as a module. If so, the module
will be called w83793.
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 4bc215c0953..4aa1a3d112a 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -29,12 +29,13 @@ obj-$(CONFIG_SENSORS_ADM1029) += adm1029.o
obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o
obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o
obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o
+obj-$(CONFIG_SENSORS_ADT7411) += adt7411.o
obj-$(CONFIG_SENSORS_ADT7462) += adt7462.o
obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o
-obj-$(CONFIG_SENSORS_ADT7473) += adt7473.o
obj-$(CONFIG_SENSORS_ADT7475) += adt7475.o
obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o
obj-$(CONFIG_SENSORS_AMS) += ams/
+obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o
obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o
obj-$(CONFIG_SENSORS_DME1737) += dme1737.o
diff --git a/drivers/hwmon/adcxx.c b/drivers/hwmon/adcxx.c
index 5e9e095f113..74d9c5195e4 100644
--- a/drivers/hwmon/adcxx.c
+++ b/drivers/hwmon/adcxx.c
@@ -62,18 +62,23 @@ static ssize_t adcxx_read(struct device *dev,
struct spi_device *spi = to_spi_device(dev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct adcxx *adc = dev_get_drvdata(&spi->dev);
- u8 tx_buf[2] = { attr->index << 3 }; /* other bits are don't care */
+ u8 tx_buf[2];
u8 rx_buf[2];
int status;
- int value;
+ u32 value;
if (mutex_lock_interruptible(&adc->lock))
return -ERESTARTSYS;
- status = spi_write_then_read(spi, tx_buf, sizeof(tx_buf),
- rx_buf, sizeof(rx_buf));
+ if (adc->channels == 1) {
+ status = spi_read(spi, rx_buf, sizeof(rx_buf));
+ } else {
+ tx_buf[0] = attr->index << 3; /* other bits are don't care */
+ status = spi_write_then_read(spi, tx_buf, sizeof(tx_buf),
+ rx_buf, sizeof(rx_buf));
+ }
if (status < 0) {
- dev_warn(dev, "spi_write_then_read failed with status %d\n",
+ dev_warn(dev, "SPI synch. transfer failed with status %d\n",
status);
goto out;
}
diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c
new file mode 100644
index 00000000000..3471884e42d
--- /dev/null
+++ b/drivers/hwmon/adt7411.c
@@ -0,0 +1,366 @@
+/*
+ * Driver for the ADT7411 (I2C/SPI 8 channel 10 bit ADC & temperature-sensor)
+ *
+ * Copyright (C) 2008, 2010 Pengutronix
+ *
+ * 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.
+ *
+ * TODO: SPI, support for external temperature sensor
+ * use power-down mode for suspend?, interrupt handling?
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+#define ADT7411_REG_INT_TEMP_VDD_LSB 0x03
+#define ADT7411_REG_EXT_TEMP_AIN14_LSB 0x04
+#define ADT7411_REG_VDD_MSB 0x06
+#define ADT7411_REG_INT_TEMP_MSB 0x07
+#define ADT7411_REG_EXT_TEMP_AIN1_MSB 0x08
+
+#define ADT7411_REG_CFG1 0x18
+#define ADT7411_CFG1_START_MONITOR (1 << 0)
+
+#define ADT7411_REG_CFG2 0x19
+#define ADT7411_CFG2_DISABLE_AVG (1 << 5)
+
+#define ADT7411_REG_CFG3 0x1a
+#define ADT7411_CFG3_ADC_CLK_225 (1 << 0)
+#define ADT7411_CFG3_REF_VDD (1 << 4)
+
+#define ADT7411_REG_DEVICE_ID 0x4d
+#define ADT7411_REG_MANUFACTURER_ID 0x4e
+
+#define ADT7411_DEVICE_ID 0x2
+#define ADT7411_MANUFACTURER_ID 0x41
+
+static const unsigned short normal_i2c[] = { 0x48, 0x4a, 0x4b, I2C_CLIENT_END };
+
+struct adt7411_data {
+ struct mutex device_lock; /* for "atomic" device accesses */
+ struct mutex update_lock;
+ unsigned long next_update;
+ int vref_cached;
+ struct device *hwmon_dev;
+};
+
+/*
+ * When reading a register containing (up to 4) lsb, all associated
+ * msb-registers get locked by the hardware. After _one_ of those msb is read,
+ * _all_ are unlocked. In order to use this locking correctly, reading lsb/msb
+ * is protected here with a mutex, too.
+ */
+static int adt7411_read_10_bit(struct i2c_client *client, u8 lsb_reg,
+ u8 msb_reg, u8 lsb_shift)
+{
+ struct adt7411_data *data = i2c_get_clientdata(client);
+ int val, tmp;
+
+ mutex_lock(&data->device_lock);
+
+ val = i2c_smbus_read_byte_data(client, lsb_reg);
+ if (val < 0)
+ goto exit_unlock;
+
+ tmp = (val >> lsb_shift) & 3;
+ val = i2c_smbus_read_byte_data(client, msb_reg);
+
+ if (val >= 0)
+ val = (val << 2) | tmp;
+
+ exit_unlock:
+ mutex_unlock(&data->device_lock);
+
+ return val;
+}
+
+static int adt7411_modify_bit(struct i2c_client *client, u8 reg, u8 bit,
+ bool flag)
+{
+ struct adt7411_data *data = i2c_get_clientdata(client);
+ int ret, val;
+
+ mutex_lock(&data->device_lock);
+
+ ret = i2c_smbus_read_byte_data(client, reg);
+ if (ret < 0)
+ goto exit_unlock;
+
+ if (flag)
+ val = ret | bit;
+ else
+ val = ret & ~bit;
+
+ ret = i2c_smbus_write_byte_data(client, reg, val);
+
+ exit_unlock:
+ mutex_unlock(&data->device_lock);
+ return ret;
+}
+
+static ssize_t adt7411_show_vdd(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ int ret = adt7411_read_10_bit(client, ADT7411_REG_INT_TEMP_VDD_LSB,
+ ADT7411_REG_VDD_MSB, 2);
+
+ return ret < 0 ? ret : sprintf(buf, "%u\n", ret * 7000 / 1024);
+}
+
+static ssize_t adt7411_show_temp(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ int val = adt7411_read_10_bit(client, ADT7411_REG_INT_TEMP_VDD_LSB,
+ ADT7411_REG_INT_TEMP_MSB, 0);
+
+ if (val < 0)
+ return val;
+
+ val = val & 0x200 ? val - 0x400 : val; /* 10 bit signed */
+
+ return sprintf(buf, "%d\n", val * 250);
+}
+
+static ssize_t adt7411_show_input(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int nr = to_sensor_dev_attr(attr)->index;
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7411_data *data = i2c_get_clientdata(client);
+ int val;
+ u8 lsb_reg, lsb_shift;
+
+ mutex_lock(&data->update_lock);
+ if (time_after_eq(jiffies, data->next_update)) {
+ val = i2c_smbus_read_byte_data(client, ADT7411_REG_CFG3);
+ if (val < 0)
+ goto exit_unlock;
+
+ if (val & ADT7411_CFG3_REF_VDD) {
+ val = adt7411_read_10_bit(client,
+ ADT7411_REG_INT_TEMP_VDD_LSB,
+ ADT7411_REG_VDD_MSB, 2);
+ if (val < 0)
+ goto exit_unlock;
+
+ data->vref_cached = val * 7000 / 1024;
+ } else {
+ data->vref_cached = 2250;
+ }
+
+ data->next_update = jiffies + HZ;
+ }
+
+ lsb_reg = ADT7411_REG_EXT_TEMP_AIN14_LSB + (nr >> 2);
+ lsb_shift = 2 * (nr & 0x03);
+ val = adt7411_read_10_bit(client, lsb_reg,
+ ADT7411_REG_EXT_TEMP_AIN1_MSB + nr, lsb_shift);
+ if (val < 0)
+ goto exit_unlock;
+
+ val = sprintf(buf, "%u\n", val * data->vref_cached / 1024);
+ exit_unlock:
+ mutex_unlock(&data->update_lock);
+ return val;
+}
+
+static ssize_t adt7411_show_bit(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ int ret = i2c_smbus_read_byte_data(client, attr2->index);
+
+ return ret < 0 ? ret : sprintf(buf, "%u\n", !!(ret & attr2->nr));
+}
+
+static ssize_t adt7411_set_bit(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute_2 *s_attr2 = to_sensor_dev_attr_2(attr);
+ struct i2c_client *client = to_i2c_client(dev);
+ struct adt7411_data *data = i2c_get_clientdata(client);
+ int ret;
+ unsigned long flag;
+
+ ret = strict_strtoul(buf, 0, &flag);
+ if (ret || flag > 1)
+ return -EINVAL;
+
+ ret = adt7411_modify_bit(client, s_attr2->index, s_attr2->nr, flag);
+
+ /* force update */
+ mutex_lock(&data->update_lock);
+ data->next_update = jiffies;
+ mutex_unlock(&data->update_lock);
+
+ return ret < 0 ? ret : count;
+}
+
+#define ADT7411_BIT_ATTR(__name, __reg, __bit) \
+ SENSOR_DEVICE_ATTR_2(__name, S_IRUGO | S_IWUSR, adt7411_show_bit, \
+ adt7411_set_bit, __bit, __reg)
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, adt7411_show_temp, NULL);
+static DEVICE_ATTR(in0_input, S_IRUGO, adt7411_show_vdd, NULL);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, adt7411_show_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, adt7411_show_input, NULL, 1);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, adt7411_show_input, NULL, 2);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, adt7411_show_input, NULL, 3);
+static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, adt7411_show_input, NULL, 4);
+static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, adt7411_show_input, NULL, 5);
+static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, adt7411_show_input, NULL, 6);
+static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, adt7411_show_input, NULL, 7);
+static ADT7411_BIT_ATTR(no_average, ADT7411_REG_CFG2, ADT7411_CFG2_DISABLE_AVG);
+static ADT7411_BIT_ATTR(fast_sampling, ADT7411_REG_CFG3, ADT7411_CFG3_ADC_CLK_225);
+static ADT7411_BIT_ATTR(adc_ref_vdd, ADT7411_REG_CFG3, ADT7411_CFG3_REF_VDD);
+
+static struct attribute *adt7411_attrs[] = {
+ &dev_attr_temp1_input.attr,
+ &dev_attr_in0_input.attr,
+ &sensor_dev_attr_in1_input.dev_attr.attr,
+ &sensor_dev_attr_in2_input.dev_attr.attr,
+ &sensor_dev_attr_in3_input.dev_attr.attr,
+ &sensor_dev_attr_in4_input.dev_attr.attr,
+ &sensor_dev_attr_in5_input.dev_attr.attr,
+ &sensor_dev_attr_in6_input.dev_attr.attr,
+ &sensor_dev_attr_in7_input.dev_attr.attr,
+ &sensor_dev_attr_in8_input.dev_attr.attr,
+ &sensor_dev_attr_no_average.dev_attr.attr,
+ &sensor_dev_attr_fast_sampling.dev_attr.attr,
+ &sensor_dev_attr_adc_ref_vdd.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group adt7411_attr_grp = {
+ .attrs = adt7411_attrs,
+};
+
+static int adt7411_detect(struct i2c_client *client,
+ struct i2c_board_info *info)
+{
+ int val;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
+
+ val = i2c_smbus_read_byte_data(client, ADT7411_REG_MANUFACTURER_ID);
+ if (val < 0 || val != ADT7411_MANUFACTURER_ID) {
+ dev_dbg(&client->dev, "Wrong manufacturer ID. Got %d, "
+ "expected %d\n", val, ADT7411_MANUFACTURER_ID);
+ return -ENODEV;
+ }
+
+ val = i2c_smbus_read_byte_data(client, ADT7411_REG_DEVICE_ID);
+ if (val < 0 || val != ADT7411_DEVICE_ID) {
+ dev_dbg(&client->dev, "Wrong device ID. Got %d, "
+ "expected %d\n", val, ADT7411_DEVICE_ID);
+ return -ENODEV;
+ }
+
+ strlcpy(info->type, "adt7411", I2C_NAME_SIZE);
+
+ return 0;
+}
+
+static int __devinit adt7411_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct adt7411_data *data;
+ int ret;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->device_lock);
+ mutex_init(&data->update_lock);
+
+ ret = adt7411_modify_bit(client, ADT7411_REG_CFG1,
+ ADT7411_CFG1_START_MONITOR, 1);
+ if (ret < 0)
+ goto exit_free;
+
+ /* force update on first occasion */
+ data->next_update = jiffies;
+
+ ret = sysfs_create_group(&client->dev.kobj, &adt7411_attr_grp);
+ if (ret)
+ goto exit_free;
+
+ data->hwmon_dev = hwmon_device_register(&client->dev);
+ if (IS_ERR(data->hwmon_dev)) {
+ ret = PTR_ERR(data->hwmon_dev);
+ goto exit_remove;
+ }
+
+ dev_info(&client->dev, "successfully registered\n");
+
+ return 0;
+
+ exit_remove:
+ sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp);
+ exit_free:
+ i2c_set_clientdata(client, NULL);
+ kfree(data);
+ return ret;
+}
+
+static int __devexit adt7411_remove(struct i2c_client *client)
+{
+ struct adt7411_data *data = i2c_get_clientdata(client);
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp);
+ i2c_set_clientdata(client, NULL);
+ kfree(data);
+ return 0;
+}
+
+static const struct i2c_device_id adt7411_id[] = {
+ { "adt7411", 0 },
+ { }
+};
+
+static struct i2c_driver adt7411_driver = {
+ .driver = {
+ .name = "adt7411",
+ },
+ .probe = adt7411_probe,
+ .remove = __devexit_p(adt7411_remove),
+ .id_table = adt7411_id,
+ .detect = adt7411_detect,
+ .address_list = normal_i2c,
+ .class = I2C_CLASS_HWMON,
+};
+
+static int __init sensors_adt7411_init(void)
+{
+ return i2c_add_driver(&adt7411_driver);
+}
+module_init(sensors_adt7411_init)
+
+static void __exit sensors_adt7411_exit(void)
+{
+ i2c_del_driver(&adt7411_driver);
+}
+module_exit(sensors_adt7411_exit)
+
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de> and "
+ "Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_DESCRIPTION("ADT7411 driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/hwmon/adt7473.c b/drivers/hwmon/adt7473.c
deleted file mode 100644
index 434576f61c8..00000000000
--- a/drivers/hwmon/adt7473.c
+++ /dev/null
@@ -1,1180 +0,0 @@
-/*
- * A hwmon driver for the Analog Devices ADT7473
- * Copyright (C) 2007 IBM
- *
- * Author: Darrick J. Wong <djwong@us.ibm.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/module.h>
-#include <linux/jiffies.h>
-#include <linux/i2c.h>
-#include <linux/hwmon.h>
-#include <linux/hwmon-sysfs.h>
-#include <linux/err.h>
-#include <linux/mutex.h>
-#include <linux/delay.h>
-#include <linux/log2.h>
-
-/* Addresses to scan */
-static const unsigned short normal_i2c[] = { 0x2C, 0x2D, 0x2E, I2C_CLIENT_END };
-
-/* ADT7473 registers */
-#define ADT7473_REG_BASE_ADDR 0x20
-
-#define ADT7473_REG_VOLT_BASE_ADDR 0x21
-#define ADT7473_REG_VOLT_MIN_BASE_ADDR 0x46
-
-#define ADT7473_REG_TEMP_BASE_ADDR 0x25
-#define ADT7473_REG_TEMP_LIMITS_BASE_ADDR 0x4E
-#define ADT7473_REG_TEMP_TMIN_BASE_ADDR 0x67
-#define ADT7473_REG_TEMP_TMAX_BASE_ADDR 0x6A
-
-#define ADT7473_REG_FAN_BASE_ADDR 0x28
-#define ADT7473_REG_FAN_MIN_BASE_ADDR 0x54
-
-#define ADT7473_REG_PWM_BASE_ADDR 0x30
-#define ADT7473_REG_PWM_MIN_BASE_ADDR 0x64
-#define ADT7473_REG_PWM_MAX_BASE_ADDR 0x38
-#define ADT7473_REG_PWM_BHVR_BASE_ADDR 0x5C
-#define ADT7473_PWM_BHVR_MASK 0xE0
-#define ADT7473_PWM_BHVR_SHIFT 5
-
-#define ADT7473_REG_CFG1 0x40
-#define ADT7473_CFG1_START 0x01
-#define ADT7473_CFG1_READY 0x04
-#define ADT7473_REG_CFG2 0x73
-#define ADT7473_REG_CFG3 0x78
-#define ADT7473_REG_CFG4 0x7D
-#define ADT7473_CFG4_MAX_DUTY_AT_OVT 0x08
-#define ADT7473_REG_CFG5 0x7C
-#define ADT7473_CFG5_TEMP_TWOS 0x01
-#define ADT7473_CFG5_TEMP_OFFSET 0x02
-
-#define ADT7473_REG_DEVICE 0x3D
-#define ADT7473_VENDOR 0x41
-#define ADT7473_REG_VENDOR 0x3E
-#define ADT7473_DEVICE 0x73
-#define ADT7473_REG_REVISION 0x3F
-#define ADT7473_REV_68 0x68
-#define ADT7473_REV_69 0x69
-
-#define ADT7473_REG_ALARM1 0x41
-#define ADT7473_VCCP_ALARM 0x02
-#define ADT7473_VCC_ALARM 0x04
-#define ADT7473_R1T_ALARM 0x10
-#define ADT7473_LT_ALARM 0x20
-#define ADT7473_R2T_ALARM 0x40
-#define ADT7473_OOL 0x80
-#define ADT7473_REG_ALARM2 0x42
-#define ADT7473_OVT_ALARM 0x02
-#define ADT7473_FAN1_ALARM 0x04
-#define ADT7473_FAN2_ALARM 0x08
-#define ADT7473_FAN3_ALARM 0x10
-#define ADT7473_FAN4_ALARM 0x20
-#define ADT7473_R1T_SHORT 0x40
-#define ADT7473_R2T_SHORT 0x80
-
-#define ALARM2(x) ((x) << 8)
-
-#define ADT7473_VOLT_COUNT 2
-#define ADT7473_REG_VOLT(x) (ADT7473_REG_VOLT_BASE_ADDR + (x))
-#define ADT7473_REG_VOLT_MIN(x) (ADT7473_REG_VOLT_MIN_BASE_ADDR + ((x) * 2))
-#define ADT7473_REG_VOLT_MAX(x) (ADT7473_REG_VOLT_MIN_BASE_ADDR + \
- ((x) * 2) + 1)
-
-#define ADT7473_TEMP_COUNT 3
-#define ADT7473_REG_TEMP(x) (ADT7473_REG_TEMP_BASE_ADDR + (x))
-#define ADT7473_REG_TEMP_MIN(x) (ADT7473_REG_TEMP_LIMITS_BASE_ADDR + ((x) * 2))
-#define ADT7473_REG_TEMP_MAX(x) (ADT7473_REG_TEMP_LIMITS_BASE_ADDR + \
- ((x) * 2) + 1)
-#define ADT7473_REG_TEMP_TMIN(x) (ADT7473_REG_TEMP_TMIN_BASE_ADDR + (x))
-#define ADT7473_REG_TEMP_TMAX(x) (ADT7473_REG_TEMP_TMAX_BASE_ADDR + (x))
-
-#define ADT7473_FAN_COUNT 4
-#define ADT7473_REG_FAN(x) (ADT7473_REG_FAN_BASE_ADDR + ((x) * 2))
-#define ADT7473_REG_FAN_MIN(x) (ADT7473_REG_FAN_MIN_BASE_ADDR + ((x) * 2))
-
-#define ADT7473_PWM_COUNT 3
-#define ADT7473_REG_PWM(x) (ADT7473_REG_PWM_BASE_ADDR + (x))
-#define ADT7473_REG_PWM_MAX(x) (ADT7473_REG_PWM_MAX_BASE_ADDR + (x))
-#define ADT7473_REG_PWM_MIN(x) (ADT7473_REG_PWM_MIN_BASE_ADDR + (x))
-#define ADT7473_REG_PWM_BHVR(x) (ADT7473_REG_PWM_BHVR_BASE_ADDR + (x))
-
-/* How often do we reread sensors values? (In jiffies) */
-#define SENSOR_REFRESH_INTERVAL (2 * HZ)
-
-/* How often do we reread sensor limit values? (In jiffies) */
-#define LIMIT_REFRESH_INTERVAL (60 * HZ)
-
-/* datasheet says to divide this number by the fan reading to get fan rpm */
-#define FAN_PERIOD_TO_RPM(x) ((90000 * 60) / (x))
-#define FAN_RPM_TO_PERIOD FAN_PERIOD_TO_RPM
-#define FAN_PERIOD_INVALID 65535
-#define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID)
-
-struct adt7473_data {
- struct device *hwmon_dev;
- struct attribute_group attrs;
- struct mutex lock;
- char sensors_valid;
- char limits_valid;
- unsigned long sensors_last_updated; /* In jiffies */
- unsigned long limits_last_updated; /* In jiffies */
-
- u8 volt[ADT7473_VOLT_COUNT];
- s8 volt_min[ADT7473_VOLT_COUNT];
- s8 volt_max[ADT7473_VOLT_COUNT];
-
- s8 temp[ADT7473_TEMP_COUNT];
- s8 temp_min[ADT7473_TEMP_COUNT];
- s8 temp_max[ADT7473_TEMP_COUNT];
- s8 temp_tmin[ADT7473_TEMP_COUNT];
- /* This is called the !THERM limit in the datasheet */
- s8 temp_tmax[ADT7473_TEMP_COUNT];
-
- u16 fan[ADT7473_FAN_COUNT];
- u16 fan_min[ADT7473_FAN_COUNT];
-
- u8 pwm[ADT7473_PWM_COUNT];
- u8 pwm_max[ADT7473_PWM_COUNT];
- u8 pwm_min[ADT7473_PWM_COUNT];
- u8 pwm_behavior[ADT7473_PWM_COUNT];
-
- u8 temp_twos_complement;
- u8 temp_offset;
-
- u16 alarm;
- u8 max_duty_at_overheat;
-};
-
-static int adt7473_probe(struct i2c_client *client,
- const struct i2c_device_id *id);
-static int adt7473_detect(struct i2c_client *client,
- struct i2c_board_info *info);
-static int adt7473_remove(struct i2c_client *client);
-
-static const struct i2c_device_id adt7473_id[] = {
- { "adt7473", 0 },
- { }
-};
-
-static struct i2c_driver adt7473_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "adt7473",
- },
- .probe = adt7473_probe,
- .remove = adt7473_remove,
- .id_table = adt7473_id,
- .detect = adt7473_detect,
- .address_list = normal_i2c,
-};
-
-/*
- * 16-bit registers on the ADT7473 are low-byte first. The data sheet says
- * that the low byte must be read before the high byte.
- */
-static inline int adt7473_read_word_data(struct i2c_client *client, u8 reg)
-{
- u16 foo;
- foo = i2c_smbus_read_byte_data(client, reg);
- foo |= ((u16)i2c_smbus_read_byte_data(client, reg + 1) << 8);
- return foo;
-}
-
-static inline int adt7473_write_word_data(struct i2c_client *client, u8 reg,
- u16 value)
-{
- return i2c_smbus_write_byte_data(client, reg, value & 0xFF)
- && i2c_smbus_write_byte_data(client, reg + 1, value >> 8);
-}
-
-static void adt7473_init_client(struct i2c_client *client)
-{
- int reg = i2c_smbus_read_byte_data(client, ADT7473_REG_CFG1);
-
- if (!(reg & ADT7473_CFG1_READY)) {
- dev_err(&client->dev, "Chip not ready.\n");
- } else {
- /* start monitoring */
- i2c_smbus_write_byte_data(client, ADT7473_REG_CFG1,
- reg | ADT7473_CFG1_START);
- }
-}
-
-static struct adt7473_data *adt7473_update_device(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7473_data *data = i2c_get_clientdata(client);
- unsigned long local_jiffies = jiffies;
- u8 cfg;
- int i;
-
- mutex_lock(&data->lock);
- if (time_before(local_jiffies, data->sensors_last_updated +
- SENSOR_REFRESH_INTERVAL)
- && data->sensors_valid)
- goto no_sensor_update;
-
- for (i = 0; i < ADT7473_VOLT_COUNT; i++)
- data->volt[i] = i2c_smbus_read_byte_data(client,
- ADT7473_REG_VOLT(i));
-
- /* Determine temperature encoding */
- cfg = i2c_smbus_read_byte_data(client, ADT7473_REG_CFG5);
- data->temp_twos_complement = (cfg & ADT7473_CFG5_TEMP_TWOS);
-
- /*
- * What does this do? it implies a variable temperature sensor
- * offset, but the datasheet doesn't say anything about this bit
- * and other parts of the datasheet imply that "offset64" mode
- * means that you shift temp values by -64 if the above bit was set.
- */
- data->temp_offset = (cfg & ADT7473_CFG5_TEMP_OFFSET);
-
- for (i = 0; i < ADT7473_TEMP_COUNT; i++)
- data->temp[i] = i2c_smbus_read_byte_data(client,
- ADT7473_REG_TEMP(i));
-
- for (i = 0; i < ADT7473_FAN_COUNT; i++)
- data->fan[i] = adt7473_read_word_data(client,
- ADT7473_REG_FAN(i));
-
- for (i = 0; i < ADT7473_PWM_COUNT; i++)
- data->pwm[i] = i2c_smbus_read_byte_data(client,
- ADT7473_REG_PWM(i));
-
- data->alarm = i2c_smbus_read_byte_data(client, ADT7473_REG_ALARM1);
- if (data->alarm & ADT7473_OOL)
- data->alarm |= ALARM2(i2c_smbus_read_byte_data(client,
- ADT7473_REG_ALARM2));
-
- data->sensors_last_updated = local_jiffies;
- data->sensors_valid = 1;
-
-no_sensor_update:
- if (time_before(local_jiffies, data->limits_last_updated +
- LIMIT_REFRESH_INTERVAL)
- && data->limits_valid)
- goto out;
-
- for (i = 0; i < ADT7473_VOLT_COUNT; i++) {
- data->volt_min[i] = i2c_smbus_read_byte_data(client,
- ADT7473_REG_VOLT_MIN(i));
- data->volt_max[i] = i2c_smbus_read_byte_data(client,
- ADT7473_REG_VOLT_MAX(i));
- }
-
- for (i = 0; i < ADT7473_TEMP_COUNT; i++) {
- data->temp_min[i] = i2c_smbus_read_byte_data(client,
- ADT7473_REG_TEMP_MIN(i));
- data->temp_max[i] = i2c_smbus_read_byte_data(client,
- ADT7473_REG_TEMP_MAX(i));
- data->temp_tmin[i] = i2c_smbus_read_byte_data(client,
- ADT7473_REG_TEMP_TMIN(i));
- data->temp_tmax[i] = i2c_smbus_read_byte_data(client,
- ADT7473_REG_TEMP_TMAX(i));
- }
-
- for (i = 0; i < ADT7473_FAN_COUNT; i++)
- data->fan_min[i] = adt7473_read_word_data(client,
- ADT7473_REG_FAN_MIN(i));
-
- for (i = 0; i < ADT7473_PWM_COUNT; i++) {
- data->pwm_max[i] = i2c_smbus_read_byte_data(client,
- ADT7473_REG_PWM_MAX(i));
- data->pwm_min[i] = i2c_smbus_read_byte_data(client,
- ADT7473_REG_PWM_MIN(i));
- data->pwm_behavior[i] = i2c_smbus_read_byte_data(client,
- ADT7473_REG_PWM_BHVR(i));
- }
-
- i = i2c_smbus_read_byte_data(client, ADT7473_REG_CFG4);
- data->max_duty_at_overheat = !!(i & ADT7473_CFG4_MAX_DUTY_AT_OVT);
-
- data->limits_last_updated = local_jiffies;
- data->limits_valid = 1;
-
-out:
- mutex_unlock(&data->lock);
- return data;
-}
-
-/*
- * Conversions
- */
-
-/* IN are scaled acording to built-in resistors */
-static const int adt7473_scaling[] = { /* .001 Volts */
- 2250, 3300
-};
-#define SCALE(val, from, to) (((val) * (to) + ((from) / 2)) / (from))
-
-static int decode_volt(int volt_index, u8 raw)
-{
- return SCALE(raw, 192, adt7473_scaling[volt_index]);
-}
-
-static u8 encode_volt(int volt_index, int cooked)
-{
- int raw = SCALE(cooked, adt7473_scaling[volt_index], 192);
- return SENSORS_LIMIT(raw, 0, 255);
-}
-
-static ssize_t show_volt_min(struct device *dev,
- struct device_attribute *devattr,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct adt7473_data *data = adt7473_update_device(dev);
- return sprintf(buf, "%d\n",
- decode_volt(attr->index, data->volt_min[attr->index]));
-}
-
-static ssize_t set_volt_min(struct device *dev,
- struct device_attribute *devattr,
- const char *buf,
- size_t count)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7473_data *data = i2c_get_clientdata(client);
- long volt;
-
- if (strict_strtol(buf, 10, &volt))
- return -EINVAL;
-
- volt = encode_volt(attr->index, volt);
-
- mutex_lock(&data->lock);
- data->volt_min[attr->index] = volt;
- i2c_smbus_write_byte_data(client, ADT7473_REG_VOLT_MIN(attr->index),
- volt);
- mutex_unlock(&data->lock);
-
- return count;
-}
-
-static ssize_t show_volt_max(struct device *dev,
- struct device_attribute *devattr,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct adt7473_data *data = adt7473_update_device(dev);
- return sprintf(buf, "%d\n",
- decode_volt(attr->index, data->volt_max[attr->index]));
-}
-
-static ssize_t set_volt_max(struct device *dev,
- struct device_attribute *devattr,
- const char *buf,
- size_t count)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7473_data *data = i2c_get_clientdata(client);
- long volt;
-
- if (strict_strtol(buf, 10, &volt))
- return -EINVAL;
-
- volt = encode_volt(attr->index, volt);
-
- mutex_lock(&data->lock);
- data->volt_max[attr->index] = volt;
- i2c_smbus_write_byte_data(client, ADT7473_REG_VOLT_MAX(attr->index),
- volt);
- mutex_unlock(&data->lock);
-
- return count;
-}
-
-static ssize_t show_volt(struct device *dev, struct device_attribute *devattr,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct adt7473_data *data = adt7473_update_device(dev);
-
- return sprintf(buf, "%d\n",
- decode_volt(attr->index, data->volt[attr->index]));
-}
-
-/*
- * This chip can report temperature data either as a two's complement
- * number in the range -128 to 127, or as an unsigned number that must
- * be offset by 64.
- */
-static int decode_temp(u8 twos_complement, u8 raw)
-{
- return twos_complement ? (s8)raw : raw - 64;
-}
-
-static u8 encode_temp(u8 twos_complement, int cooked)
-{
- u8 ret = twos_complement ? cooked & 0xFF : cooked + 64;
- return SENSORS_LIMIT(ret, 0, 255);
-}
-
-static ssize_t show_temp_min(struct device *dev,
- struct device_attribute *devattr,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct adt7473_data *data = adt7473_update_device(dev);
- return sprintf(buf, "%d\n", 1000 * decode_temp(
- data->temp_twos_complement,
- data->temp_min[attr->index]));
-}
-
-static ssize_t set_temp_min(struct device *dev,
- struct device_attribute *devattr,
- const char *buf,
- size_t count)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7473_data *data = i2c_get_clientdata(client);
- long temp;
-
- if (strict_strtol(buf, 10, &temp))
- return -EINVAL;
-
- temp = DIV_ROUND_CLOSEST(temp, 1000);
- temp = encode_temp(data->temp_twos_complement, temp);
-
- mutex_lock(&data->lock);
- data->temp_min[attr->index] = temp;
- i2c_smbus_write_byte_data(client, ADT7473_REG_TEMP_MIN(attr->index),
- temp);
- mutex_unlock(&data->lock);
-
- return count;
-}
-
-static ssize_t show_temp_max(struct device *dev,
- struct device_attribute *devattr,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct adt7473_data *data = adt7473_update_device(dev);
- return sprintf(buf, "%d\n", 1000 * decode_temp(
- data->temp_twos_complement,
- data->temp_max[attr->index]));
-}
-
-static ssize_t set_temp_max(struct device *dev,
- struct device_attribute *devattr,
- const char *buf,
- size_t count)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7473_data *data = i2c_get_clientdata(client);
- long temp;
-
- if (strict_strtol(buf, 10, &temp))
- return -EINVAL;
-
- temp = DIV_ROUND_CLOSEST(temp, 1000);
- temp = encode_temp(data->temp_twos_complement, temp);
-
- mutex_lock(&data->lock);
- data->temp_max[attr->index] = temp;
- i2c_smbus_write_byte_data(client, ADT7473_REG_TEMP_MAX(attr->index),
- temp);
- mutex_unlock(&data->lock);
-
- return count;
-}
-
-static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct adt7473_data *data = adt7473_update_device(dev);
- return sprintf(buf, "%d\n", 1000 * decode_temp(
- data->temp_twos_complement,
- data->temp[attr->index]));
-}
-
-static ssize_t show_fan_min(struct device *dev,
- struct device_attribute *devattr,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct adt7473_data *data = adt7473_update_device(dev);
-
- if (FAN_DATA_VALID(data->fan_min[attr->index]))
- return sprintf(buf, "%d\n",
- FAN_PERIOD_TO_RPM(data->fan_min[attr->index]));
- else
- return sprintf(buf, "0\n");
-}
-
-static ssize_t set_fan_min(struct device *dev,
- struct device_attribute *devattr,
- const char *buf, size_t count)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7473_data *data = i2c_get_clientdata(client);
- long temp;
-
- if (strict_strtol(buf, 10, &temp) || !temp)
- return -EINVAL;
-
- temp = FAN_RPM_TO_PERIOD(temp);
- temp = SENSORS_LIMIT(temp, 1, 65534);
-
- mutex_lock(&data->lock);
- data->fan_min[attr->index] = temp;
- adt7473_write_word_data(client, ADT7473_REG_FAN_MIN(attr->index), temp);
- mutex_unlock(&data->lock);
-
- return count;
-}
-
-static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct adt7473_data *data = adt7473_update_device(dev);
-
- if (FAN_DATA_VALID(data->fan[attr->index]))
- return sprintf(buf, "%d\n",
- FAN_PERIOD_TO_RPM(data->fan[attr->index]));
- else
- return sprintf(buf, "0\n");
-}
-
-static ssize_t show_max_duty_at_crit(struct device *dev,
- struct device_attribute *devattr,
- char *buf)
-{
- struct adt7473_data *data = adt7473_update_device(dev);
- return sprintf(buf, "%d\n", data->max_duty_at_overheat);
-}
-
-static ssize_t set_max_duty_at_crit(struct device *dev,
- struct device_attribute *devattr,
- const char *buf,
- size_t count)
-{
- u8 reg;
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7473_data *data = i2c_get_clientdata(client);
- long temp;
-
- if (strict_strtol(buf, 10, &temp))
- return -EINVAL;
-
- mutex_lock(&data->lock);
- data->max_duty_at_overheat = !!temp;
- reg = i2c_smbus_read_byte_data(client, ADT7473_REG_CFG4);
- if (temp)
- reg |= ADT7473_CFG4_MAX_DUTY_AT_OVT;
- else
- reg &= ~ADT7473_CFG4_MAX_DUTY_AT_OVT;
- i2c_smbus_write_byte_data(client, ADT7473_REG_CFG4, reg);
- mutex_unlock(&data->lock);
-
- return count;
-}
-
-static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct adt7473_data *data = adt7473_update_device(dev);
- return sprintf(buf, "%d\n", data->pwm[attr->index]);
-}
-
-static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7473_data *data = i2c_get_clientdata(client);
- long temp;
-
- if (strict_strtol(buf, 10, &temp))
- return -EINVAL;
-
- temp = SENSORS_LIMIT(temp, 0, 255);
-
- mutex_lock(&data->lock);
- data->pwm[attr->index] = temp;
- i2c_smbus_write_byte_data(client, ADT7473_REG_PWM(attr->index), temp);
- mutex_unlock(&data->lock);
-
- return count;
-}
-
-static ssize_t show_pwm_max(struct device *dev,
- struct device_attribute *devattr,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct adt7473_data *data = adt7473_update_device(dev);
- return sprintf(buf, "%d\n", data->pwm_max[attr->index]);
-}
-
-static ssize_t set_pwm_max(struct device *dev,
- struct device_attribute *devattr,
- const char *buf,
- size_t count)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7473_data *data = i2c_get_clientdata(client);
- long temp;
-
- if (strict_strtol(buf, 10, &temp))
- return -EINVAL;
-
- temp = SENSORS_LIMIT(temp, 0, 255);
-
- mutex_lock(&data->lock);
- data->pwm_max[attr->index] = temp;
- i2c_smbus_write_byte_data(client, ADT7473_REG_PWM_MAX(attr->index),
- temp);
- mutex_unlock(&data->lock);
-
- return count;
-}
-
-static ssize_t show_pwm_min(struct device *dev,
- struct device_attribute *devattr,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct adt7473_data *data = adt7473_update_device(dev);
- return sprintf(buf, "%d\n", data->pwm_min[attr->index]);
-}
-
-static ssize_t set_pwm_min(struct device *dev,
- struct device_attribute *devattr,
- const char *buf,
- size_t count)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7473_data *data = i2c_get_clientdata(client);
- long temp;
-
- if (strict_strtol(buf, 10, &temp))
- return -EINVAL;
-
- temp = SENSORS_LIMIT(temp, 0, 255);
-
- mutex_lock(&data->lock);
- data->pwm_min[attr->index] = temp;
- i2c_smbus_write_byte_data(client, ADT7473_REG_PWM_MIN(attr->index),
- temp);
- mutex_unlock(&data->lock);
-
- return count;
-}
-
-static ssize_t show_temp_tmax(struct device *dev,
- struct device_attribute *devattr,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct adt7473_data *data = adt7473_update_device(dev);
- return sprintf(buf, "%d\n", 1000 * decode_temp(
- data->temp_twos_complement,
- data->temp_tmax[attr->index]));
-}
-
-static ssize_t set_temp_tmax(struct device *dev,
- struct device_attribute *devattr,
- const char *buf,
- size_t count)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7473_data *data = i2c_get_clientdata(client);
- long temp;
-
- if (strict_strtol(buf, 10, &temp))
- return -EINVAL;
-
- temp = DIV_ROUND_CLOSEST(temp, 1000);
- temp = encode_temp(data->temp_twos_complement, temp);
-
- mutex_lock(&data->lock);
- data->temp_tmax[attr->index] = temp;
- i2c_smbus_write_byte_data(client, ADT7473_REG_TEMP_TMAX(attr->index),
- temp);
- mutex_unlock(&data->lock);
-
- return count;
-}
-
-static ssize_t show_temp_tmin(struct device *dev,
- struct device_attribute *devattr,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct adt7473_data *data = adt7473_update_device(dev);
- return sprintf(buf, "%d\n", 1000 * decode_temp(
- data->temp_twos_complement,
- data->temp_tmin[attr->index]));
-}
-
-static ssize_t set_temp_tmin(struct device *dev,
- struct device_attribute *devattr,
- const char *buf,
- size_t count)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7473_data *data = i2c_get_clientdata(client);
- long temp;
-
- if (strict_strtol(buf, 10, &temp))
- return -EINVAL;
-
- temp = DIV_ROUND_CLOSEST(temp, 1000);
- temp = encode_temp(data->temp_twos_complement, temp);
-
- mutex_lock(&data->lock);
- data->temp_tmin[attr->index] = temp;
- i2c_smbus_write_byte_data(client, ADT7473_REG_TEMP_TMIN(attr->index),
- temp);
- mutex_unlock(&data->lock);
-
- return count;
-}
-
-static ssize_t show_pwm_enable(struct device *dev,
- struct device_attribute *devattr,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct adt7473_data *data = adt7473_update_device(dev);
-
- switch (data->pwm_behavior[attr->index] >> ADT7473_PWM_BHVR_SHIFT) {
- case 3:
- return sprintf(buf, "0\n");
- case 7:
- return sprintf(buf, "1\n");
- default:
- return sprintf(buf, "2\n");
- }
-}
-
-static ssize_t set_pwm_enable(struct device *dev,
- struct device_attribute *devattr,
- const char *buf,
- size_t count)
-{
- u8 reg;
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7473_data *data = i2c_get_clientdata(client);
- long temp;
-
- if (strict_strtol(buf, 10, &temp))
- return -EINVAL;
-
- switch (temp) {
- case 0:
- temp = 3;
- break;
- case 1:
- temp = 7;
- break;
- case 2:
- /* Enter automatic mode with fans off */
- temp = 4;
- break;
- default:
- return -EINVAL;
- }
-
- mutex_lock(&data->lock);
- reg = i2c_smbus_read_byte_data(client,
- ADT7473_REG_PWM_BHVR(attr->index));
- reg = (temp << ADT7473_PWM_BHVR_SHIFT) |
- (reg & ~ADT7473_PWM_BHVR_MASK);
- i2c_smbus_write_byte_data(client, ADT7473_REG_PWM_BHVR(attr->index),
- reg);
- data->pwm_behavior[attr->index] = reg;
- mutex_unlock(&data->lock);
-
- return count;
-}
-
-static ssize_t show_pwm_auto_temp(struct device *dev,
- struct device_attribute *devattr,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct adt7473_data *data = adt7473_update_device(dev);
- int bhvr = data->pwm_behavior[attr->index] >> ADT7473_PWM_BHVR_SHIFT;
-
- switch (bhvr) {
- case 3:
- case 4:
- case 7:
- return sprintf(buf, "0\n");
- case 0:
- case 1:
- case 5:
- case 6:
- return sprintf(buf, "%d\n", bhvr + 1);
- case 2:
- return sprintf(buf, "4\n");
- }
- /* shouldn't ever get here */
- BUG();
-}
-
-static ssize_t set_pwm_auto_temp(struct device *dev,
- struct device_attribute *devattr,
- const char *buf,
- size_t count)
-{
- u8 reg;
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct i2c_client *client = to_i2c_client(dev);
- struct adt7473_data *data = i2c_get_clientdata(client);
- long temp;
-
- if (strict_strtol(buf, 10, &temp))
- return -EINVAL;
-
- switch (temp) {
- case 1:
- case 2:
- case 6:
- case 7:
- temp--;
- break;
- case 0:
- temp = 4;
- break;
- default:
- return -EINVAL;
- }
-
- mutex_lock(&data->lock);
- reg = i2c_smbus_read_byte_data(client,
- ADT7473_REG_PWM_BHVR(attr->index));
- reg = (temp << ADT7473_PWM_BHVR_SHIFT) |
- (reg & ~ADT7473_PWM_BHVR_MASK);
- i2c_smbus_write_byte_data(client, ADT7473_REG_PWM_BHVR(attr->index),
- reg);
- data->pwm_behavior[attr->index] = reg;
- mutex_unlock(&data->lock);
-
- return count;
-}
-
-static ssize_t show_alarm(struct device *dev,
- struct device_attribute *devattr,
- char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct adt7473_data *data = adt7473_update_device(dev);
-
- if (data->alarm & attr->index)
- return sprintf(buf, "1\n");
- else
- return sprintf(buf, "0\n");
-}
-
-
-static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, show_volt_max,
- set_volt_max, 0);
-static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, show_volt_max,
- set_volt_max, 1);
-
-static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, show_volt_min,
- set_volt_min, 0);
-static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, show_volt_min,
- set_volt_min, 1);
-
-static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_volt, NULL, 0);
-static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_volt, NULL, 1);
-
-static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL,
- ADT7473_VCCP_ALARM);
-static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL,
- ADT7473_VCC_ALARM);
-
-static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
- set_temp_max, 0);
-static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max,
- set_temp_max, 1);
-static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_max,
- set_temp_max, 2);
-
-static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_min,
- set_temp_min, 0);
-static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min,
- set_temp_min, 1);
-static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_temp_min,
- set_temp_min, 2);
-
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
-static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
-
-static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL,
- ADT7473_R1T_ALARM | ALARM2(ADT7473_R1T_SHORT));
-static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL,
- ADT7473_LT_ALARM);
-static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL,
- ADT7473_R2T_ALARM | ALARM2(ADT7473_R2T_SHORT));
-
-static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min,
- set_fan_min, 0);
-static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min,
- set_fan_min, 1);
-static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min,
- set_fan_min, 2);
-static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min,
- set_fan_min, 3);
-
-static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
-static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
-static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
-static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3);
-
-static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL,
- ALARM2(ADT7473_FAN1_ALARM));
-static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL,
- ALARM2(ADT7473_FAN2_ALARM));
-static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL,
- ALARM2(ADT7473_FAN3_ALARM));
-static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL,
- ALARM2(ADT7473_FAN4_ALARM));
-
-static SENSOR_DEVICE_ATTR(pwm_use_point2_pwm_at_crit, S_IWUSR | S_IRUGO,
- show_max_duty_at_crit, set_max_duty_at_crit, 0);
-
-static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0);
-static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1);
-static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2);
-
-static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO,
- show_pwm_min, set_pwm_min, 0);
-static SENSOR_DEVICE_ATTR(pwm2_auto_point1_pwm, S_IWUSR | S_IRUGO,
- show_pwm_min, set_pwm_min, 1);
-static SENSOR_DEVICE_ATTR(pwm3_auto_point1_pwm, S_IWUSR | S_IRUGO,
- show_pwm_min, set_pwm_min, 2);
-
-static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO,
- show_pwm_max, set_pwm_max, 0);
-static SENSOR_DEVICE_ATTR(pwm2_auto_point2_pwm, S_IWUSR | S_IRUGO,
- show_pwm_max, set_pwm_max, 1);
-static SENSOR_DEVICE_ATTR(pwm3_auto_point2_pwm, S_IWUSR | S_IRUGO,
- show_pwm_max, set_pwm_max, 2);
-
-static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp, S_IWUSR | S_IRUGO,
- show_temp_tmin, set_temp_tmin, 0);
-static SENSOR_DEVICE_ATTR(temp2_auto_point1_temp, S_IWUSR | S_IRUGO,
- show_temp_tmin, set_temp_tmin, 1);
-static SENSOR_DEVICE_ATTR(temp3_auto_point1_temp, S_IWUSR | S_IRUGO,
- show_temp_tmin, set_temp_tmin, 2);
-
-static SENSOR_DEVICE_ATTR(temp1_auto_point2_temp, S_IWUSR | S_IRUGO,
- show_temp_tmax, set_temp_tmax, 0);
-static SENSOR_DEVICE_ATTR(temp2_auto_point2_temp, S_IWUSR | S_IRUGO,
- show_temp_tmax, set_temp_tmax, 1);
-static SENSOR_DEVICE_ATTR(temp3_auto_point2_temp, S_IWUSR | S_IRUGO,
- show_temp_tmax, set_temp_tmax, 2);
-
-static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
- set_pwm_enable, 0);
-static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
- set_pwm_enable, 1);
-static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
- set_pwm_enable, 2);
-
-static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IWUSR | S_IRUGO,
- show_pwm_auto_temp, set_pwm_auto_temp, 0);
-static SENSOR_DEVICE_ATTR(pwm2_auto_channels_temp, S_IWUSR | S_IRUGO,
- show_pwm_auto_temp, set_pwm_auto_temp, 1);
-static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IWUSR | S_IRUGO,
- show_pwm_auto_temp, set_pwm_auto_temp, 2);
-
-static struct attribute *adt7473_attr[] =
-{
- &sensor_dev_attr_in1_max.dev_attr.attr,
- &sensor_dev_attr_in2_max.dev_attr.attr,
- &sensor_dev_attr_in1_min.dev_attr.attr,
- &sensor_dev_attr_in2_min.dev_attr.attr,
- &sensor_dev_attr_in1_input.dev_attr.attr,
- &sensor_dev_attr_in2_input.dev_attr.attr,
- &sensor_dev_attr_in1_alarm.dev_attr.attr,
- &sensor_dev_attr_in2_alarm.dev_attr.attr,
-
- &sensor_dev_attr_temp1_max.dev_attr.attr,
- &sensor_dev_attr_temp2_max.dev_attr.attr,
- &sensor_dev_attr_temp3_max.dev_attr.attr,
- &sensor_dev_attr_temp1_min.dev_attr.attr,
- &sensor_dev_attr_temp2_min.dev_attr.attr,
- &sensor_dev_attr_temp3_min.dev_attr.attr,
- &sensor_dev_attr_temp1_input.dev_attr.attr,
- &sensor_dev_attr_temp2_input.dev_attr.attr,
- &sensor_dev_attr_temp3_input.dev_attr.attr,
- &sensor_dev_attr_temp1_alarm.dev_attr.attr,
- &sensor_dev_attr_temp2_alarm.dev_attr.attr,
- &sensor_dev_attr_temp3_alarm.dev_attr.attr,
- &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
- &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr,
- &sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr,
- &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr,
- &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr,
- &sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr,
-
- &sensor_dev_attr_fan1_min.dev_attr.attr,
- &sensor_dev_attr_fan2_min.dev_attr.attr,
- &sensor_dev_attr_fan3_min.dev_attr.attr,
- &sensor_dev_attr_fan4_min.dev_attr.attr,
- &sensor_dev_attr_fan1_input.dev_attr.attr,
- &sensor_dev_attr_fan2_input.dev_attr.attr,
- &sensor_dev_attr_fan3_input.dev_attr.attr,
- &sensor_dev_attr_fan4_input.dev_attr.attr,
- &sensor_dev_attr_fan1_alarm.dev_attr.attr,
- &sensor_dev_attr_fan2_alarm.dev_attr.attr,
- &sensor_dev_attr_fan3_alarm.dev_attr.attr,
- &sensor_dev_attr_fan4_alarm.dev_attr.attr,
-
- &sensor_dev_attr_pwm_use_point2_pwm_at_crit.dev_attr.attr,
-
- &sensor_dev_attr_pwm1.dev_attr.attr,
- &sensor_dev_attr_pwm2.dev_attr.attr,
- &sensor_dev_attr_pwm3.dev_attr.attr,
- &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
- &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
- &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,
- &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
- &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
- &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr,
-
- &sensor_dev_attr_pwm1_enable.dev_attr.attr,
- &sensor_dev_attr_pwm2_enable.dev_attr.attr,
- &sensor_dev_attr_pwm3_enable.dev_attr.attr,
- &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr,
- &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr,
- &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr,
-
- NULL
-};
-
-/* Return 0 if detection is successful, -ENODEV otherwise */
-static int adt7473_detect(struct i2c_client *client,
- struct i2c_board_info *info)
-{
- struct i2c_adapter *adapter = client->adapter;
- int vendor, device, revision;
-
- if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return -ENODEV;
-
- vendor = i2c_smbus_read_byte_data(client, ADT7473_REG_VENDOR);
- if (vendor != ADT7473_VENDOR)
- return -ENODEV;
-
- device = i2c_smbus_read_byte_data(client, ADT7473_REG_DEVICE);
- if (device != ADT7473_DEVICE)
- return -ENODEV;
-
- revision = i2c_smbus_read_byte_data(client, ADT7473_REG_REVISION);
- if (revision != ADT7473_REV_68 && revision != ADT7473_REV_69)
- return -ENODEV;
-
- strlcpy(info->type, "adt7473", I2C_NAME_SIZE);
-
- return 0;
-}
-
-static int adt7473_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct adt7473_data *data;
- int err;
-
- data = kzalloc(sizeof(struct adt7473_data), GFP_KERNEL);
- if (!data) {
- err = -ENOMEM;
- goto exit;
- }
-
- i2c_set_clientdata(client, data);
- mutex_init(&data->lock);
-
- dev_info(&client->dev, "%s chip found\n", client->name);
-
- /* Initialize the ADT7473 chip */
- adt7473_init_client(client);
-
- /* Register sysfs hooks */
- data->attrs.attrs = adt7473_attr;
- err = sysfs_create_group(&client->dev.kobj, &data->attrs);
- if (err)
- goto exit_free;
-
- data->hwmon_dev = hwmon_device_register(&client->dev);
- if (IS_ERR(data->hwmon_dev)) {
- err = PTR_ERR(data->hwmon_dev);
- goto exit_remove;
- }
-
- return 0;
-
-exit_remove:
- sysfs_remove_group(&client->dev.kobj, &data->attrs);
-exit_free:
- kfree(data);
-exit:
- return err;
-}
-
-static int adt7473_remove(struct i2c_client *client)
-{
- struct adt7473_data *data = i2c_get_clientdata(client);
-
- hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&client->dev.kobj, &data->attrs);
- kfree(data);
- return 0;
-}
-
-static int __init adt7473_init(void)
-{
- pr_notice("The adt7473 driver is deprecated, please use the adt7475 "
- "driver instead\n");
- return i2c_add_driver(&adt7473_driver);
-}
-
-static void __exit adt7473_exit(void)
-{
- i2c_del_driver(&adt7473_driver);
-}
-
-MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>");
-MODULE_DESCRIPTION("ADT7473 driver");
-MODULE_LICENSE("GPL");
-
-module_init(adt7473_init);
-module_exit(adt7473_exit);
diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c
new file mode 100644
index 00000000000..7f948105d8a
--- /dev/null
+++ b/drivers/hwmon/asc7621.c
@@ -0,0 +1,1255 @@
+/*
+ * asc7621.c - Part of lm_sensors, Linux kernel modules for hardware monitoring
+ * Copyright (c) 2007, 2010 George Joseph <george.joseph@fairview5.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/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = {
+ 0x2c, 0x2d, 0x2e, I2C_CLIENT_END
+};
+
+enum asc7621_type {
+ asc7621,
+ asc7621a
+};
+
+#define INTERVAL_HIGH (HZ + HZ / 2)
+#define INTERVAL_LOW (1 * 60 * HZ)
+#define PRI_NONE 0
+#define PRI_LOW 1
+#define PRI_HIGH 2
+#define FIRST_CHIP asc7621
+#define LAST_CHIP asc7621a
+
+struct asc7621_chip {
+ char *name;
+ enum asc7621_type chip_type;
+ u8 company_reg;
+ u8 company_id;
+ u8 verstep_reg;
+ u8 verstep_id;
+ unsigned short *addresses;
+};
+
+static struct asc7621_chip asc7621_chips[] = {
+ {
+ .name = "asc7621",
+ .chip_type = asc7621,
+ .company_reg = 0x3e,
+ .company_id = 0x61,
+ .verstep_reg = 0x3f,
+ .verstep_id = 0x6c,
+ .addresses = normal_i2c,
+ },
+ {
+ .name = "asc7621a",
+ .chip_type = asc7621a,
+ .company_reg = 0x3e,
+ .company_id = 0x61,
+ .verstep_reg = 0x3f,
+ .verstep_id = 0x6d,
+ .addresses = normal_i2c,
+ },
+};
+
+/*
+ * Defines the highest register to be used, not the count.
+ * The actual count will probably be smaller because of gaps
+ * in the implementation (unused register locations).
+ * This define will safely set the array size of both the parameter
+ * and data arrays.
+ * This comes from the data sheet register description table.
+ */
+#define LAST_REGISTER 0xff
+
+struct asc7621_data {
+ struct i2c_client client;
+ struct device *class_dev;
+ struct mutex update_lock;
+ int valid; /* !=0 if following fields are valid */
+ unsigned long last_high_reading; /* In jiffies */
+ unsigned long last_low_reading; /* In jiffies */
+ /*
+ * Registers we care about occupy the corresponding index
+ * in the array. Registers we don't care about are left
+ * at 0.
+ */
+ u8 reg[LAST_REGISTER + 1];
+};
+
+/*
+ * Macro to get the parent asc7621_param structure
+ * from a sensor_device_attribute passed into the
+ * show/store functions.
+ */
+#define to_asc7621_param(_sda) \
+ container_of(_sda, struct asc7621_param, sda)
+
+/*
+ * Each parameter to be retrieved needs an asc7621_param structure
+ * allocated. It contains the sensor_device_attribute structure
+ * and the control info needed to retrieve the value from the register map.
+ */
+struct asc7621_param {
+ struct sensor_device_attribute sda;
+ u8 priority;
+ u8 msb[3];
+ u8 lsb[3];
+ u8 mask[3];
+ u8 shift[3];
+};
+
+/*
+ * This is the map that ultimately indicates whether we'll be
+ * retrieving a register value or not, and at what frequency.
+ */
+static u8 asc7621_register_priorities[255];
+
+static struct asc7621_data *asc7621_update_device(struct device *dev);
+
+static inline u8 read_byte(struct i2c_client *client, u8 reg)
+{
+ int res = i2c_smbus_read_byte_data(client, reg);
+ if (res < 0) {
+ dev_err(&client->dev,
+ "Unable to read from register 0x%02x.\n", reg);
+ return 0;
+ };
+ return res & 0xff;
+}
+
+static inline int write_byte(struct i2c_client *client, u8 reg, u8 data)
+{
+ int res = i2c_smbus_write_byte_data(client, reg, data);
+ if (res < 0) {
+ dev_err(&client->dev,
+ "Unable to write value 0x%02x to register 0x%02x.\n",
+ data, reg);
+ };
+ return res;
+}
+
+/*
+ * Data Handlers
+ * Each function handles the formatting, storage
+ * and retrieval of like parameters.
+ */
+
+#define SETUP_SHOW_data_param(d, a) \
+ struct sensor_device_attribute *sda = to_sensor_dev_attr(a); \
+ struct asc7621_data *data = asc7621_update_device(d); \
+ struct asc7621_param *param = to_asc7621_param(sda)
+
+#define SETUP_STORE_data_param(d, a) \
+ struct sensor_device_attribute *sda = to_sensor_dev_attr(a); \
+ struct i2c_client *client = to_i2c_client(d); \
+ struct asc7621_data *data = i2c_get_clientdata(client); \
+ struct asc7621_param *param = to_asc7621_param(sda)
+
+/*
+ * u8 is just what it sounds like...an unsigned byte with no
+ * special formatting.
+ */
+static ssize_t show_u8(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ SETUP_SHOW_data_param(dev, attr);
+
+ return sprintf(buf, "%u\n", data->reg[param->msb[0]]);
+}
+
+static ssize_t store_u8(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ SETUP_STORE_data_param(dev, attr);
+ long reqval;
+
+ if (strict_strtol(buf, 10, &reqval))
+ return -EINVAL;
+
+ reqval = SENSORS_LIMIT(reqval, 0, 255);
+
+ mutex_lock(&data->update_lock);
+ data->reg[param->msb[0]] = reqval;
+ write_byte(client, param->msb[0], reqval);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+/*
+ * Many of the config values occupy only a few bits of a register.
+ */
+static ssize_t show_bitmask(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ SETUP_SHOW_data_param(dev, attr);
+
+ return sprintf(buf, "%u\n",
+ (data->reg[param->msb[0]] >> param->
+ shift[0]) & param->mask[0]);
+}
+
+static ssize_t store_bitmask(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ SETUP_STORE_data_param(dev, attr);
+ long reqval;
+ u8 currval;
+
+ if (strict_strtol(buf, 10, &reqval))
+ return -EINVAL;
+
+ reqval = SENSORS_LIMIT(reqval, 0, param->mask[0]);
+
+ reqval = (reqval & param->mask[0]) << param->shift[0];
+
+ mutex_lock(&data->update_lock);
+ currval = read_byte(client, param->msb[0]);
+ reqval |= (currval & ~(param->mask[0] << param->shift[0]));
+ data->reg[param->msb[0]] = reqval;
+ write_byte(client, param->msb[0], reqval);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+/*
+ * 16 bit fan rpm values
+ * reported by the device as the number of 11.111us periods (90khz)
+ * between full fan rotations. Therefore...
+ * RPM = (90000 * 60) / register value
+ */
+static ssize_t show_fan16(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ SETUP_SHOW_data_param(dev, attr);
+ u16 regval;
+
+ mutex_lock(&data->update_lock);
+ regval = (data->reg[param->msb[0]] << 8) | data->reg[param->lsb[0]];
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "%u\n",
+ (regval == 0 ? -1 : (regval) ==
+ 0xffff ? 0 : 5400000 / regval));
+}
+
+static ssize_t store_fan16(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ SETUP_STORE_data_param(dev, attr);
+ long reqval;
+
+ if (strict_strtol(buf, 10, &reqval))
+ return -EINVAL;
+
+ reqval =
+ (SENSORS_LIMIT((reqval) <= 0 ? 0 : 5400000 / (reqval), 0, 65534));
+
+ mutex_lock(&data->update_lock);
+ data->reg[param->msb[0]] = (reqval >> 8) & 0xff;
+ data->reg[param->lsb[0]] = reqval & 0xff;
+ write_byte(client, param->msb[0], data->reg[param->msb[0]]);
+ write_byte(client, param->lsb[0], data->reg[param->lsb[0]]);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+/*
+ * Voltages are scaled in the device so that the nominal voltage
+ * is 3/4ths of the 0-255 range (i.e. 192).
+ * If all voltages are 'normal' then all voltage registers will
+ * read 0xC0. This doesn't help us if we don't have a point of refernce.
+ * The data sheet however provides us with the full scale value for each
+ * which is stored in in_scaling. The sda->index parameter value provides
+ * the index into in_scaling.
+ *
+ * NOTE: The chip expects the first 2 inputs be 2.5 and 2.25 volts
+ * respectively. That doesn't mean that's what the motherboard provides. :)
+ */
+
+static int asc7621_in_scaling[] = {
+ 3320, 3000, 4380, 6640, 16000
+};
+
+static ssize_t show_in10(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ SETUP_SHOW_data_param(dev, attr);
+ u16 regval;
+ u8 nr = sda->index;
+
+ mutex_lock(&data->update_lock);
+ regval = (data->reg[param->msb[0]] * asc7621_in_scaling[nr]) / 256;
+
+ /* The LSB value is a 2-bit scaling of the MSB's LSbit value.
+ * I.E. If the maximim voltage for this input is 6640 millivolts then
+ * a MSB register value of 0 = 0mv and 255 = 6640mv.
+ * A 1 step change therefore represents 25.9mv (6640 / 256).
+ * The extra 2-bits therefore represent increments of 6.48mv.
+ */
+ regval += ((asc7621_in_scaling[nr] / 256) / 4) *
+ (data->reg[param->lsb[0]] >> 6);
+
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "%u\n", regval);
+}
+
+/* 8 bit voltage values (the mins and maxs) */
+static ssize_t show_in8(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ SETUP_SHOW_data_param(dev, attr);
+ u8 nr = sda->index;
+
+ return sprintf(buf, "%u\n",
+ ((data->reg[param->msb[0]] *
+ asc7621_in_scaling[nr]) / 256));
+}
+
+static ssize_t store_in8(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ SETUP_STORE_data_param(dev, attr);
+ long reqval;
+ u8 nr = sda->index;
+
+ if (strict_strtol(buf, 10, &reqval))
+ return -EINVAL;
+
+ reqval = SENSORS_LIMIT(reqval, 0, asc7621_in_scaling[nr]);
+
+ reqval = (reqval * 255 + 128) / asc7621_in_scaling[nr];
+
+ mutex_lock(&data->update_lock);
+ data->reg[param->msb[0]] = reqval;
+ write_byte(client, param->msb[0], reqval);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+static ssize_t show_temp8(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ SETUP_SHOW_data_param(dev, attr);
+
+ return sprintf(buf, "%d\n", ((s8) data->reg[param->msb[0]]) * 1000);
+}
+
+static ssize_t store_temp8(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ SETUP_STORE_data_param(dev, attr);
+ long reqval;
+ s8 temp;
+
+ if (strict_strtol(buf, 10, &reqval))
+ return -EINVAL;
+
+ reqval = SENSORS_LIMIT(reqval, -127000, 127000);
+
+ temp = reqval / 1000;
+
+ mutex_lock(&data->update_lock);
+ data->reg[param->msb[0]] = temp;
+ write_byte(client, param->msb[0], temp);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+/*
+ * Temperatures that occupy 2 bytes always have the whole
+ * number of degrees in the MSB with some part of the LSB
+ * indicating fractional degrees.
+ */
+
+/* mmmmmmmm.llxxxxxx */
+static ssize_t show_temp10(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ SETUP_SHOW_data_param(dev, attr);
+ u8 msb, lsb;
+ int temp;
+
+ mutex_lock(&data->update_lock);
+ msb = data->reg[param->msb[0]];
+ lsb = (data->reg[param->lsb[0]] >> 6) & 0x03;
+ temp = (((s8) msb) * 1000) + (lsb * 250);
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "%d\n", temp);
+}
+
+/* mmmmmm.ll */
+static ssize_t show_temp62(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ SETUP_SHOW_data_param(dev, attr);
+ u8 regval = data->reg[param->msb[0]];
+ int temp = ((s8) (regval & 0xfc) * 1000) + ((regval & 0x03) * 250);
+
+ return sprintf(buf, "%d\n", temp);
+}
+
+static ssize_t store_temp62(struct device *dev,
+ struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ SETUP_STORE_data_param(dev, attr);
+ long reqval, i, f;
+ s8 temp;
+
+ if (strict_strtol(buf, 10, &reqval))
+ return -EINVAL;
+
+ reqval = SENSORS_LIMIT(reqval, -32000, 31750);
+ i = reqval / 1000;
+ f = reqval - (i * 1000);
+ temp = i << 2;
+ temp |= f / 250;
+
+ mutex_lock(&data->update_lock);
+ data->reg[param->msb[0]] = temp;
+ write_byte(client, param->msb[0], temp);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+/*
+ * The aSC7621 doesn't provide an "auto_point2". Instead, you
+ * specify the auto_point1 and a range. To keep with the sysfs
+ * hwmon specs, we synthesize the auto_point_2 from them.
+ */
+
+static u32 asc7621_range_map[] = {
+ 2000, 2500, 3330, 4000, 5000, 6670, 8000, 10000,
+ 13330, 16000, 20000, 26670, 32000, 40000, 53330, 80000,
+};
+
+static ssize_t show_ap2_temp(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ SETUP_SHOW_data_param(dev, attr);
+ long auto_point1;
+ u8 regval;
+ int temp;
+
+ mutex_lock(&data->update_lock);
+ auto_point1 = ((s8) data->reg[param->msb[1]]) * 1000;
+ regval =
+ ((data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]);
+ temp = auto_point1 + asc7621_range_map[SENSORS_LIMIT(regval, 0, 15)];
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "%d\n", temp);
+
+}
+
+static ssize_t store_ap2_temp(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ SETUP_STORE_data_param(dev, attr);
+ long reqval, auto_point1;
+ int i;
+ u8 currval, newval = 0;
+
+ if (strict_strtol(buf, 10, &reqval))
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+ auto_point1 = data->reg[param->msb[1]] * 1000;
+ reqval = SENSORS_LIMIT(reqval, auto_point1 + 2000, auto_point1 + 80000);
+
+ for (i = ARRAY_SIZE(asc7621_range_map) - 1; i >= 0; i--) {
+ if (reqval >= auto_point1 + asc7621_range_map[i]) {
+ newval = i;
+ break;
+ }
+ }
+
+ newval = (newval & param->mask[0]) << param->shift[0];
+ currval = read_byte(client, param->msb[0]);
+ newval |= (currval & ~(param->mask[0] << param->shift[0]));
+ data->reg[param->msb[0]] = newval;
+ write_byte(client, param->msb[0], newval);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static ssize_t show_pwm_ac(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ SETUP_SHOW_data_param(dev, attr);
+ u8 config, altbit, regval;
+ u8 map[] = {
+ 0x01, 0x02, 0x04, 0x1f, 0x00, 0x06, 0x07, 0x10,
+ 0x08, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f
+ };
+
+ mutex_lock(&data->update_lock);
+ config = (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0];
+ altbit = (data->reg[param->msb[1]] >> param->shift[1]) & param->mask[1];
+ regval = config | (altbit << 3);
+ mutex_unlock(&data->update_lock);
+
+ return sprintf(buf, "%u\n", map[SENSORS_LIMIT(regval, 0, 15)]);
+}
+
+static ssize_t store_pwm_ac(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ SETUP_STORE_data_param(dev, attr);
+ unsigned long reqval;
+ u8 currval, config, altbit, newval;
+ u16 map[] = {
+ 0x04, 0x00, 0x01, 0xff, 0x02, 0xff, 0x05, 0x06,
+ 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
+ 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
+ };
+
+ if (strict_strtoul(buf, 10, &reqval))
+ return -EINVAL;
+
+ if (reqval > 31)
+ return -EINVAL;
+
+ reqval = map[reqval];
+ if (reqval == 0xff)
+ return -EINVAL;
+
+ config = reqval & 0x07;
+ altbit = (reqval >> 3) & 0x01;
+
+ config = (config & param->mask[0]) << param->shift[0];
+ altbit = (altbit & param->mask[1]) << param->shift[1];
+
+ mutex_lock(&data->update_lock);
+ currval = read_byte(client, param->msb[0]);
+ newval = config | (currval & ~(param->mask[0] << param->shift[0]));
+ newval = altbit | (newval & ~(param->mask[1] << param->shift[1]));
+ data->reg[param->msb[0]] = newval;
+ write_byte(client, param->msb[0], newval);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static ssize_t show_pwm_enable(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ SETUP_SHOW_data_param(dev, attr);
+ u8 config, altbit, minoff, val, newval;
+
+ mutex_lock(&data->update_lock);
+ config = (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0];
+ altbit = (data->reg[param->msb[1]] >> param->shift[1]) & param->mask[1];
+ minoff = (data->reg[param->msb[2]] >> param->shift[2]) & param->mask[2];
+ mutex_unlock(&data->update_lock);
+
+ val = config | (altbit << 3);
+ newval = 0;
+
+ if (val == 3 || val >= 10)
+ newval = 255;
+ else if (val == 4)
+ newval = 0;
+ else if (val == 7)
+ newval = 1;
+ else if (minoff == 1)
+ newval = 2;
+ else
+ newval = 3;
+
+ return sprintf(buf, "%u\n", newval);
+}
+
+static ssize_t store_pwm_enable(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ SETUP_STORE_data_param(dev, attr);
+ long reqval;
+ u8 currval, config, altbit, newval, minoff = 255;
+
+ if (strict_strtol(buf, 10, &reqval))
+ return -EINVAL;
+
+ switch (reqval) {
+ case 0:
+ newval = 0x04;
+ break;
+ case 1:
+ newval = 0x07;
+ break;
+ case 2:
+ newval = 0x00;
+ minoff = 1;
+ break;
+ case 3:
+ newval = 0x00;
+ minoff = 0;
+ break;
+ case 255:
+ newval = 0x03;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ config = newval & 0x07;
+ altbit = (newval >> 3) & 0x01;
+
+ mutex_lock(&data->update_lock);
+ config = (config & param->mask[0]) << param->shift[0];
+ altbit = (altbit & param->mask[1]) << param->shift[1];
+ currval = read_byte(client, param->msb[0]);
+ newval = config | (currval & ~(param->mask[0] << param->shift[0]));
+ newval = altbit | (newval & ~(param->mask[1] << param->shift[1]));
+ data->reg[param->msb[0]] = newval;
+ write_byte(client, param->msb[0], newval);
+ if (minoff < 255) {
+ minoff = (minoff & param->mask[2]) << param->shift[2];
+ currval = read_byte(client, param->msb[2]);
+ newval =
+ minoff | (currval & ~(param->mask[2] << param->shift[2]));
+ data->reg[param->msb[2]] = newval;
+ write_byte(client, param->msb[2], newval);
+ }
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static u32 asc7621_pwm_freq_map[] = {
+ 10, 15, 23, 30, 38, 47, 62, 94,
+ 23000, 24000, 25000, 26000, 27000, 28000, 29000, 30000
+};
+
+static ssize_t show_pwm_freq(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ SETUP_SHOW_data_param(dev, attr);
+ u8 regval =
+ (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0];
+
+ regval = SENSORS_LIMIT(regval, 0, 15);
+
+ return sprintf(buf, "%u\n", asc7621_pwm_freq_map[regval]);
+}
+
+static ssize_t store_pwm_freq(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ SETUP_STORE_data_param(dev, attr);
+ unsigned long reqval;
+ u8 currval, newval = 255;
+ int i;
+
+ if (strict_strtoul(buf, 10, &reqval))
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(asc7621_pwm_freq_map); i++) {
+ if (reqval == asc7621_pwm_freq_map[i]) {
+ newval = i;
+ break;
+ }
+ }
+ if (newval == 255)
+ return -EINVAL;
+
+ newval = (newval & param->mask[0]) << param->shift[0];
+
+ mutex_lock(&data->update_lock);
+ currval = read_byte(client, param->msb[0]);
+ newval |= (currval & ~(param->mask[0] << param->shift[0]));
+ data->reg[param->msb[0]] = newval;
+ write_byte(client, param->msb[0], newval);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static u32 asc7621_pwm_auto_spinup_map[] = {
+ 0, 100, 250, 400, 700, 1000, 2000, 4000
+};
+
+static ssize_t show_pwm_ast(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ SETUP_SHOW_data_param(dev, attr);
+ u8 regval =
+ (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0];
+
+ regval = SENSORS_LIMIT(regval, 0, 7);
+
+ return sprintf(buf, "%u\n", asc7621_pwm_auto_spinup_map[regval]);
+
+}
+
+static ssize_t store_pwm_ast(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ SETUP_STORE_data_param(dev, attr);
+ long reqval;
+ u8 currval, newval = 255;
+ u32 i;
+
+ if (strict_strtol(buf, 10, &reqval))
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(asc7621_pwm_auto_spinup_map); i++) {
+ if (reqval == asc7621_pwm_auto_spinup_map[i]) {
+ newval = i;
+ break;
+ }
+ }
+ if (newval == 255)
+ return -EINVAL;
+
+ newval = (newval & param->mask[0]) << param->shift[0];
+
+ mutex_lock(&data->update_lock);
+ currval = read_byte(client, param->msb[0]);
+ newval |= (currval & ~(param->mask[0] << param->shift[0]));
+ data->reg[param->msb[0]] = newval;
+ write_byte(client, param->msb[0], newval);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static u32 asc7621_temp_smoothing_time_map[] = {
+ 35000, 17600, 11800, 7000, 4400, 3000, 1600, 800
+};
+
+static ssize_t show_temp_st(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ SETUP_SHOW_data_param(dev, attr);
+ u8 regval =
+ (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0];
+ regval = SENSORS_LIMIT(regval, 0, 7);
+
+ return sprintf(buf, "%u\n", asc7621_temp_smoothing_time_map[regval]);
+}
+
+static ssize_t store_temp_st(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ SETUP_STORE_data_param(dev, attr);
+ long reqval;
+ u8 currval, newval = 255;
+ u32 i;
+
+ if (strict_strtol(buf, 10, &reqval))
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(asc7621_temp_smoothing_time_map); i++) {
+ if (reqval == asc7621_temp_smoothing_time_map[i]) {
+ newval = i;
+ break;
+ }
+ }
+
+ if (newval == 255)
+ return -EINVAL;
+
+ newval = (newval & param->mask[0]) << param->shift[0];
+
+ mutex_lock(&data->update_lock);
+ currval = read_byte(client, param->msb[0]);
+ newval |= (currval & ~(param->mask[0] << param->shift[0]));
+ data->reg[param->msb[0]] = newval;
+ write_byte(client, param->msb[0], newval);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+/*
+ * End of data handlers
+ *
+ * These defines do nothing more than make the table easier
+ * to read when wrapped at column 80.
+ */
+
+/*
+ * Creates a variable length array inititalizer.
+ * VAA(1,3,5,7) would produce {1,3,5,7}
+ */
+#define VAA(args...) {args}
+
+#define PREAD(name, n, pri, rm, rl, m, s, r) \
+ {.sda = SENSOR_ATTR(name, S_IRUGO, show_##r, NULL, n), \
+ .priority = pri, .msb[0] = rm, .lsb[0] = rl, .mask[0] = m, \
+ .shift[0] = s,}
+
+#define PWRITE(name, n, pri, rm, rl, m, s, r) \
+ {.sda = SENSOR_ATTR(name, S_IRUGO | S_IWUSR, show_##r, store_##r, n), \
+ .priority = pri, .msb[0] = rm, .lsb[0] = rl, .mask[0] = m, \
+ .shift[0] = s,}
+
+/*
+ * PWRITEM assumes that the initializers for the .msb, .lsb, .mask and .shift
+ * were created using the VAA macro.
+ */
+#define PWRITEM(name, n, pri, rm, rl, m, s, r) \
+ {.sda = SENSOR_ATTR(name, S_IRUGO | S_IWUSR, show_##r, store_##r, n), \
+ .priority = pri, .msb = rm, .lsb = rl, .mask = m, .shift = s,}
+
+static struct asc7621_param asc7621_params[] = {
+ PREAD(in0_input, 0, PRI_HIGH, 0x20, 0x13, 0, 0, in10),
+ PREAD(in1_input, 1, PRI_HIGH, 0x21, 0x18, 0, 0, in10),
+ PREAD(in2_input, 2, PRI_HIGH, 0x22, 0x11, 0, 0, in10),
+ PREAD(in3_input, 3, PRI_HIGH, 0x23, 0x12, 0, 0, in10),
+ PREAD(in4_input, 4, PRI_HIGH, 0x24, 0x14, 0, 0, in10),
+
+ PWRITE(in0_min, 0, PRI_LOW, 0x44, 0, 0, 0, in8),
+ PWRITE(in1_min, 1, PRI_LOW, 0x46, 0, 0, 0, in8),
+ PWRITE(in2_min, 2, PRI_LOW, 0x48, 0, 0, 0, in8),
+ PWRITE(in3_min, 3, PRI_LOW, 0x4a, 0, 0, 0, in8),
+ PWRITE(in4_min, 4, PRI_LOW, 0x4c, 0, 0, 0, in8),
+
+ PWRITE(in0_max, 0, PRI_LOW, 0x45, 0, 0, 0, in8),
+ PWRITE(in1_max, 1, PRI_LOW, 0x47, 0, 0, 0, in8),
+ PWRITE(in2_max, 2, PRI_LOW, 0x49, 0, 0, 0, in8),
+ PWRITE(in3_max, 3, PRI_LOW, 0x4b, 0, 0, 0, in8),
+ PWRITE(in4_max, 4, PRI_LOW, 0x4d, 0, 0, 0, in8),
+
+ PREAD(in0_alarm, 0, PRI_LOW, 0x41, 0, 0x01, 0, bitmask),
+ PREAD(in1_alarm, 1, PRI_LOW, 0x41, 0, 0x01, 1, bitmask),
+ PREAD(in2_alarm, 2, PRI_LOW, 0x41, 0, 0x01, 2, bitmask),
+ PREAD(in3_alarm, 3, PRI_LOW, 0x41, 0, 0x01, 3, bitmask),
+ PREAD(in4_alarm, 4, PRI_LOW, 0x42, 0, 0x01, 0, bitmask),
+
+ PREAD(fan1_input, 0, PRI_HIGH, 0x29, 0x28, 0, 0, fan16),
+ PREAD(fan2_input, 1, PRI_HIGH, 0x2b, 0x2a, 0, 0, fan16),
+ PREAD(fan3_input, 2, PRI_HIGH, 0x2d, 0x2c, 0, 0, fan16),
+ PREAD(fan4_input, 3, PRI_HIGH, 0x2f, 0x2e, 0, 0, fan16),
+
+ PWRITE(fan1_min, 0, PRI_LOW, 0x55, 0x54, 0, 0, fan16),
+ PWRITE(fan2_min, 1, PRI_LOW, 0x57, 0x56, 0, 0, fan16),
+ PWRITE(fan3_min, 2, PRI_LOW, 0x59, 0x58, 0, 0, fan16),
+ PWRITE(fan4_min, 3, PRI_LOW, 0x5b, 0x5a, 0, 0, fan16),
+
+ PREAD(fan1_alarm, 0, PRI_LOW, 0x42, 0, 0x01, 0, bitmask),
+ PREAD(fan2_alarm, 1, PRI_LOW, 0x42, 0, 0x01, 1, bitmask),
+ PREAD(fan3_alarm, 2, PRI_LOW, 0x42, 0, 0x01, 2, bitmask),
+ PREAD(fan4_alarm, 3, PRI_LOW, 0x42, 0, 0x01, 3, bitmask),
+
+ PREAD(temp1_input, 0, PRI_HIGH, 0x25, 0x10, 0, 0, temp10),
+ PREAD(temp2_input, 1, PRI_HIGH, 0x26, 0x15, 0, 0, temp10),
+ PREAD(temp3_input, 2, PRI_HIGH, 0x27, 0x16, 0, 0, temp10),
+ PREAD(temp4_input, 3, PRI_HIGH, 0x33, 0x17, 0, 0, temp10),
+ PREAD(temp5_input, 4, PRI_HIGH, 0xf7, 0xf6, 0, 0, temp10),
+ PREAD(temp6_input, 5, PRI_HIGH, 0xf9, 0xf8, 0, 0, temp10),
+ PREAD(temp7_input, 6, PRI_HIGH, 0xfb, 0xfa, 0, 0, temp10),
+ PREAD(temp8_input, 7, PRI_HIGH, 0xfd, 0xfc, 0, 0, temp10),
+
+ PWRITE(temp1_min, 0, PRI_LOW, 0x4e, 0, 0, 0, temp8),
+ PWRITE(temp2_min, 1, PRI_LOW, 0x50, 0, 0, 0, temp8),
+ PWRITE(temp3_min, 2, PRI_LOW, 0x52, 0, 0, 0, temp8),
+ PWRITE(temp4_min, 3, PRI_LOW, 0x34, 0, 0, 0, temp8),
+
+ PWRITE(temp1_max, 0, PRI_LOW, 0x4f, 0, 0, 0, temp8),
+ PWRITE(temp2_max, 1, PRI_LOW, 0x51, 0, 0, 0, temp8),
+ PWRITE(temp3_max, 2, PRI_LOW, 0x53, 0, 0, 0, temp8),
+ PWRITE(temp4_max, 3, PRI_LOW, 0x35, 0, 0, 0, temp8),
+
+ PREAD(temp1_alarm, 0, PRI_LOW, 0x41, 0, 0x01, 4, bitmask),
+ PREAD(temp2_alarm, 1, PRI_LOW, 0x41, 0, 0x01, 5, bitmask),
+ PREAD(temp3_alarm, 2, PRI_LOW, 0x41, 0, 0x01, 6, bitmask),
+ PREAD(temp4_alarm, 3, PRI_LOW, 0x43, 0, 0x01, 0, bitmask),
+
+ PWRITE(temp1_source, 0, PRI_LOW, 0x02, 0, 0x07, 4, bitmask),
+ PWRITE(temp2_source, 1, PRI_LOW, 0x02, 0, 0x07, 0, bitmask),
+ PWRITE(temp3_source, 2, PRI_LOW, 0x03, 0, 0x07, 4, bitmask),
+ PWRITE(temp4_source, 3, PRI_LOW, 0x03, 0, 0x07, 0, bitmask),
+
+ PWRITE(temp1_smoothing_enable, 0, PRI_LOW, 0x62, 0, 0x01, 3, bitmask),
+ PWRITE(temp2_smoothing_enable, 1, PRI_LOW, 0x63, 0, 0x01, 7, bitmask),
+ PWRITE(temp3_smoothing_enable, 2, PRI_LOW, 0x64, 0, 0x01, 3, bitmask),
+ PWRITE(temp4_smoothing_enable, 3, PRI_LOW, 0x3c, 0, 0x01, 3, bitmask),
+
+ PWRITE(temp1_smoothing_time, 0, PRI_LOW, 0x62, 0, 0x07, 0, temp_st),
+ PWRITE(temp2_smoothing_time, 1, PRI_LOW, 0x63, 0, 0x07, 4, temp_st),
+ PWRITE(temp3_smoothing_time, 2, PRI_LOW, 0x63, 0, 0x07, 0, temp_st),
+ PWRITE(temp4_smoothing_time, 3, PRI_LOW, 0x3c, 0, 0x07, 0, temp_st),
+
+ PWRITE(temp1_auto_point1_temp_hyst, 0, PRI_LOW, 0x6d, 0, 0x0f, 4,
+ bitmask),
+ PWRITE(temp2_auto_point1_temp_hyst, 1, PRI_LOW, 0x6d, 0, 0x0f, 0,
+ bitmask),
+ PWRITE(temp3_auto_point1_temp_hyst, 2, PRI_LOW, 0x6e, 0, 0x0f, 4,
+ bitmask),
+ PWRITE(temp4_auto_point1_temp_hyst, 3, PRI_LOW, 0x6e, 0, 0x0f, 0,
+ bitmask),
+
+ PREAD(temp1_auto_point2_temp_hyst, 0, PRI_LOW, 0x6d, 0, 0x0f, 4,
+ bitmask),
+ PREAD(temp2_auto_point2_temp_hyst, 1, PRI_LOW, 0x6d, 0, 0x0f, 0,
+ bitmask),
+ PREAD(temp3_auto_point2_temp_hyst, 2, PRI_LOW, 0x6e, 0, 0x0f, 4,
+ bitmask),
+ PREAD(temp4_auto_point2_temp_hyst, 3, PRI_LOW, 0x6e, 0, 0x0f, 0,
+ bitmask),
+
+ PWRITE(temp1_auto_point1_temp, 0, PRI_LOW, 0x67, 0, 0, 0, temp8),
+ PWRITE(temp2_auto_point1_temp, 1, PRI_LOW, 0x68, 0, 0, 0, temp8),
+ PWRITE(temp3_auto_point1_temp, 2, PRI_LOW, 0x69, 0, 0, 0, temp8),
+ PWRITE(temp4_auto_point1_temp, 3, PRI_LOW, 0x3b, 0, 0, 0, temp8),
+
+ PWRITEM(temp1_auto_point2_temp, 0, PRI_LOW, VAA(0x5f, 0x67), VAA(0),
+ VAA(0x0f), VAA(4), ap2_temp),
+ PWRITEM(temp2_auto_point2_temp, 1, PRI_LOW, VAA(0x60, 0x68), VAA(0),
+ VAA(0x0f), VAA(4), ap2_temp),
+ PWRITEM(temp3_auto_point2_temp, 2, PRI_LOW, VAA(0x61, 0x69), VAA(0),
+ VAA(0x0f), VAA(4), ap2_temp),
+ PWRITEM(temp4_auto_point2_temp, 3, PRI_LOW, VAA(0x3c, 0x3b), VAA(0),
+ VAA(0x0f), VAA(4), ap2_temp),
+
+ PWRITE(temp1_crit, 0, PRI_LOW, 0x6a, 0, 0, 0, temp8),
+ PWRITE(temp2_crit, 1, PRI_LOW, 0x6b, 0, 0, 0, temp8),
+ PWRITE(temp3_crit, 2, PRI_LOW, 0x6c, 0, 0, 0, temp8),
+ PWRITE(temp4_crit, 3, PRI_LOW, 0x3d, 0, 0, 0, temp8),
+
+ PWRITE(temp5_enable, 4, PRI_LOW, 0x0e, 0, 0x01, 0, bitmask),
+ PWRITE(temp6_enable, 5, PRI_LOW, 0x0e, 0, 0x01, 1, bitmask),
+ PWRITE(temp7_enable, 6, PRI_LOW, 0x0e, 0, 0x01, 2, bitmask),
+ PWRITE(temp8_enable, 7, PRI_LOW, 0x0e, 0, 0x01, 3, bitmask),
+
+ PWRITE(remote1_offset, 0, PRI_LOW, 0x1c, 0, 0, 0, temp62),
+ PWRITE(remote2_offset, 1, PRI_LOW, 0x1d, 0, 0, 0, temp62),
+
+ PWRITE(pwm1, 0, PRI_HIGH, 0x30, 0, 0, 0, u8),
+ PWRITE(pwm2, 1, PRI_HIGH, 0x31, 0, 0, 0, u8),
+ PWRITE(pwm3, 2, PRI_HIGH, 0x32, 0, 0, 0, u8),
+
+ PWRITE(pwm1_invert, 0, PRI_LOW, 0x5c, 0, 0x01, 4, bitmask),
+ PWRITE(pwm2_invert, 1, PRI_LOW, 0x5d, 0, 0x01, 4, bitmask),
+ PWRITE(pwm3_invert, 2, PRI_LOW, 0x5e, 0, 0x01, 4, bitmask),
+
+ PWRITEM(pwm1_enable, 0, PRI_LOW, VAA(0x5c, 0x5c, 0x62), VAA(0, 0, 0),
+ VAA(0x07, 0x01, 0x01), VAA(5, 3, 5), pwm_enable),
+ PWRITEM(pwm2_enable, 1, PRI_LOW, VAA(0x5d, 0x5d, 0x62), VAA(0, 0, 0),
+ VAA(0x07, 0x01, 0x01), VAA(5, 3, 6), pwm_enable),
+ PWRITEM(pwm3_enable, 2, PRI_LOW, VAA(0x5e, 0x5e, 0x62), VAA(0, 0, 0),
+ VAA(0x07, 0x01, 0x01), VAA(5, 3, 7), pwm_enable),
+
+ PWRITEM(pwm1_auto_channels, 0, PRI_LOW, VAA(0x5c, 0x5c), VAA(0, 0),
+ VAA(0x07, 0x01), VAA(5, 3), pwm_ac),
+ PWRITEM(pwm2_auto_channels, 1, PRI_LOW, VAA(0x5d, 0x5d), VAA(0, 0),
+ VAA(0x07, 0x01), VAA(5, 3), pwm_ac),
+ PWRITEM(pwm3_auto_channels, 2, PRI_LOW, VAA(0x5e, 0x5e), VAA(0, 0),
+ VAA(0x07, 0x01), VAA(5, 3), pwm_ac),
+
+ PWRITE(pwm1_auto_point1_pwm, 0, PRI_LOW, 0x64, 0, 0, 0, u8),
+ PWRITE(pwm2_auto_point1_pwm, 1, PRI_LOW, 0x65, 0, 0, 0, u8),
+ PWRITE(pwm3_auto_point1_pwm, 2, PRI_LOW, 0x66, 0, 0, 0, u8),
+
+ PWRITE(pwm1_auto_point2_pwm, 0, PRI_LOW, 0x38, 0, 0, 0, u8),
+ PWRITE(pwm2_auto_point2_pwm, 1, PRI_LOW, 0x39, 0, 0, 0, u8),
+ PWRITE(pwm3_auto_point2_pwm, 2, PRI_LOW, 0x3a, 0, 0, 0, u8),
+
+ PWRITE(pwm1_freq, 0, PRI_LOW, 0x5f, 0, 0x0f, 0, pwm_freq),
+ PWRITE(pwm2_freq, 1, PRI_LOW, 0x60, 0, 0x0f, 0, pwm_freq),
+ PWRITE(pwm3_freq, 2, PRI_LOW, 0x61, 0, 0x0f, 0, pwm_freq),
+
+ PREAD(pwm1_auto_zone_assigned, 0, PRI_LOW, 0, 0, 0x03, 2, bitmask),
+ PREAD(pwm2_auto_zone_assigned, 1, PRI_LOW, 0, 0, 0x03, 4, bitmask),
+ PREAD(pwm3_auto_zone_assigned, 2, PRI_LOW, 0, 0, 0x03, 6, bitmask),
+
+ PWRITE(pwm1_auto_spinup_time, 0, PRI_LOW, 0x5c, 0, 0x07, 0, pwm_ast),
+ PWRITE(pwm2_auto_spinup_time, 1, PRI_LOW, 0x5d, 0, 0x07, 0, pwm_ast),
+ PWRITE(pwm3_auto_spinup_time, 2, PRI_LOW, 0x5e, 0, 0x07, 0, pwm_ast),
+
+ PWRITE(peci_enable, 0, PRI_LOW, 0x40, 0, 0x01, 4, bitmask),
+ PWRITE(peci_avg, 0, PRI_LOW, 0x36, 0, 0x07, 0, bitmask),
+ PWRITE(peci_domain, 0, PRI_LOW, 0x36, 0, 0x01, 3, bitmask),
+ PWRITE(peci_legacy, 0, PRI_LOW, 0x36, 0, 0x01, 4, bitmask),
+ PWRITE(peci_diode, 0, PRI_LOW, 0x0e, 0, 0x07, 4, bitmask),
+ PWRITE(peci_4domain, 0, PRI_LOW, 0x0e, 0, 0x01, 4, bitmask),
+
+};
+
+static struct asc7621_data *asc7621_update_device(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct asc7621_data *data = i2c_get_clientdata(client);
+ int i;
+
+/*
+ * The asc7621 chips guarantee consistent reads of multi-byte values
+ * regardless of the order of the reads. No special logic is needed
+ * so we can just read the registers in whatever order they appear
+ * in the asc7621_params array.
+ */
+
+ mutex_lock(&data->update_lock);
+
+ /* Read all the high priority registers */
+
+ if (!data->valid ||
+ time_after(jiffies, data->last_high_reading + INTERVAL_HIGH)) {
+
+ for (i = 0; i < ARRAY_SIZE(asc7621_register_priorities); i++) {
+ if (asc7621_register_priorities[i] == PRI_HIGH) {
+ data->reg[i] =
+ i2c_smbus_read_byte_data(client, i) & 0xff;
+ }
+ }
+ data->last_high_reading = jiffies;
+ }; /* last_reading */
+
+ /* Read all the low priority registers. */
+
+ if (!data->valid ||
+ time_after(jiffies, data->last_low_reading + INTERVAL_LOW)) {
+
+ for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) {
+ if (asc7621_register_priorities[i] == PRI_LOW) {
+ data->reg[i] =
+ i2c_smbus_read_byte_data(client, i) & 0xff;
+ }
+ }
+ data->last_low_reading = jiffies;
+ }; /* last_reading */
+
+ data->valid = 1;
+
+ mutex_unlock(&data->update_lock);
+
+ return data;
+}
+
+/*
+ * Standard detection and initialization below
+ *
+ * Helper function that checks if an address is valid
+ * for a particular chip.
+ */
+
+static inline int valid_address_for_chip(int chip_type, int address)
+{
+ int i;
+
+ for (i = 0; asc7621_chips[chip_type].addresses[i] != I2C_CLIENT_END;
+ i++) {
+ if (asc7621_chips[chip_type].addresses[i] == address)
+ return 1;
+ }
+ return 0;
+}
+
+static void asc7621_init_client(struct i2c_client *client)
+{
+ int value;
+
+ /* Warn if part was not "READY" */
+
+ value = read_byte(client, 0x40);
+
+ if (value & 0x02) {
+ dev_err(&client->dev,
+ "Client (%d,0x%02x) config is locked.\n",
+ i2c_adapter_id(client->adapter), client->addr);
+ };
+ if (!(value & 0x04)) {
+ dev_err(&client->dev, "Client (%d,0x%02x) is not ready.\n",
+ i2c_adapter_id(client->adapter), client->addr);
+ };
+
+/*
+ * Start monitoring
+ *
+ * Try to clear LOCK, Set START, save everything else
+ */
+ value = (value & ~0x02) | 0x01;
+ write_byte(client, 0x40, value & 0xff);
+
+}
+
+static int
+asc7621_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ struct asc7621_data *data;
+ int i, err;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -EIO;
+
+ data = kzalloc(sizeof(struct asc7621_data), GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, data);
+ data->valid = 0;
+ mutex_init(&data->update_lock);
+
+ /* Initialize the asc7621 chip */
+ asc7621_init_client(client);
+
+ /* Create the sysfs entries */
+ for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) {
+ err =
+ device_create_file(&client->dev,
+ &(asc7621_params[i].sda.dev_attr));
+ if (err)
+ goto exit_remove;
+ }
+
+ data->class_dev = hwmon_device_register(&client->dev);
+ if (IS_ERR(data->class_dev)) {
+ err = PTR_ERR(data->class_dev);
+ goto exit_remove;
+ }
+
+ return 0;
+
+exit_remove:
+ for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) {
+ device_remove_file(&client->dev,
+ &(asc7621_params[i].sda.dev_attr));
+ }
+
+ i2c_set_clientdata(client, NULL);
+ kfree(data);
+ return err;
+}
+
+static int asc7621_detect(struct i2c_client *client,
+ struct i2c_board_info *info)
+{
+ struct i2c_adapter *adapter = client->adapter;
+ int company, verstep, chip_index;
+ struct device *dev;
+
+ dev = &client->dev;
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+ return -ENODEV;
+
+ for (chip_index = FIRST_CHIP; chip_index <= LAST_CHIP; chip_index++) {
+
+ if (!valid_address_for_chip(chip_index, client->addr))
+ continue;
+
+ company = read_byte(client,
+ asc7621_chips[chip_index].company_reg);
+ verstep = read_byte(client,
+ asc7621_chips[chip_index].verstep_reg);
+
+ if (company == asc7621_chips[chip_index].company_id &&
+ verstep == asc7621_chips[chip_index].verstep_id) {
+ strlcpy(client->name, asc7621_chips[chip_index].name,
+ I2C_NAME_SIZE);
+ strlcpy(info->type, asc7621_chips[chip_index].name,
+ I2C_NAME_SIZE);
+
+ dev_info(&adapter->dev, "Matched %s\n",
+ asc7621_chips[chip_index].name);
+ return 0;
+ }
+ }
+
+ return -ENODEV;
+}
+
+static int asc7621_remove(struct i2c_client *client)
+{
+ struct asc7621_data *data = i2c_get_clientdata(client);
+ int i;
+
+ hwmon_device_unregister(data->class_dev);
+
+ for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) {
+ device_remove_file(&client->dev,
+ &(asc7621_params[i].sda.dev_attr));
+ }
+
+ i2c_set_clientdata(client, NULL);
+ kfree(data);
+ return 0;
+}
+
+static const struct i2c_device_id asc7621_id[] = {
+ {"asc7621", asc7621},
+ {"asc7621a", asc7621a},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, asc7621_id);
+
+static struct i2c_driver asc7621_driver = {
+ .class = I2C_CLASS_HWMON,
+ .driver = {
+ .name = "asc7621",
+ },
+ .probe = asc7621_probe,
+ .remove = asc7621_remove,
+ .id_table = asc7621_id,
+ .detect = asc7621_detect,
+ .address_list = normal_i2c,
+};
+
+static int __init sm_asc7621_init(void)
+{
+ int i, j;
+/*
+ * Collect all the registers needed into a single array.
+ * This way, if a register isn't actually used for anything,
+ * we don't retrieve it.
+ */
+
+ for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) {
+ for (j = 0; j < ARRAY_SIZE(asc7621_params[i].msb); j++)
+ asc7621_register_priorities[asc7621_params[i].msb[j]] =
+ asc7621_params[i].priority;
+ for (j = 0; j < ARRAY_SIZE(asc7621_params[i].lsb); j++)
+ asc7621_register_priorities[asc7621_params[i].lsb[j]] =
+ asc7621_params[i].priority;
+ }
+ return i2c_add_driver(&asc7621_driver);
+}
+
+static void __exit sm_asc7621_exit(void)
+{
+ i2c_del_driver(&asc7621_driver);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("George Joseph");
+MODULE_DESCRIPTION("Andigilog aSC7621 and aSC7621a driver");
+
+module_init(sm_asc7621_init);
+module_exit(sm_asc7621_exit);
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c
index fa0728232e7..0627f7a5b9b 100644
--- a/drivers/hwmon/fschmd.c
+++ b/drivers/hwmon/fschmd.c
@@ -267,7 +267,7 @@ struct fschmd_data {
struct list_head list; /* member of the watchdog_data_list */
struct kref kref;
struct miscdevice watchdog_miscdev;
- int kind;
+ enum chips kind;
unsigned long watchdog_is_open;
char watchdog_expect_close;
char watchdog_name[10]; /* must be unique to avoid sysfs conflict */
@@ -325,8 +325,7 @@ static ssize_t show_in_value(struct device *dev,
int index = to_sensor_dev_attr(devattr)->index;
struct fschmd_data *data = fschmd_update_device(dev);
- /* fscher / fschrc - 1 as data->kind is an array index, not a chips */
- if (data->kind == (fscher - 1) || data->kind >= (fschrc - 1))
+ if (data->kind == fscher || data->kind >= fschrc)
return sprintf(buf, "%d\n", (data->volt[index] * dmi_vref *
dmi_mult[index]) / 255 + dmi_offset[index]);
else
@@ -492,7 +491,7 @@ static ssize_t show_pwm_auto_point1_pwm(struct device *dev,
int val = data->fan_min[index];
/* 0 = allow turning off (except on the syl), 1-255 = 50-100% */
- if (val || data->kind == fscsyl - 1)
+ if (val || data->kind == fscsyl)
val = val / 2 + 128;
return sprintf(buf, "%d\n", val);
@@ -506,7 +505,7 @@ static ssize_t store_pwm_auto_point1_pwm(struct device *dev,
unsigned long v = simple_strtoul(buf, NULL, 10);
/* reg: 0 = allow turning off (except on the syl), 1-255 = 50-100% */
- if (v || data->kind == fscsyl - 1) {
+ if (v || data->kind == fscsyl) {
v = SENSORS_LIMIT(v, 128, 255);
v = (v - 128) * 2 + 1;
}
@@ -1037,7 +1036,7 @@ static int fschmd_detect(struct i2c_client *client,
else
return -ENODEV;
- strlcpy(info->type, fschmd_id[kind - 1].name, I2C_NAME_SIZE);
+ strlcpy(info->type, fschmd_id[kind].name, I2C_NAME_SIZE);
return 0;
}
@@ -1065,6 +1064,7 @@ static int fschmd_probe(struct i2c_client *client,
(where the client is found through a data ptr instead of the
otherway around) */
data->client = client;
+ data->kind = kind;
if (kind == fscpos) {
/* The Poseidon has hardwired temp limits, fill these
@@ -1085,9 +1085,6 @@ static int fschmd_probe(struct i2c_client *client,
}
}
- /* i2c kind goes from 1-6, we want from 0-5 to address arrays */
- data->kind = kind - 1;
-
/* Read in some never changing registers */
data->revision = i2c_smbus_read_byte_data(client, FSCHMD_REG_REVISION);
data->global_control = i2c_smbus_read_byte_data(client,
diff --git a/drivers/hwmon/g760a.c b/drivers/hwmon/g760a.c
index 19c01a49f6b..09ea12e0a55 100644
--- a/drivers/hwmon/g760a.c
+++ b/drivers/hwmon/g760a.c
@@ -68,7 +68,7 @@ struct g760a_data {
#define PWM_FROM_CNT(cnt) (0xff-(cnt))
#define PWM_TO_CNT(pwm) (0xff-(pwm))
-unsigned int rpm_from_cnt(u8 val, u32 clk, u16 div)
+static inline unsigned int rpm_from_cnt(u8 val, u32 clk, u16 div)
{
return ((val == 0x00) ? 0 : ((clk*30)/(val*div)));
}
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 0ffe84d190b..1002befd87d 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -1,40 +1,40 @@
/*
- it87.c - Part of lm_sensors, Linux kernel modules for hardware
- monitoring.
-
- The IT8705F is an LPC-based Super I/O part that contains UARTs, a
- parallel port, an IR port, a MIDI port, a floppy controller, etc., in
- addition to an Environment Controller (Enhanced Hardware Monitor and
- Fan Controller)
-
- This driver supports only the Environment Controller in the IT8705F and
- similar parts. The other devices are supported by different drivers.
-
- Supports: IT8705F Super I/O chip w/LPC interface
- IT8712F Super I/O chip w/LPC interface
- IT8716F Super I/O chip w/LPC interface
- IT8718F Super I/O chip w/LPC interface
- IT8720F Super I/O chip w/LPC interface
- IT8726F Super I/O chip w/LPC interface
- Sis950 A clone of the IT8705F
-
- Copyright (C) 2001 Chris Gauthron
- Copyright (C) 2005-2007 Jean Delvare <khali@linux-fr.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
+ * it87.c - Part of lm_sensors, Linux kernel modules for hardware
+ * monitoring.
+ *
+ * The IT8705F is an LPC-based Super I/O part that contains UARTs, a
+ * parallel port, an IR port, a MIDI port, a floppy controller, etc., in
+ * addition to an Environment Controller (Enhanced Hardware Monitor and
+ * Fan Controller)
+ *
+ * This driver supports only the Environment Controller in the IT8705F and
+ * similar parts. The other devices are supported by different drivers.
+ *
+ * Supports: IT8705F Super I/O chip w/LPC interface
+ * IT8712F Super I/O chip w/LPC interface
+ * IT8716F Super I/O chip w/LPC interface
+ * IT8718F Super I/O chip w/LPC interface
+ * IT8720F Super I/O chip w/LPC interface
+ * IT8726F Super I/O chip w/LPC interface
+ * Sis950 A clone of the IT8705F
+ *
+ * Copyright (C) 2001 Chris Gauthron
+ * Copyright (C) 2005-2010 Jean Delvare <khali@linux-fr.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
#include <linux/module.h>
#include <linux/init.h>
@@ -128,6 +128,7 @@ superio_exit(void)
#define IT87_SIO_GPIO5_REG 0x29
#define IT87_SIO_PINX2_REG 0x2c /* Pin selection */
#define IT87_SIO_VID_REG 0xfc /* VID value */
+#define IT87_SIO_BEEP_PIN_REG 0xf6 /* Beep pin mapping */
/* Update battery voltage after every reading if true */
static int update_vbat;
@@ -187,9 +188,13 @@ static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 };
#define IT87_REG_VIN_ENABLE 0x50
#define IT87_REG_TEMP_ENABLE 0x51
+#define IT87_REG_BEEP_ENABLE 0x5c
#define IT87_REG_CHIPID 0x58
+#define IT87_REG_AUTO_TEMP(nr, i) (0x60 + (nr) * 8 + (i))
+#define IT87_REG_AUTO_PWM(nr, i) (0x65 + (nr) * 8 + (i))
+
#define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 8)/16),0,255))
#define IN_FROM_REG(val) ((val) * 16)
@@ -246,6 +251,7 @@ struct it87_sio_data {
/* Values read from Super-I/O config space */
u8 revision;
u8 vid_value;
+ u8 beep_pin;
/* Features skipped based on config or DMI */
u8 skip_vid;
u8 skip_fan;
@@ -279,9 +285,21 @@ struct it87_data {
u8 vid; /* Register encoding, combined */
u8 vrm;
u32 alarms; /* Register encoding, combined */
+ u8 beeps; /* Register encoding */
u8 fan_main_ctrl; /* Register value */
u8 fan_ctl; /* Register value */
- u8 manual_pwm_ctl[3]; /* manual PWM value set by user */
+
+ /* The following 3 arrays correspond to the same registers. The
+ * meaning of bits 6-0 depends on the value of bit 7, and we want
+ * to preserve settings on mode changes, so we have to track all
+ * values separately. */
+ u8 pwm_ctrl[3]; /* Register value */
+ u8 pwm_duty[3]; /* Manual PWM value set by user (bit 6-0) */
+ u8 pwm_temp_map[3]; /* PWM to temp. chan. mapping (bits 1-0) */
+
+ /* Automatic fan speed control registers */
+ u8 auto_pwm[3][4]; /* [nr][3] is hard-coded */
+ s8 auto_temp[3][5]; /* [nr][0] is point1_temp_hyst */
};
static inline int has_16bit_fans(const struct it87_data *data)
@@ -296,6 +314,15 @@ static inline int has_16bit_fans(const struct it87_data *data)
|| data->type == it8720;
}
+static inline int has_old_autopwm(const struct it87_data *data)
+{
+ /* The old automatic fan speed control interface is implemented
+ by IT8705F chips up to revision F and IT8712F chips up to
+ revision G. */
+ return (data->type == it87 && data->revision < 0x03)
+ || (data->type == it8712 && data->revision < 0x08);
+}
+
static int it87_probe(struct platform_device *pdev);
static int __devexit it87_remove(struct platform_device *pdev);
@@ -352,7 +379,10 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
int nr = sensor_attr->index;
struct it87_data *data = dev_get_drvdata(dev);
- unsigned long val = simple_strtoul(buf, NULL, 10);
+ unsigned long val;
+
+ if (strict_strtoul(buf, 10, &val) < 0)
+ return -EINVAL;
mutex_lock(&data->update_lock);
data->in_min[nr] = IN_TO_REG(val);
@@ -368,7 +398,10 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
int nr = sensor_attr->index;
struct it87_data *data = dev_get_drvdata(dev);
- unsigned long val = simple_strtoul(buf, NULL, 10);
+ unsigned long val;
+
+ if (strict_strtoul(buf, 10, &val) < 0)
+ return -EINVAL;
mutex_lock(&data->update_lock);
data->in_max[nr] = IN_TO_REG(val);
@@ -441,7 +474,10 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
int nr = sensor_attr->index;
struct it87_data *data = dev_get_drvdata(dev);
- int val = simple_strtol(buf, NULL, 10);
+ long val;
+
+ if (strict_strtol(buf, 10, &val) < 0)
+ return -EINVAL;
mutex_lock(&data->update_lock);
data->temp_high[nr] = TEMP_TO_REG(val);
@@ -456,7 +492,10 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
int nr = sensor_attr->index;
struct it87_data *data = dev_get_drvdata(dev);
- int val = simple_strtol(buf, NULL, 10);
+ long val;
+
+ if (strict_strtol(buf, 10, &val) < 0)
+ return -EINVAL;
mutex_lock(&data->update_lock);
data->temp_low[nr] = TEMP_TO_REG(val);
@@ -483,8 +522,9 @@ static ssize_t show_sensor(struct device *dev, struct device_attribute *attr,
int nr = sensor_attr->index;
struct it87_data *data = it87_update_device(dev);
- u8 reg = data->sensor; /* In case the value is updated while we use it */
-
+ u8 reg = data->sensor; /* In case the value is updated while
+ we use it */
+
if (reg & (1 << nr))
return sprintf(buf, "3\n"); /* thermal diode */
if (reg & (8 << nr))
@@ -498,7 +538,10 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr,
int nr = sensor_attr->index;
struct it87_data *data = dev_get_drvdata(dev);
- int val = simple_strtol(buf, NULL, 10);
+ long val;
+
+ if (strict_strtol(buf, 10, &val) < 0)
+ return -EINVAL;
mutex_lock(&data->update_lock);
@@ -511,9 +554,9 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr,
}
/* 3 = thermal diode; 4 = thermistor; 0 = disabled */
if (val == 3)
- data->sensor |= 1 << nr;
+ data->sensor |= 1 << nr;
else if (val == 4)
- data->sensor |= 8 << nr;
+ data->sensor |= 8 << nr;
else if (val != 0) {
mutex_unlock(&data->update_lock);
return -EINVAL;
@@ -531,6 +574,19 @@ show_sensor_offset(2);
show_sensor_offset(3);
/* 3 Fans */
+
+static int pwm_mode(const struct it87_data *data, int nr)
+{
+ int ctrl = data->fan_main_ctrl & (1 << nr);
+
+ if (ctrl == 0) /* Full speed */
+ return 0;
+ if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */
+ return 2;
+ else /* Manual mode */
+ return 1;
+}
+
static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -538,7 +594,7 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
int nr = sensor_attr->index;
struct it87_data *data = it87_update_device(dev);
- return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan[nr],
+ return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
DIV_FROM_REG(data->fan_div[nr])));
}
static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
@@ -548,8 +604,8 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr,
int nr = sensor_attr->index;
struct it87_data *data = it87_update_device(dev);
- return sprintf(buf,"%d\n",
- FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])));
+ return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
+ DIV_FROM_REG(data->fan_div[nr])));
}
static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -560,14 +616,14 @@ static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
struct it87_data *data = it87_update_device(dev);
return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
}
-static ssize_t show_pwm_enable(struct device *dev, struct device_attribute *attr,
- char *buf)
+static ssize_t show_pwm_enable(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
int nr = sensor_attr->index;
struct it87_data *data = it87_update_device(dev);
- return sprintf(buf,"%d\n", (data->fan_main_ctrl & (1 << nr)) ? 1 : 0);
+ return sprintf(buf, "%d\n", pwm_mode(data, nr));
}
static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -576,7 +632,7 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
int nr = sensor_attr->index;
struct it87_data *data = it87_update_device(dev);
- return sprintf(buf,"%d\n", data->manual_pwm_ctl[nr]);
+ return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm_duty[nr]));
}
static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -593,15 +649,24 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
int nr = sensor_attr->index;
struct it87_data *data = dev_get_drvdata(dev);
- int val = simple_strtol(buf, NULL, 10);
+ long val;
u8 reg;
+ if (strict_strtol(buf, 10, &val) < 0)
+ return -EINVAL;
+
mutex_lock(&data->update_lock);
reg = it87_read_value(data, IT87_REG_FAN_DIV);
switch (nr) {
- case 0: data->fan_div[nr] = reg & 0x07; break;
- case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break;
- case 2: data->fan_div[nr] = (reg & 0x40) ? 3 : 1; break;
+ case 0:
+ data->fan_div[nr] = reg & 0x07;
+ break;
+ case 1:
+ data->fan_div[nr] = (reg >> 3) & 0x07;
+ break;
+ case 2:
+ data->fan_div[nr] = (reg & 0x40) ? 3 : 1;
+ break;
}
data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
@@ -616,10 +681,13 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
int nr = sensor_attr->index;
struct it87_data *data = dev_get_drvdata(dev);
- unsigned long val = simple_strtoul(buf, NULL, 10);
+ unsigned long val;
int min;
u8 old;
+ if (strict_strtoul(buf, 10, &val) < 0)
+ return -EINVAL;
+
mutex_lock(&data->update_lock);
old = it87_read_value(data, IT87_REG_FAN_DIV);
@@ -651,6 +719,32 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
mutex_unlock(&data->update_lock);
return count;
}
+
+/* Returns 0 if OK, -EINVAL otherwise */
+static int check_trip_points(struct device *dev, int nr)
+{
+ const struct it87_data *data = dev_get_drvdata(dev);
+ int i, err = 0;
+
+ if (has_old_autopwm(data)) {
+ for (i = 0; i < 3; i++) {
+ if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
+ err = -EINVAL;
+ }
+ for (i = 0; i < 2; i++) {
+ if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
+ err = -EINVAL;
+ }
+ }
+
+ if (err) {
+ dev_err(dev, "Inconsistent trip points, not switching to "
+ "automatic mode\n");
+ dev_err(dev, "Adjust the trip points and try again\n");
+ }
+ return err;
+}
+
static ssize_t set_pwm_enable(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
@@ -658,7 +752,16 @@ static ssize_t set_pwm_enable(struct device *dev,
int nr = sensor_attr->index;
struct it87_data *data = dev_get_drvdata(dev);
- int val = simple_strtol(buf, NULL, 10);
+ long val;
+
+ if (strict_strtol(buf, 10, &val) < 0 || val < 0 || val > 2)
+ return -EINVAL;
+
+ /* Check trip points before switching to automatic mode */
+ if (val == 2) {
+ if (check_trip_points(dev, nr) < 0)
+ return -EINVAL;
+ }
mutex_lock(&data->update_lock);
@@ -669,16 +772,18 @@ static ssize_t set_pwm_enable(struct device *dev,
it87_write_value(data, IT87_REG_FAN_CTL, tmp | (1 << nr));
/* set on/off mode */
data->fan_main_ctrl &= ~(1 << nr);
- it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
- } else if (val == 1) {
+ it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
+ data->fan_main_ctrl);
+ } else {
+ if (val == 1) /* Manual mode */
+ data->pwm_ctrl[nr] = data->pwm_duty[nr];
+ else /* Automatic mode */
+ data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
+ it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
/* set SmartGuardian mode */
data->fan_main_ctrl |= (1 << nr);
- it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
- /* set saved pwm value, clear FAN_CTLX PWM mode bit */
- it87_write_value(data, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr]));
- } else {
- mutex_unlock(&data->update_lock);
- return -EINVAL;
+ it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
+ data->fan_main_ctrl);
}
mutex_unlock(&data->update_lock);
@@ -691,15 +796,19 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
int nr = sensor_attr->index;
struct it87_data *data = dev_get_drvdata(dev);
- int val = simple_strtol(buf, NULL, 10);
+ long val;
- if (val < 0 || val > 255)
+ if (strict_strtol(buf, 10, &val) < 0 || val < 0 || val > 255)
return -EINVAL;
mutex_lock(&data->update_lock);
- data->manual_pwm_ctl[nr] = val;
- if (data->fan_main_ctrl & (1 << nr))
- it87_write_value(data, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr]));
+ data->pwm_duty[nr] = PWM_TO_REG(val);
+ /* If we are in manual mode, write the duty cycle immediately;
+ * otherwise, just store it for later use. */
+ if (!(data->pwm_ctrl[nr] & 0x80)) {
+ data->pwm_ctrl[nr] = data->pwm_duty[nr];
+ it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
+ }
mutex_unlock(&data->update_lock);
return count;
}
@@ -707,9 +816,12 @@ static ssize_t set_pwm_freq(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
struct it87_data *data = dev_get_drvdata(dev);
- unsigned long val = simple_strtoul(buf, NULL, 10);
+ unsigned long val;
int i;
+ if (strict_strtoul(buf, 10, &val) < 0)
+ return -EINVAL;
+
/* Search for the nearest available frequency */
for (i = 0; i < 7; i++) {
if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2)
@@ -724,6 +836,132 @@ static ssize_t set_pwm_freq(struct device *dev,
return count;
}
+static ssize_t show_pwm_temp_map(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
+ struct it87_data *data = it87_update_device(dev);
+ int map;
+
+ if (data->pwm_temp_map[nr] < 3)
+ map = 1 << data->pwm_temp_map[nr];
+ else
+ map = 0; /* Should never happen */
+ return sprintf(buf, "%d\n", map);
+}
+static ssize_t set_pwm_temp_map(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+ int nr = sensor_attr->index;
+
+ struct it87_data *data = dev_get_drvdata(dev);
+ long val;
+ u8 reg;
+
+ /* This check can go away if we ever support automatic fan speed
+ control on newer chips. */
+ if (!has_old_autopwm(data)) {
+ dev_notice(dev, "Mapping change disabled for safety reasons\n");
+ return -EINVAL;
+ }
+
+ if (strict_strtol(buf, 10, &val) < 0)
+ return -EINVAL;
+
+ switch (val) {
+ case (1 << 0):
+ reg = 0x00;
+ break;
+ case (1 << 1):
+ reg = 0x01;
+ break;
+ case (1 << 2):
+ reg = 0x02;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ mutex_lock(&data->update_lock);
+ data->pwm_temp_map[nr] = reg;
+ /* If we are in automatic mode, write the temp mapping immediately;
+ * otherwise, just store it for later use. */
+ if (data->pwm_ctrl[nr] & 0x80) {
+ data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr];
+ it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]);
+ }
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static ssize_t show_auto_pwm(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct it87_data *data = it87_update_device(dev);
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int point = sensor_attr->index;
+
+ return sprintf(buf, "%d\n", PWM_FROM_REG(data->auto_pwm[nr][point]));
+}
+
+static ssize_t set_auto_pwm(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct it87_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int point = sensor_attr->index;
+ long val;
+
+ if (strict_strtol(buf, 10, &val) < 0 || val < 0 || val > 255)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+ data->auto_pwm[nr][point] = PWM_TO_REG(val);
+ it87_write_value(data, IT87_REG_AUTO_PWM(nr, point),
+ data->auto_pwm[nr][point]);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static ssize_t show_auto_temp(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct it87_data *data = it87_update_device(dev);
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int point = sensor_attr->index;
+
+ return sprintf(buf, "%d\n", TEMP_FROM_REG(data->auto_temp[nr][point]));
+}
+
+static ssize_t set_auto_temp(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct it87_data *data = dev_get_drvdata(dev);
+ struct sensor_device_attribute_2 *sensor_attr =
+ to_sensor_dev_attr_2(attr);
+ int nr = sensor_attr->nr;
+ int point = sensor_attr->index;
+ long val;
+
+ if (strict_strtol(buf, 10, &val) < 0 || val < -128000 || val > 127000)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+ data->auto_temp[nr][point] = TEMP_TO_REG(val);
+ it87_write_value(data, IT87_REG_AUTO_TEMP(nr, point),
+ data->auto_temp[nr][point]);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
#define show_fan_offset(offset) \
static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
@@ -744,7 +982,36 @@ static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
show_pwm, set_pwm, offset - 1); \
static DEVICE_ATTR(pwm##offset##_freq, \
(offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO), \
- show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL));
+ show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL)); \
+static SENSOR_DEVICE_ATTR(pwm##offset##_auto_channels_temp, \
+ S_IRUGO | S_IWUSR, show_pwm_temp_map, set_pwm_temp_map, \
+ offset - 1); \
+static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_pwm, \
+ S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \
+ offset - 1, 0); \
+static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point2_pwm, \
+ S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \
+ offset - 1, 1); \
+static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point3_pwm, \
+ S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \
+ offset - 1, 2); \
+static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point4_pwm, \
+ S_IRUGO, show_auto_pwm, NULL, offset - 1, 3); \
+static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_temp, \
+ S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \
+ offset - 1, 1); \
+static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_temp_hyst, \
+ S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \
+ offset - 1, 0); \
+static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point2_temp, \
+ S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \
+ offset - 1, 2); \
+static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point3_temp, \
+ S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \
+ offset - 1, 3); \
+static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point4_temp, \
+ S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \
+ offset - 1, 4);
show_pwm_offset(1);
show_pwm_offset(2);
@@ -775,7 +1042,10 @@ static ssize_t set_fan16_min(struct device *dev, struct device_attribute *attr,
struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
int nr = sensor_attr->index;
struct it87_data *data = dev_get_drvdata(dev);
- int val = simple_strtol(buf, NULL, 10);
+ long val;
+
+ if (strict_strtol(buf, 10, &val) < 0)
+ return -EINVAL;
mutex_lock(&data->update_lock);
data->fan_min[nr] = FAN16_TO_REG(val);
@@ -805,7 +1075,8 @@ show_fan16_offset(4);
show_fan16_offset(5);
/* Alarms */
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct it87_data *data = it87_update_device(dev);
return sprintf(buf, "%u\n", data->alarms);
@@ -836,27 +1107,78 @@ static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 16);
static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 17);
static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 18);
-static ssize_t
-show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_beep(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ int bitnr = to_sensor_dev_attr(attr)->index;
+ struct it87_data *data = it87_update_device(dev);
+ return sprintf(buf, "%u\n", (data->beeps >> bitnr) & 1);
+}
+static ssize_t set_beep(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int bitnr = to_sensor_dev_attr(attr)->index;
+ struct it87_data *data = dev_get_drvdata(dev);
+ long val;
+
+ if (strict_strtol(buf, 10, &val) < 0
+ || (val != 0 && val != 1))
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+ data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE);
+ if (val)
+ data->beeps |= (1 << bitnr);
+ else
+ data->beeps &= ~(1 << bitnr);
+ it87_write_value(data, IT87_REG_BEEP_ENABLE, data->beeps);
+ mutex_unlock(&data->update_lock);
+ return count;
+}
+
+static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR,
+ show_beep, set_beep, 1);
+static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO, show_beep, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO, show_beep, NULL, 1);
+static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO, show_beep, NULL, 1);
+static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO, show_beep, NULL, 1);
+static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO, show_beep, NULL, 1);
+static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO, show_beep, NULL, 1);
+static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO, show_beep, NULL, 1);
+/* fanX_beep writability is set later */
+static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO, show_beep, set_beep, 0);
+static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO, show_beep, set_beep, 0);
+static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO, show_beep, set_beep, 0);
+static SENSOR_DEVICE_ATTR(fan4_beep, S_IRUGO, show_beep, set_beep, 0);
+static SENSOR_DEVICE_ATTR(fan5_beep, S_IRUGO, show_beep, set_beep, 0);
+static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR,
+ show_beep, set_beep, 2);
+static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO, show_beep, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO, show_beep, NULL, 2);
+
+static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct it87_data *data = dev_get_drvdata(dev);
return sprintf(buf, "%u\n", data->vrm);
}
-static ssize_t
-store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct it87_data *data = dev_get_drvdata(dev);
- u32 val;
+ unsigned long val;
+
+ if (strict_strtoul(buf, 10, &val) < 0)
+ return -EINVAL;
- val = simple_strtoul(buf, NULL, 10);
data->vrm = val;
return count;
}
static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg);
-static ssize_t
-show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct it87_data *data = it87_update_device(dev);
return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm));
@@ -931,51 +1253,176 @@ static const struct attribute_group it87_group = {
.attrs = it87_attributes,
};
-static struct attribute *it87_attributes_opt[] = {
+static struct attribute *it87_attributes_beep[] = {
+ &sensor_dev_attr_in0_beep.dev_attr.attr,
+ &sensor_dev_attr_in1_beep.dev_attr.attr,
+ &sensor_dev_attr_in2_beep.dev_attr.attr,
+ &sensor_dev_attr_in3_beep.dev_attr.attr,
+ &sensor_dev_attr_in4_beep.dev_attr.attr,
+ &sensor_dev_attr_in5_beep.dev_attr.attr,
+ &sensor_dev_attr_in6_beep.dev_attr.attr,
+ &sensor_dev_attr_in7_beep.dev_attr.attr,
+
+ &sensor_dev_attr_temp1_beep.dev_attr.attr,
+ &sensor_dev_attr_temp2_beep.dev_attr.attr,
+ &sensor_dev_attr_temp3_beep.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group it87_group_beep = {
+ .attrs = it87_attributes_beep,
+};
+
+static struct attribute *it87_attributes_fan16[5][3+1] = { {
&sensor_dev_attr_fan1_input16.dev_attr.attr,
&sensor_dev_attr_fan1_min16.dev_attr.attr,
+ &sensor_dev_attr_fan1_alarm.dev_attr.attr,
+ NULL
+}, {
&sensor_dev_attr_fan2_input16.dev_attr.attr,
&sensor_dev_attr_fan2_min16.dev_attr.attr,
+ &sensor_dev_attr_fan2_alarm.dev_attr.attr,
+ NULL
+}, {
&sensor_dev_attr_fan3_input16.dev_attr.attr,
&sensor_dev_attr_fan3_min16.dev_attr.attr,
+ &sensor_dev_attr_fan3_alarm.dev_attr.attr,
+ NULL
+}, {
&sensor_dev_attr_fan4_input16.dev_attr.attr,
&sensor_dev_attr_fan4_min16.dev_attr.attr,
+ &sensor_dev_attr_fan4_alarm.dev_attr.attr,
+ NULL
+}, {
&sensor_dev_attr_fan5_input16.dev_attr.attr,
&sensor_dev_attr_fan5_min16.dev_attr.attr,
+ &sensor_dev_attr_fan5_alarm.dev_attr.attr,
+ NULL
+} };
+
+static const struct attribute_group it87_group_fan16[5] = {
+ { .attrs = it87_attributes_fan16[0] },
+ { .attrs = it87_attributes_fan16[1] },
+ { .attrs = it87_attributes_fan16[2] },
+ { .attrs = it87_attributes_fan16[3] },
+ { .attrs = it87_attributes_fan16[4] },
+};
+static struct attribute *it87_attributes_fan[3][4+1] = { {
&sensor_dev_attr_fan1_input.dev_attr.attr,
&sensor_dev_attr_fan1_min.dev_attr.attr,
&sensor_dev_attr_fan1_div.dev_attr.attr,
+ &sensor_dev_attr_fan1_alarm.dev_attr.attr,
+ NULL
+}, {
&sensor_dev_attr_fan2_input.dev_attr.attr,
&sensor_dev_attr_fan2_min.dev_attr.attr,
&sensor_dev_attr_fan2_div.dev_attr.attr,
+ &sensor_dev_attr_fan2_alarm.dev_attr.attr,
+ NULL
+}, {
&sensor_dev_attr_fan3_input.dev_attr.attr,
&sensor_dev_attr_fan3_min.dev_attr.attr,
&sensor_dev_attr_fan3_div.dev_attr.attr,
-
- &sensor_dev_attr_fan1_alarm.dev_attr.attr,
- &sensor_dev_attr_fan2_alarm.dev_attr.attr,
&sensor_dev_attr_fan3_alarm.dev_attr.attr,
- &sensor_dev_attr_fan4_alarm.dev_attr.attr,
- &sensor_dev_attr_fan5_alarm.dev_attr.attr,
+ NULL
+} };
+
+static const struct attribute_group it87_group_fan[3] = {
+ { .attrs = it87_attributes_fan[0] },
+ { .attrs = it87_attributes_fan[1] },
+ { .attrs = it87_attributes_fan[2] },
+};
+
+static const struct attribute_group *
+it87_get_fan_group(const struct it87_data *data)
+{
+ return has_16bit_fans(data) ? it87_group_fan16 : it87_group_fan;
+}
+static struct attribute *it87_attributes_pwm[3][4+1] = { {
&sensor_dev_attr_pwm1_enable.dev_attr.attr,
- &sensor_dev_attr_pwm2_enable.dev_attr.attr,
- &sensor_dev_attr_pwm3_enable.dev_attr.attr,
&sensor_dev_attr_pwm1.dev_attr.attr,
- &sensor_dev_attr_pwm2.dev_attr.attr,
- &sensor_dev_attr_pwm3.dev_attr.attr,
&dev_attr_pwm1_freq.attr,
+ &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr,
+ NULL
+}, {
+ &sensor_dev_attr_pwm2_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm2.dev_attr.attr,
&dev_attr_pwm2_freq.attr,
+ &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr,
+ NULL
+}, {
+ &sensor_dev_attr_pwm3_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm3.dev_attr.attr,
&dev_attr_pwm3_freq.attr,
+ &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr,
+ NULL
+} };
+
+static const struct attribute_group it87_group_pwm[3] = {
+ { .attrs = it87_attributes_pwm[0] },
+ { .attrs = it87_attributes_pwm[1] },
+ { .attrs = it87_attributes_pwm[2] },
+};
+static struct attribute *it87_attributes_autopwm[3][9+1] = { {
+ &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point1_temp_hyst.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr,
+ NULL
+}, {
+ &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point3_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point4_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point1_temp_hyst.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm2_auto_point4_temp.dev_attr.attr,
+ NULL
+}, {
+ &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm3_auto_point3_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm3_auto_point4_pwm.dev_attr.attr,
+ &sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm3_auto_point1_temp_hyst.dev_attr.attr,
+ &sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr,
+ &sensor_dev_attr_pwm3_auto_point4_temp.dev_attr.attr,
+ NULL
+} };
+
+static const struct attribute_group it87_group_autopwm[3] = {
+ { .attrs = it87_attributes_autopwm[0] },
+ { .attrs = it87_attributes_autopwm[1] },
+ { .attrs = it87_attributes_autopwm[2] },
+};
+
+static struct attribute *it87_attributes_fan_beep[] = {
+ &sensor_dev_attr_fan1_beep.dev_attr.attr,
+ &sensor_dev_attr_fan2_beep.dev_attr.attr,
+ &sensor_dev_attr_fan3_beep.dev_attr.attr,
+ &sensor_dev_attr_fan4_beep.dev_attr.attr,
+ &sensor_dev_attr_fan5_beep.dev_attr.attr,
+};
+
+static struct attribute *it87_attributes_vid[] = {
&dev_attr_vrm.attr,
&dev_attr_cpu0_vid.attr,
NULL
};
-static const struct attribute_group it87_group_opt = {
- .attrs = it87_attributes_opt,
+static const struct attribute_group it87_group_vid = {
+ .attrs = it87_attributes_vid,
};
/* SuperIO detection - will change isa_address if a chip is found */
@@ -1035,6 +1482,10 @@ static int __init it87_find(unsigned short *address,
if (sio_data->type == it87) {
/* The IT8705F doesn't have VID pins at all */
sio_data->skip_vid = 1;
+
+ /* The IT8705F has a different LD number for GPIO */
+ superio_select(5);
+ sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
} else {
int reg;
@@ -1068,7 +1519,11 @@ static int __init it87_find(unsigned short *address,
pr_info("it87: in3 is VCC (+5V)\n");
if (reg & (1 << 1))
pr_info("it87: in7 is VCCH (+5V Stand-By)\n");
+
+ sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f;
}
+ if (sio_data->beep_pin)
+ pr_info("it87: Beeping is supported\n");
/* Disable specific features based on DMI strings */
board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
@@ -1093,14 +1548,46 @@ exit:
return err;
}
+static void it87_remove_files(struct device *dev)
+{
+ struct it87_data *data = platform_get_drvdata(pdev);
+ struct it87_sio_data *sio_data = dev->platform_data;
+ const struct attribute_group *fan_group = it87_get_fan_group(data);
+ int i;
+
+ sysfs_remove_group(&dev->kobj, &it87_group);
+ if (sio_data->beep_pin)
+ sysfs_remove_group(&dev->kobj, &it87_group_beep);
+ for (i = 0; i < 5; i++) {
+ if (!(data->has_fan & (1 << i)))
+ continue;
+ sysfs_remove_group(&dev->kobj, &fan_group[i]);
+ if (sio_data->beep_pin)
+ sysfs_remove_file(&dev->kobj,
+ it87_attributes_fan_beep[i]);
+ }
+ for (i = 0; i < 3; i++) {
+ if (sio_data->skip_pwm & (1 << 0))
+ continue;
+ sysfs_remove_group(&dev->kobj, &it87_group_pwm[i]);
+ if (has_old_autopwm(data))
+ sysfs_remove_group(&dev->kobj,
+ &it87_group_autopwm[i]);
+ }
+ if (!sio_data->skip_vid)
+ sysfs_remove_group(&dev->kobj, &it87_group_vid);
+}
+
static int __devinit it87_probe(struct platform_device *pdev)
{
struct it87_data *data;
struct resource *res;
struct device *dev = &pdev->dev;
struct it87_sio_data *sio_data = dev->platform_data;
- int err = 0;
+ const struct attribute_group *fan_group;
+ int err = 0, i;
int enable_pwm_interface;
+ int fan_beep_need_rw;
static const char *names[] = {
"it87",
"it8712",
@@ -1118,7 +1605,8 @@ static int __devinit it87_probe(struct platform_device *pdev)
goto ERROR0;
}
- if (!(data = kzalloc(sizeof(struct it87_data), GFP_KERNEL))) {
+ data = kzalloc(sizeof(struct it87_data), GFP_KERNEL);
+ if (!data) {
err = -ENOMEM;
goto ERROR1;
}
@@ -1146,120 +1634,60 @@ static int __devinit it87_probe(struct platform_device *pdev)
it87_init_device(pdev);
/* Register sysfs hooks */
- if ((err = sysfs_create_group(&dev->kobj, &it87_group)))
+ err = sysfs_create_group(&dev->kobj, &it87_group);
+ if (err)
goto ERROR2;
+ if (sio_data->beep_pin) {
+ err = sysfs_create_group(&dev->kobj, &it87_group_beep);
+ if (err)
+ goto ERROR4;
+ }
+
/* Do not create fan files for disabled fans */
- if (has_16bit_fans(data)) {
- /* 16-bit tachometers */
- if (data->has_fan & (1 << 0)) {
- if ((err = device_create_file(dev,
- &sensor_dev_attr_fan1_input16.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_fan1_min16.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_fan1_alarm.dev_attr)))
- goto ERROR4;
- }
- if (data->has_fan & (1 << 1)) {
- if ((err = device_create_file(dev,
- &sensor_dev_attr_fan2_input16.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_fan2_min16.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_fan2_alarm.dev_attr)))
- goto ERROR4;
- }
- if (data->has_fan & (1 << 2)) {
- if ((err = device_create_file(dev,
- &sensor_dev_attr_fan3_input16.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_fan3_min16.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_fan3_alarm.dev_attr)))
- goto ERROR4;
- }
- if (data->has_fan & (1 << 3)) {
- if ((err = device_create_file(dev,
- &sensor_dev_attr_fan4_input16.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_fan4_min16.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_fan4_alarm.dev_attr)))
- goto ERROR4;
- }
- if (data->has_fan & (1 << 4)) {
- if ((err = device_create_file(dev,
- &sensor_dev_attr_fan5_input16.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_fan5_min16.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_fan5_alarm.dev_attr)))
- goto ERROR4;
- }
- } else {
- /* 8-bit tachometers with clock divider */
- if (data->has_fan & (1 << 0)) {
- if ((err = device_create_file(dev,
- &sensor_dev_attr_fan1_input.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_fan1_min.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_fan1_div.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_fan1_alarm.dev_attr)))
- goto ERROR4;
- }
- if (data->has_fan & (1 << 1)) {
- if ((err = device_create_file(dev,
- &sensor_dev_attr_fan2_input.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_fan2_min.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_fan2_div.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_fan2_alarm.dev_attr)))
- goto ERROR4;
- }
- if (data->has_fan & (1 << 2)) {
- if ((err = device_create_file(dev,
- &sensor_dev_attr_fan3_input.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_fan3_min.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_fan3_div.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_fan3_alarm.dev_attr)))
+ fan_group = it87_get_fan_group(data);
+ fan_beep_need_rw = 1;
+ for (i = 0; i < 5; i++) {
+ if (!(data->has_fan & (1 << i)))
+ continue;
+ err = sysfs_create_group(&dev->kobj, &fan_group[i]);
+ if (err)
+ goto ERROR4;
+
+ if (sio_data->beep_pin) {
+ err = sysfs_create_file(&dev->kobj,
+ it87_attributes_fan_beep[i]);
+ if (err)
goto ERROR4;
+ if (!fan_beep_need_rw)
+ continue;
+
+ /* As we have a single beep enable bit for all fans,
+ * only the first enabled fan has a writable attribute
+ * for it. */
+ if (sysfs_chmod_file(&dev->kobj,
+ it87_attributes_fan_beep[i],
+ S_IRUGO | S_IWUSR))
+ dev_dbg(dev, "chmod +w fan%d_beep failed\n",
+ i + 1);
+ fan_beep_need_rw = 0;
}
}
if (enable_pwm_interface) {
- if (!(sio_data->skip_pwm & (1 << 0))) {
- if ((err = device_create_file(dev,
- &sensor_dev_attr_pwm1_enable.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_pwm1.dev_attr))
- || (err = device_create_file(dev,
- &dev_attr_pwm1_freq)))
- goto ERROR4;
- }
- if (!(sio_data->skip_pwm & (1 << 1))) {
- if ((err = device_create_file(dev,
- &sensor_dev_attr_pwm2_enable.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_pwm2.dev_attr))
- || (err = device_create_file(dev,
- &dev_attr_pwm2_freq)))
+ for (i = 0; i < 3; i++) {
+ if (sio_data->skip_pwm & (1 << i))
+ continue;
+ err = sysfs_create_group(&dev->kobj,
+ &it87_group_pwm[i]);
+ if (err)
goto ERROR4;
- }
- if (!(sio_data->skip_pwm & (1 << 2))) {
- if ((err = device_create_file(dev,
- &sensor_dev_attr_pwm3_enable.dev_attr))
- || (err = device_create_file(dev,
- &sensor_dev_attr_pwm3.dev_attr))
- || (err = device_create_file(dev,
- &dev_attr_pwm3_freq)))
+
+ if (!has_old_autopwm(data))
+ continue;
+ err = sysfs_create_group(&dev->kobj,
+ &it87_group_autopwm[i]);
+ if (err)
goto ERROR4;
}
}
@@ -1268,10 +1696,8 @@ static int __devinit it87_probe(struct platform_device *pdev)
data->vrm = vid_which_vrm();
/* VID reading from Super-I/O config space if available */
data->vid = sio_data->vid_value;
- if ((err = device_create_file(dev,
- &dev_attr_vrm))
- || (err = device_create_file(dev,
- &dev_attr_cpu0_vid)))
+ err = sysfs_create_group(&dev->kobj, &it87_group_vid);
+ if (err)
goto ERROR4;
}
@@ -1284,8 +1710,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
return 0;
ERROR4:
- sysfs_remove_group(&dev->kobj, &it87_group);
- sysfs_remove_group(&dev->kobj, &it87_group_opt);
+ it87_remove_files(dev);
ERROR2:
platform_set_drvdata(pdev, NULL);
kfree(data);
@@ -1300,8 +1725,7 @@ static int __devexit it87_remove(struct platform_device *pdev)
struct it87_data *data = platform_get_drvdata(pdev);
hwmon_device_unregister(data->hwmon_dev);
- sysfs_remove_group(&pdev->dev.kobj, &it87_group);
- sysfs_remove_group(&pdev->dev.kobj, &it87_group_opt);
+ it87_remove_files(&pdev->dev);
release_region(data->addr, IT87_EC_EXTENT);
platform_set_drvdata(pdev, NULL);
@@ -1387,15 +1811,18 @@ static void __devinit it87_init_device(struct platform_device *pdev)
int tmp, i;
u8 mask;
- /* initialize to sane defaults:
- * - if the chip is in manual pwm mode, this will be overwritten with
- * the actual settings on the chip (so in this case, initialization
- * is not needed)
- * - if in automatic or on/off mode, we could switch to manual mode,
- * read the registers and set manual_pwm_ctl accordingly, but currently
- * this is not implemented, so we initialize to something sane */
+ /* For each PWM channel:
+ * - If it is in automatic mode, setting to manual mode should set
+ * the fan to full speed by default.
+ * - If it is in manual mode, we need a mapping to temperature
+ * channels to use when later setting to automatic mode later.
+ * Use a 1:1 mapping by default (we are clueless.)
+ * In both cases, the value can (and should) be changed by the user
+ * prior to switching to a different mode. */
for (i = 0; i < 3; i++) {
- data->manual_pwm_ctl[i] = 0xff;
+ data->pwm_temp_map[i] = i;
+ data->pwm_duty[i] = 0x7f; /* Full speed */
+ data->auto_pwm[i][3] = 0x7f; /* Full speed, hard-coded */
}
/* Some chips seem to have default value 0xff for all limit
@@ -1436,7 +1863,8 @@ static void __devinit it87_init_device(struct platform_device *pdev)
if ((data->fan_main_ctrl & mask) == 0) {
/* Enable all fan tachometers */
data->fan_main_ctrl |= mask;
- it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
+ it87_write_value(data, IT87_REG_FAN_MAIN_CTRL,
+ data->fan_main_ctrl);
}
data->has_fan = (data->fan_main_ctrl >> 4) & 0x07;
@@ -1461,30 +1889,32 @@ static void __devinit it87_init_device(struct platform_device *pdev)
/* Fan input pins may be used for alternative functions */
data->has_fan &= ~sio_data->skip_fan;
- /* Set current fan mode registers and the default settings for the
- * other mode registers */
- for (i = 0; i < 3; i++) {
- if (data->fan_main_ctrl & (1 << i)) {
- /* pwm mode */
- tmp = it87_read_value(data, IT87_REG_PWM(i));
- if (tmp & 0x80) {
- /* automatic pwm - not yet implemented, but
- * leave the settings made by the BIOS alone
- * until a change is requested via the sysfs
- * interface */
- } else {
- /* manual pwm */
- data->manual_pwm_ctl[i] = PWM_FROM_REG(tmp);
- }
- }
- }
-
/* Start monitoring */
it87_write_value(data, IT87_REG_CONFIG,
(it87_read_value(data, IT87_REG_CONFIG) & 0x36)
| (update_vbat ? 0x41 : 0x01));
}
+static void it87_update_pwm_ctrl(struct it87_data *data, int nr)
+{
+ data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr));
+ if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */
+ data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03;
+ else /* Manual mode */
+ data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f;
+
+ if (has_old_autopwm(data)) {
+ int i;
+
+ for (i = 0; i < 5 ; i++)
+ data->auto_temp[nr][i] = it87_read_value(data,
+ IT87_REG_AUTO_TEMP(nr, i));
+ for (i = 0; i < 3 ; i++)
+ data->auto_pwm[nr][i] = it87_read_value(data,
+ IT87_REG_AUTO_PWM(nr, i));
+ }
+}
+
static struct it87_data *it87_update_device(struct device *dev)
{
struct it87_data *data = dev_get_drvdata(dev);
@@ -1494,24 +1924,22 @@ static struct it87_data *it87_update_device(struct device *dev)
if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
|| !data->valid) {
-
if (update_vbat) {
/* Cleared after each update, so reenable. Value
- returned by this read will be previous value */
+ returned by this read will be previous value */
it87_write_value(data, IT87_REG_CONFIG,
- it87_read_value(data, IT87_REG_CONFIG) | 0x40);
+ it87_read_value(data, IT87_REG_CONFIG) | 0x40);
}
for (i = 0; i <= 7; i++) {
data->in[i] =
- it87_read_value(data, IT87_REG_VIN(i));
+ it87_read_value(data, IT87_REG_VIN(i));
data->in_min[i] =
- it87_read_value(data, IT87_REG_VIN_MIN(i));
+ it87_read_value(data, IT87_REG_VIN_MIN(i));
data->in_max[i] =
- it87_read_value(data, IT87_REG_VIN_MAX(i));
+ it87_read_value(data, IT87_REG_VIN_MAX(i));
}
/* in8 (battery) has no limit registers */
- data->in[8] =
- it87_read_value(data, IT87_REG_VIN(8));
+ data->in[8] = it87_read_value(data, IT87_REG_VIN(8));
for (i = 0; i < 5; i++) {
/* Skip disabled fans */
@@ -1519,7 +1947,7 @@ static struct it87_data *it87_update_device(struct device *dev)
continue;
data->fan_min[i] =
- it87_read_value(data, IT87_REG_FAN_MIN[i]);
+ it87_read_value(data, IT87_REG_FAN_MIN[i]);
data->fan[i] = it87_read_value(data,
IT87_REG_FAN[i]);
/* Add high byte if in 16-bit mode */
@@ -1532,11 +1960,11 @@ static struct it87_data *it87_update_device(struct device *dev)
}
for (i = 0; i < 3; i++) {
data->temp[i] =
- it87_read_value(data, IT87_REG_TEMP(i));
+ it87_read_value(data, IT87_REG_TEMP(i));
data->temp_high[i] =
- it87_read_value(data, IT87_REG_TEMP_HIGH(i));
+ it87_read_value(data, IT87_REG_TEMP_HIGH(i));
data->temp_low[i] =
- it87_read_value(data, IT87_REG_TEMP_LOW(i));
+ it87_read_value(data, IT87_REG_TEMP_LOW(i));
}
/* Newer chips don't have clock dividers */
@@ -1551,9 +1979,13 @@ static struct it87_data *it87_update_device(struct device *dev)
it87_read_value(data, IT87_REG_ALARM1) |
(it87_read_value(data, IT87_REG_ALARM2) << 8) |
(it87_read_value(data, IT87_REG_ALARM3) << 16);
+ data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE);
+
data->fan_main_ctrl = it87_read_value(data,
IT87_REG_FAN_MAIN_CTRL);
data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL);
+ for (i = 0; i < 3; i++)
+ it87_update_pwm_ctrl(data, i);
data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE);
/* The 8705 does not have VID capability.
@@ -1628,7 +2060,7 @@ exit:
static int __init sm_it87_init(void)
{
int err;
- unsigned short isa_address=0;
+ unsigned short isa_address = 0;
struct it87_sio_data sio_data;
memset(&sio_data, 0, sizeof(struct it87_sio_data));
@@ -1640,7 +2072,7 @@ static int __init sm_it87_init(void)
return err;
err = it87_device_add(isa_address, &sio_data);
- if (err){
+ if (err) {
platform_driver_unregister(&it87_driver);
return err;
}
@@ -1661,7 +2093,8 @@ MODULE_DESCRIPTION("IT8705F/8712F/8716F/8718F/8720F/8726F, SiS950 driver");
module_param(update_vbat, bool, 0);
MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");
module_param(fix_pwm_polarity, bool, 0);
-MODULE_PARM_DESC(fix_pwm_polarity, "Force PWM polarity to active high (DANGEROUS)");
+MODULE_PARM_DESC(fix_pwm_polarity,
+ "Force PWM polarity to active high (DANGEROUS)");
MODULE_LICENSE("GPL");
module_init(sm_it87_init);
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index 7c9bdc16742..7cc2708871a 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -1,7 +1,7 @@
/*
* lm90.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring
- * Copyright (C) 2003-2009 Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org>
*
* Based on the lm83 driver. The LM90 is a sensor chip made by National
* Semiconductor. It reports up to two temperatures (its own plus up to
@@ -93,7 +93,8 @@
static const unsigned short normal_i2c[] = {
0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END };
-enum chips { lm90, adm1032, lm99, lm86, max6657, adt7461, max6680, max6646 };
+enum chips { lm90, adm1032, lm99, lm86, max6657, adt7461, max6680, max6646,
+ w83l771 };
/*
* The LM90 registers
@@ -151,6 +152,7 @@ static int lm90_detect(struct i2c_client *client, struct i2c_board_info *info);
static int lm90_probe(struct i2c_client *client,
const struct i2c_device_id *id);
static void lm90_init_client(struct i2c_client *client);
+static void lm90_alert(struct i2c_client *client, unsigned int flag);
static int lm90_remove(struct i2c_client *client);
static struct lm90_data *lm90_update_device(struct device *dev);
@@ -173,6 +175,7 @@ static const struct i2c_device_id lm90_id[] = {
{ "max6659", max6657 },
{ "max6680", max6680 },
{ "max6681", max6680 },
+ { "w83l771", w83l771 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm90_id);
@@ -184,6 +187,7 @@ static struct i2c_driver lm90_driver = {
},
.probe = lm90_probe,
.remove = lm90_remove,
+ .alert = lm90_alert,
.id_table = lm90_id,
.detect = lm90_detect,
.address_list = normal_i2c,
@@ -201,6 +205,9 @@ struct lm90_data {
int kind;
int flags;
+ u8 config_orig; /* Original configuration register value */
+ u8 alert_alarms; /* Which alarm bits trigger ALERT# */
+
/* registers values */
s8 temp8[4]; /* 0: local low limit
1: local high limit
@@ -758,6 +765,14 @@ static int lm90_detect(struct i2c_client *new_client,
&& reg_convrate <= 0x07) {
name = "max6646";
}
+ } else
+ if (address == 0x4C
+ && man_id == 0x5C) { /* Winbond/Nuvoton */
+ if ((chip_id & 0xFE) == 0x10 /* W83L771AWG/ASG */
+ && (reg_config1 & 0x2A) == 0x00
+ && reg_convrate <= 0x08) {
+ name = "w83l771";
+ }
}
if (!name) { /* identification failed */
@@ -794,6 +809,19 @@ static int lm90_probe(struct i2c_client *new_client,
new_client->flags &= ~I2C_CLIENT_PEC;
}
+ /* Different devices have different alarm bits triggering the
+ * ALERT# output */
+ switch (data->kind) {
+ case lm90:
+ case lm99:
+ case lm86:
+ data->alert_alarms = 0x7b;
+ break;
+ default:
+ data->alert_alarms = 0x7c;
+ break;
+ }
+
/* Initialize the LM90 chip */
lm90_init_client(new_client);
@@ -830,7 +858,7 @@ exit:
static void lm90_init_client(struct i2c_client *client)
{
- u8 config, config_orig;
+ u8 config;
struct lm90_data *data = i2c_get_clientdata(client);
/*
@@ -842,7 +870,7 @@ static void lm90_init_client(struct i2c_client *client)
dev_warn(&client->dev, "Initialization failed!\n");
return;
}
- config_orig = config;
+ data->config_orig = config;
/* Check Temperature Range Select */
if (data->kind == adt7461) {
@@ -860,7 +888,7 @@ static void lm90_init_client(struct i2c_client *client)
}
config &= 0xBF; /* run */
- if (config != config_orig) /* Only write if changed */
+ if (config != data->config_orig) /* Only write if changed */
i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config);
}
@@ -875,10 +903,46 @@ static int lm90_remove(struct i2c_client *client)
device_remove_file(&client->dev,
&sensor_dev_attr_temp2_offset.dev_attr);
+ /* Restore initial configuration */
+ i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
+ data->config_orig);
+
kfree(data);
return 0;
}
+static void lm90_alert(struct i2c_client *client, unsigned int flag)
+{
+ struct lm90_data *data = i2c_get_clientdata(client);
+ u8 config, alarms;
+
+ lm90_read_reg(client, LM90_REG_R_STATUS, &alarms);
+ if ((alarms & 0x7f) == 0) {
+ dev_info(&client->dev, "Everything OK\n");
+ } else {
+ if (alarms & 0x61)
+ dev_warn(&client->dev,
+ "temp%d out of range, please check!\n", 1);
+ if (alarms & 0x1a)
+ dev_warn(&client->dev,
+ "temp%d out of range, please check!\n", 2);
+ if (alarms & 0x04)
+ dev_warn(&client->dev,
+ "temp%d diode open, please check!\n", 2);
+
+ /* Disable ALERT# output, because these chips don't implement
+ SMBus alert correctly; they should only hold the alert line
+ low briefly. */
+ if ((data->kind == adm1032 || data->kind == adt7461)
+ && (alarms & data->alert_alarms)) {
+ dev_dbg(&client->dev, "Disabling ALERT#\n");
+ lm90_read_reg(client, LM90_REG_R_CONFIG1, &config);
+ i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
+ config | 0x80);
+ }
+ }
+}
+
static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value)
{
int err;
@@ -966,6 +1030,21 @@ static struct lm90_data *lm90_update_device(struct device *dev)
}
lm90_read_reg(client, LM90_REG_R_STATUS, &data->alarms);
+ /* Re-enable ALERT# output if it was originally enabled and
+ * relevant alarms are all clear */
+ if ((data->config_orig & 0x80) == 0
+ && (data->alarms & data->alert_alarms) == 0) {
+ u8 config;
+
+ lm90_read_reg(client, LM90_REG_R_CONFIG1, &config);
+ if (config & 0x80) {
+ dev_dbg(&client->dev, "Re-enabling ALERT#\n");
+ i2c_smbus_write_byte_data(client,
+ LM90_REG_W_CONFIG1,
+ config & ~0x80);
+ }
+ }
+
data->last_updated = jiffies;
data->valid = 1;
}
diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c
index a13b30e8d8d..d14a1af9f55 100644
--- a/drivers/hwmon/tmp401.c
+++ b/drivers/hwmon/tmp401.c
@@ -134,7 +134,7 @@ struct tmp401_data {
struct mutex update_lock;
char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */
- int kind;
+ enum chips kind;
/* register values */
u8 status;
@@ -524,7 +524,7 @@ static int tmp401_detect(struct i2c_client *client,
if (reg > 15)
return -ENODEV;
- strlcpy(info->type, tmp401_id[kind - 1].name, I2C_NAME_SIZE);
+ strlcpy(info->type, tmp401_id[kind].name, I2C_NAME_SIZE);
return 0;
}
@@ -572,8 +572,7 @@ static int tmp401_probe(struct i2c_client *client,
goto exit_remove;
}
- dev_info(&client->dev, "Detected TI %s chip\n",
- names[data->kind - 1]);
+ dev_info(&client->dev, "Detected TI %s chip\n", names[data->kind]);
return 0;
diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c
index 4f7c051e2d7..738c472ece2 100644
--- a/drivers/hwmon/tmp421.c
+++ b/drivers/hwmon/tmp421.c
@@ -61,9 +61,9 @@ static const u8 TMP421_TEMP_LSB[4] = { 0x10, 0x11, 0x12, 0x13 };
#define TMP423_DEVICE_ID 0x23
static const struct i2c_device_id tmp421_id[] = {
- { "tmp421", tmp421 },
- { "tmp422", tmp422 },
- { "tmp423", tmp423 },
+ { "tmp421", 2 },
+ { "tmp422", 3 },
+ { "tmp423", 4 },
{ }
};
MODULE_DEVICE_TABLE(i2c, tmp421_id);
@@ -73,21 +73,23 @@ struct tmp421_data {
struct mutex update_lock;
char valid;
unsigned long last_updated;
- int kind;
+ int channels;
u8 config;
s16 temp[4];
};
static int temp_from_s16(s16 reg)
{
- int temp = reg;
+ /* Mask out status bits */
+ int temp = reg & ~0xf;
return (temp * 1000 + 128) / 256;
}
static int temp_from_u16(u16 reg)
{
- int temp = reg;
+ /* Mask out status bits */
+ int temp = reg & ~0xf;
/* Add offset for extended temperature range. */
temp -= 64 * 256;
@@ -107,7 +109,7 @@ static struct tmp421_data *tmp421_update_device(struct device *dev)
data->config = i2c_smbus_read_byte_data(client,
TMP421_CONFIG_REG_1);
- for (i = 0; i <= data->kind; i++) {
+ for (i = 0; i < data->channels; i++) {
data->temp[i] = i2c_smbus_read_byte_data(client,
TMP421_TEMP_MSB[i]) << 8;
data->temp[i] |= i2c_smbus_read_byte_data(client,
@@ -166,7 +168,7 @@ static mode_t tmp421_is_visible(struct kobject *kobj, struct attribute *a,
devattr = container_of(a, struct device_attribute, attr);
index = to_sensor_dev_attr(devattr)->index;
- if (data->kind > index)
+ if (index < data->channels)
return a->mode;
return 0;
@@ -252,9 +254,9 @@ static int tmp421_detect(struct i2c_client *client,
return -ENODEV;
}
- strlcpy(info->type, tmp421_id[kind - 1].name, I2C_NAME_SIZE);
+ strlcpy(info->type, tmp421_id[kind].name, I2C_NAME_SIZE);
dev_info(&adapter->dev, "Detected TI %s chip at 0x%02x\n",
- names[kind - 1], client->addr);
+ names[kind], client->addr);
return 0;
}
@@ -271,7 +273,7 @@ static int tmp421_probe(struct i2c_client *client,
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
- data->kind = id->driver_data;
+ data->channels = id->driver_data;
err = tmp421_init_client(client);
if (err)
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
index d47b4c9949c..e6078c9f0e2 100644
--- a/drivers/hwmon/vt8231.c
+++ b/drivers/hwmon/vt8231.c
@@ -948,8 +948,7 @@ static int __devinit vt8231_pci_probe(struct pci_dev *dev,
address = val & ~(VT8231_EXTENT - 1);
if (address == 0) {
- dev_err(&dev->dev, "base address not set -\
- upgrade BIOS or use force_addr=0xaddr\n");
+ dev_err(&dev->dev, "base address not set - upgrade BIOS or use force_addr=0xaddr\n");
return -ENODEV;
}
diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c
index 9a2022b6749..9de81a4c15a 100644
--- a/drivers/hwmon/w83793.c
+++ b/drivers/hwmon/w83793.c
@@ -3,6 +3,10 @@
Copyright (C) 2006 Winbond Electronics Corp.
Yuan Mu
Rudolf Marek <r.marek@assembler.cz>
+ Copyright (C) 2009-2010 Sven Anders <anders@anduras.de>, ANDURAS AG.
+ Watchdog driver part
+ (Based partially on fschmd driver,
+ Copyright 2007-2008 by Hans de Goede)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -35,6 +39,16 @@
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
+#include <linux/fs.h>
+#include <linux/watchdog.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/kref.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+
+/* Default values */
+#define WATCHDOG_TIMEOUT 2 /* 2 minute default timeout */
/* Addresses to scan */
static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
@@ -51,6 +65,18 @@ static int reset;
module_param(reset, bool, 0);
MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended");
+static int timeout = WATCHDOG_TIMEOUT; /* default timeout in minutes */
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout,
+ "Watchdog timeout in minutes. 2<= timeout <=255 (default="
+ __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout,
+ "Watchdog cannot be stopped once started (default="
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
/*
Address 0x00, 0x0d, 0x0e, 0x0f in all three banks are reserved
as ID, Bank Select registers
@@ -72,6 +98,11 @@ MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended");
#define W83793_REG_VID_LATCHB 0x08
#define W83793_REG_VID_CTRL 0x59
+#define W83793_REG_WDT_LOCK 0x01
+#define W83793_REG_WDT_ENABLE 0x02
+#define W83793_REG_WDT_STATUS 0x03
+#define W83793_REG_WDT_TIMEOUT 0x04
+
static u16 W83793_REG_TEMP_MODE[2] = { 0x5e, 0x5f };
#define TEMP_READ 0
@@ -223,8 +254,37 @@ struct w83793_data {
u8 tolerance[3]; /* Temp tolerance(Smart Fan I/II) */
u8 sf2_pwm[6][7]; /* Smart FanII: Fan duty cycle */
u8 sf2_temp[6][7]; /* Smart FanII: Temp level point */
+
+ /* watchdog */
+ struct i2c_client *client;
+ struct mutex watchdog_lock;
+ struct list_head list; /* member of the watchdog_data_list */
+ struct kref kref;
+ struct miscdevice watchdog_miscdev;
+ unsigned long watchdog_is_open;
+ char watchdog_expect_close;
+ char watchdog_name[10]; /* must be unique to avoid sysfs conflict */
+ unsigned int watchdog_caused_reboot;
+ int watchdog_timeout; /* watchdog timeout in minutes */
};
+/* Somewhat ugly :( global data pointer list with all devices, so that
+ we can find our device data as when using misc_register. There is no
+ other method to get to one's device data from the open file-op and
+ for usage in the reboot notifier callback. */
+static LIST_HEAD(watchdog_data_list);
+
+/* Note this lock not only protect list access, but also data.kref access */
+static DEFINE_MUTEX(watchdog_data_mutex);
+
+/* Release our data struct when we're detached from the i2c client *and* all
+ references to our watchdog device are released */
+static void w83793_release_resources(struct kref *ref)
+{
+ struct w83793_data *data = container_of(ref, struct w83793_data, kref);
+ kfree(data);
+}
+
static u8 w83793_read_value(struct i2c_client *client, u16 reg);
static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value);
static int w83793_probe(struct i2c_client *client,
@@ -1063,14 +1123,349 @@ static void w83793_init_client(struct i2c_client *client)
/* Start monitoring */
w83793_write_value(client, W83793_REG_CONFIG,
w83793_read_value(client, W83793_REG_CONFIG) | 0x01);
+}
+
+/*
+ * Watchdog routines
+ */
+
+static int watchdog_set_timeout(struct w83793_data *data, int timeout)
+{
+ int ret, mtimeout;
+
+ mtimeout = DIV_ROUND_UP(timeout, 60);
+
+ if (mtimeout > 255)
+ return -EINVAL;
+
+ mutex_lock(&data->watchdog_lock);
+ if (!data->client) {
+ ret = -ENODEV;
+ goto leave;
+ }
+
+ data->watchdog_timeout = mtimeout;
+
+ /* Set Timeout value (in Minutes) */
+ w83793_write_value(data->client, W83793_REG_WDT_TIMEOUT,
+ data->watchdog_timeout);
+
+ ret = mtimeout * 60;
+
+leave:
+ mutex_unlock(&data->watchdog_lock);
+ return ret;
+}
+
+static int watchdog_get_timeout(struct w83793_data *data)
+{
+ int timeout;
+
+ mutex_lock(&data->watchdog_lock);
+ timeout = data->watchdog_timeout * 60;
+ mutex_unlock(&data->watchdog_lock);
+
+ return timeout;
+}
+
+static int watchdog_trigger(struct w83793_data *data)
+{
+ int ret = 0;
+
+ mutex_lock(&data->watchdog_lock);
+ if (!data->client) {
+ ret = -ENODEV;
+ goto leave;
+ }
+
+ /* Set Timeout value (in Minutes) */
+ w83793_write_value(data->client, W83793_REG_WDT_TIMEOUT,
+ data->watchdog_timeout);
+
+leave:
+ mutex_unlock(&data->watchdog_lock);
+ return ret;
+}
+
+static int watchdog_enable(struct w83793_data *data)
+{
+ int ret = 0;
+
+ mutex_lock(&data->watchdog_lock);
+ if (!data->client) {
+ ret = -ENODEV;
+ goto leave;
+ }
+
+ /* Set initial timeout */
+ w83793_write_value(data->client, W83793_REG_WDT_TIMEOUT,
+ data->watchdog_timeout);
+
+ /* Enable Soft Watchdog */
+ w83793_write_value(data->client, W83793_REG_WDT_LOCK, 0x55);
+
+leave:
+ mutex_unlock(&data->watchdog_lock);
+ return ret;
+}
+
+static int watchdog_disable(struct w83793_data *data)
+{
+ int ret = 0;
+
+ mutex_lock(&data->watchdog_lock);
+ if (!data->client) {
+ ret = -ENODEV;
+ goto leave;
+ }
+
+ /* Disable Soft Watchdog */
+ w83793_write_value(data->client, W83793_REG_WDT_LOCK, 0xAA);
+
+leave:
+ mutex_unlock(&data->watchdog_lock);
+ return ret;
+}
+
+static int watchdog_open(struct inode *inode, struct file *filp)
+{
+ struct w83793_data *pos, *data = NULL;
+ int watchdog_is_open;
+
+ /* We get called from drivers/char/misc.c with misc_mtx hold, and we
+ call misc_register() from w83793_probe() with watchdog_data_mutex
+ hold, as misc_register() takes the misc_mtx lock, this is a possible
+ deadlock, so we use mutex_trylock here. */
+ if (!mutex_trylock(&watchdog_data_mutex))
+ return -ERESTARTSYS;
+ list_for_each_entry(pos, &watchdog_data_list, list) {
+ if (pos->watchdog_miscdev.minor == iminor(inode)) {
+ data = pos;
+ break;
+ }
+ }
+
+ /* Check, if device is already open */
+ watchdog_is_open = test_and_set_bit(0, &data->watchdog_is_open);
+
+ /* Increase data reference counter (if not already done).
+ Note we can never not have found data, so we don't check for this */
+ if (!watchdog_is_open)
+ kref_get(&data->kref);
+
+ mutex_unlock(&watchdog_data_mutex);
+
+ /* Check, if device is already open and possibly issue error */
+ if (watchdog_is_open)
+ return -EBUSY;
+
+ /* Enable Soft Watchdog */
+ watchdog_enable(data);
+
+ /* Store pointer to data into filp's private data */
+ filp->private_data = data;
+
+ return nonseekable_open(inode, filp);
+}
+
+static int watchdog_close(struct inode *inode, struct file *filp)
+{
+ struct w83793_data *data = filp->private_data;
+ if (data->watchdog_expect_close) {
+ watchdog_disable(data);
+ data->watchdog_expect_close = 0;
+ } else {
+ watchdog_trigger(data);
+ dev_crit(&data->client->dev,
+ "unexpected close, not stopping watchdog!\n");
+ }
+
+ clear_bit(0, &data->watchdog_is_open);
+
+ /* Decrease data reference counter */
+ mutex_lock(&watchdog_data_mutex);
+ kref_put(&data->kref, w83793_release_resources);
+ mutex_unlock(&watchdog_data_mutex);
+
+ return 0;
+}
+
+static ssize_t watchdog_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *offset)
+{
+ size_t ret;
+ struct w83793_data *data = filp->private_data;
+
+ if (count) {
+ if (!nowayout) {
+ size_t i;
+
+ /* Clear it in case it was set with a previous write */
+ data->watchdog_expect_close = 0;
+
+ for (i = 0; i != count; i++) {
+ char c;
+ if (get_user(c, buf + i))
+ return -EFAULT;
+ if (c == 'V')
+ data->watchdog_expect_close = 1;
+ }
+ }
+ ret = watchdog_trigger(data);
+ if (ret < 0)
+ return ret;
+ }
+ return count;
+}
+
+static int watchdog_ioctl(struct inode *inode, struct file *filp,
+ unsigned int cmd, unsigned long arg)
+{
+ static struct watchdog_info ident = {
+ .options = WDIOF_KEEPALIVEPING |
+ WDIOF_SETTIMEOUT |
+ WDIOF_CARDRESET,
+ .identity = "w83793 watchdog"
+ };
+
+ int val, ret = 0;
+ struct w83793_data *data = filp->private_data;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ if (!nowayout)
+ ident.options |= WDIOF_MAGICCLOSE;
+ if (copy_to_user((void __user *)arg, &ident, sizeof(ident)))
+ ret = -EFAULT;
+ break;
+
+ case WDIOC_GETSTATUS:
+ val = data->watchdog_caused_reboot ? WDIOF_CARDRESET : 0;
+ ret = put_user(val, (int __user *)arg);
+ break;
+
+ case WDIOC_GETBOOTSTATUS:
+ ret = put_user(0, (int __user *)arg);
+ break;
+
+ case WDIOC_KEEPALIVE:
+ ret = watchdog_trigger(data);
+ break;
+
+ case WDIOC_GETTIMEOUT:
+ val = watchdog_get_timeout(data);
+ ret = put_user(val, (int __user *)arg);
+ break;
+
+ case WDIOC_SETTIMEOUT:
+ if (get_user(val, (int __user *)arg)) {
+ ret = -EFAULT;
+ break;
+ }
+ ret = watchdog_set_timeout(data, val);
+ if (ret > 0)
+ ret = put_user(ret, (int __user *)arg);
+ break;
+
+ case WDIOC_SETOPTIONS:
+ if (get_user(val, (int __user *)arg)) {
+ ret = -EFAULT;
+ break;
+ }
+
+ if (val & WDIOS_DISABLECARD)
+ ret = watchdog_disable(data);
+ else if (val & WDIOS_ENABLECARD)
+ ret = watchdog_enable(data);
+ else
+ ret = -EINVAL;
+
+ break;
+ default:
+ ret = -ENOTTY;
+ }
+
+ return ret;
+}
+
+static const struct file_operations watchdog_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = watchdog_open,
+ .release = watchdog_close,
+ .write = watchdog_write,
+ .ioctl = watchdog_ioctl,
+};
+
+/*
+ * Notifier for system down
+ */
+
+static int watchdog_notify_sys(struct notifier_block *this, unsigned long code,
+ void *unused)
+{
+ struct w83793_data *data = NULL;
+
+ if (code == SYS_DOWN || code == SYS_HALT) {
+
+ /* Disable each registered watchdog */
+ mutex_lock(&watchdog_data_mutex);
+ list_for_each_entry(data, &watchdog_data_list, list) {
+ if (data->watchdog_miscdev.minor)
+ watchdog_disable(data);
+ }
+ mutex_unlock(&watchdog_data_mutex);
+ }
+
+ return NOTIFY_DONE;
}
+/*
+ * The WDT needs to learn about soft shutdowns in order to
+ * turn the timebomb registers off.
+ */
+
+static struct notifier_block watchdog_notifier = {
+ .notifier_call = watchdog_notify_sys,
+};
+
+/*
+ * Init / remove routines
+ */
+
static int w83793_remove(struct i2c_client *client)
{
struct w83793_data *data = i2c_get_clientdata(client);
struct device *dev = &client->dev;
- int i;
+ int i, tmp;
+
+ /* Unregister the watchdog (if registered) */
+ if (data->watchdog_miscdev.minor) {
+ misc_deregister(&data->watchdog_miscdev);
+
+ if (data->watchdog_is_open) {
+ dev_warn(&client->dev,
+ "i2c client detached with watchdog open! "
+ "Stopping watchdog.\n");
+ watchdog_disable(data);
+ }
+
+ mutex_lock(&watchdog_data_mutex);
+ list_del(&data->list);
+ mutex_unlock(&watchdog_data_mutex);
+
+ /* Tell the watchdog code the client is gone */
+ mutex_lock(&data->watchdog_lock);
+ data->client = NULL;
+ mutex_unlock(&data->watchdog_lock);
+ }
+
+ /* Reset Configuration Register to Disable Watch Dog Registers */
+ tmp = w83793_read_value(client, W83793_REG_CONFIG);
+ w83793_write_value(client, W83793_REG_CONFIG, tmp & ~0x04);
+
+ unregister_reboot_notifier(&watchdog_notifier);
hwmon_device_unregister(data->hwmon_dev);
@@ -1099,7 +1494,10 @@ static int w83793_remove(struct i2c_client *client)
if (data->lm75[1] != NULL)
i2c_unregister_device(data->lm75[1]);
- kfree(data);
+ /* Decrease data reference counter */
+ mutex_lock(&watchdog_data_mutex);
+ kref_put(&data->kref, w83793_release_resources);
+ mutex_unlock(&watchdog_data_mutex);
return 0;
}
@@ -1203,6 +1601,7 @@ static int w83793_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
+ const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 };
struct w83793_data *data;
int i, tmp, val, err;
int files_fan = ARRAY_SIZE(w83793_left_fan) / 7;
@@ -1218,6 +1617,14 @@ static int w83793_probe(struct i2c_client *client,
i2c_set_clientdata(client, data);
data->bank = i2c_smbus_read_byte_data(client, W83793_REG_BANKSEL);
mutex_init(&data->update_lock);
+ mutex_init(&data->watchdog_lock);
+ INIT_LIST_HEAD(&data->list);
+ kref_init(&data->kref);
+
+ /* Store client pointer in our data struct for watchdog usage
+ (where the client is found through a data ptr instead of the
+ otherway around) */
+ data->client = client;
err = w83793_detect_subclients(client);
if (err)
@@ -1380,8 +1787,77 @@ static int w83793_probe(struct i2c_client *client,
goto exit_remove;
}
+ /* Watchdog initialization */
+
+ /* Register boot notifier */
+ err = register_reboot_notifier(&watchdog_notifier);
+ if (err != 0) {
+ dev_err(&client->dev,
+ "cannot register reboot notifier (err=%d)\n", err);
+ goto exit_devunreg;
+ }
+
+ /* Enable Watchdog registers.
+ Set Configuration Register to Enable Watch Dog Registers
+ (Bit 2) = XXXX, X1XX. */
+ tmp = w83793_read_value(client, W83793_REG_CONFIG);
+ w83793_write_value(client, W83793_REG_CONFIG, tmp | 0x04);
+
+ /* Set the default watchdog timeout */
+ data->watchdog_timeout = timeout;
+
+ /* Check, if last reboot was caused by watchdog */
+ data->watchdog_caused_reboot =
+ w83793_read_value(data->client, W83793_REG_WDT_STATUS) & 0x01;
+
+ /* Disable Soft Watchdog during initialiation */
+ watchdog_disable(data);
+
+ /* We take the data_mutex lock early so that watchdog_open() cannot
+ run when misc_register() has completed, but we've not yet added
+ our data to the watchdog_data_list (and set the default timeout) */
+ mutex_lock(&watchdog_data_mutex);
+ for (i = 0; i < ARRAY_SIZE(watchdog_minors); i++) {
+ /* Register our watchdog part */
+ snprintf(data->watchdog_name, sizeof(data->watchdog_name),
+ "watchdog%c", (i == 0) ? '\0' : ('0' + i));
+ data->watchdog_miscdev.name = data->watchdog_name;
+ data->watchdog_miscdev.fops = &watchdog_fops;
+ data->watchdog_miscdev.minor = watchdog_minors[i];
+
+ err = misc_register(&data->watchdog_miscdev);
+ if (err == -EBUSY)
+ continue;
+ if (err) {
+ data->watchdog_miscdev.minor = 0;
+ dev_err(&client->dev,
+ "Registering watchdog chardev: %d\n", err);
+ break;
+ }
+
+ list_add(&data->list, &watchdog_data_list);
+
+ dev_info(&client->dev,
+ "Registered watchdog chardev major 10, minor: %d\n",
+ watchdog_minors[i]);
+ break;
+ }
+ if (i == ARRAY_SIZE(watchdog_minors)) {
+ data->watchdog_miscdev.minor = 0;
+ dev_warn(&client->dev, "Couldn't register watchdog chardev "
+ "(due to no free minor)\n");
+ }
+
+ mutex_unlock(&watchdog_data_mutex);
+
return 0;
+ /* Unregister hwmon device */
+
+exit_devunreg:
+
+ hwmon_device_unregister(data->hwmon_dev);
+
/* Unregister sysfs hooks */
exit_remove:
@@ -1628,7 +2104,7 @@ static void __exit sensors_w83793_exit(void)
i2c_del_driver(&w83793_driver);
}
-MODULE_AUTHOR("Yuan Mu");
+MODULE_AUTHOR("Yuan Mu, Sven Anders");
MODULE_DESCRIPTION("w83793 driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 4cc3807bd31..9c6170cd9aa 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -106,6 +106,8 @@ config I2C_I801
config I2C_ISCH
tristate "Intel SCH SMBus 1.0"
depends on PCI
+ select MFD_CORE
+ select LPC_SCH
help
Say Y here if you want to use SMBus controller on the Intel SCH
based systems.
@@ -419,13 +421,12 @@ config I2C_IXP2000
instead.
config I2C_MPC
- tristate "MPC107/824x/85xx/52xx/86xx"
+ tristate "MPC107/824x/85xx/512x/52xx/83xx/86xx"
depends on PPC32
help
If you say yes to this option, support will be included for the
- built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
- MPC85xx/MPC8641 family processors. The driver may also work on 52xx
- family processors, though interrupts are known not to work.
+ built-in I2C interface on the MPC107, Tsi107, MPC512x, MPC52xx,
+ MPC8240, MPC8245, MPC83xx, MPC85xx and MPC8641 family processors.
This driver can also be built as a module. If so, the module
will be called i2c-mpc.
@@ -440,6 +441,13 @@ config I2C_MV64XXX
This driver can also be built as a module. If so, the module
will be called i2c-mv64xxx.
+config I2C_NOMADIK
+ tristate "ST-Ericsson Nomadik/Ux500 I2C Controller"
+ depends on PLAT_NOMADIK
+ help
+ If you say yes to this option, support will be included for the
+ I2C interface from ST-Ericsson's Nomadik and Ux500 architectures.
+
config I2C_OCORES
tristate "OpenCores I2C Controller"
depends on EXPERIMENTAL
@@ -575,6 +583,16 @@ config I2C_OCTEON
This driver can also be built as a module. If so, the module
will be called i2c-octeon.
+config I2C_XILINX
+ tristate "Xilinx I2C Controller"
+ depends on EXPERIMENTAL && HAS_IOMEM
+ help
+ If you say yes to this option, support will be included for the
+ Xilinx I2C controller.
+
+ This driver can also be built as a module. If so, the module
+ will be called xilinx_i2c.
+
comment "External I2C/SMBus adapter drivers"
config I2C_PARPORT
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index c2c4ea1908d..097236f631e 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -42,6 +42,7 @@ obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o
obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o
obj-$(CONFIG_I2C_MPC) += i2c-mpc.o
obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
+obj-$(CONFIG_I2C_NOMADIK) += i2c-nomadik.o
obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o
obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o
@@ -55,6 +56,7 @@ obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o
obj-$(CONFIG_I2C_STU300) += i2c-stu300.o
obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o
+obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o
# External I2C/SMBus adapter drivers
obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o
diff --git a/drivers/i2c/busses/i2c-designware.c b/drivers/i2c/busses/i2c-designware.c
index 9e18ef97f15..3e72b69aa7f 100644
--- a/drivers/i2c/busses/i2c-designware.c
+++ b/drivers/i2c/busses/i2c-designware.c
@@ -497,13 +497,13 @@ static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
int i;
if (abort_source & DW_IC_TX_ABRT_NOACK) {
- for_each_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
+ for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
dev_dbg(dev->dev,
"%s: %s\n", __func__, abort_sources[i]);
return -EREMOTEIO;
}
- for_each_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
+ for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources))
dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]);
if (abort_source & DW_IC_TX_ARB_LOST)
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 75bf820e7cc..32375bddae7 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -627,7 +627,6 @@ static int __exit i2c_imx_remove(struct platform_device *pdev)
}
static struct platform_driver i2c_imx_driver = {
- .probe = i2c_imx_probe,
.remove = __exit_p(i2c_imx_remove),
.driver = {
.name = DRIVER_NAME,
diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c
index 69c22f79f23..ddc258edb34 100644
--- a/drivers/i2c/busses/i2c-isch.c
+++ b/drivers/i2c/busses/i2c-isch.c
@@ -27,7 +27,7 @@
*/
#include <linux/module.h>
-#include <linux/pci.h>
+#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/stddef.h>
@@ -46,12 +46,6 @@
#define SMBHSTDAT1 (7 + sch_smba)
#define SMBBLKDAT (0x20 + sch_smba)
-/* count for request_region */
-#define SMBIOSIZE 64
-
-/* PCI Address Constants */
-#define SMBBA_SCH 0x40
-
/* Other settings */
#define MAX_TIMEOUT 500
@@ -63,7 +57,6 @@
#define SCH_BLOCK_DATA 0x05
static unsigned short sch_smba;
-static struct pci_driver sch_driver;
static struct i2c_adapter sch_adapter;
/*
@@ -256,37 +249,23 @@ static struct i2c_adapter sch_adapter = {
.algo = &smbus_algorithm,
};
-static const struct pci_device_id sch_ids[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) },
- { 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, sch_ids);
-
-static int __devinit sch_probe(struct pci_dev *dev,
- const struct pci_device_id *id)
+static int __devinit smbus_sch_probe(struct platform_device *dev)
{
+ struct resource *res;
int retval;
- unsigned int smba;
- pci_read_config_dword(dev, SMBBA_SCH, &smba);
- if (!(smba & (1 << 31))) {
- dev_err(&dev->dev, "SMBus I/O space disabled!\n");
- return -ENODEV;
- }
+ res = platform_get_resource(dev, IORESOURCE_IO, 0);
+ if (!res)
+ return -EBUSY;
- sch_smba = (unsigned short)smba;
- if (sch_smba == 0) {
- dev_err(&dev->dev, "SMBus base address uninitialized!\n");
- return -ENODEV;
- }
- if (acpi_check_region(sch_smba, SMBIOSIZE, sch_driver.name))
- return -ENODEV;
- if (!request_region(sch_smba, SMBIOSIZE, sch_driver.name)) {
+ if (!request_region(res->start, resource_size(res), dev->name)) {
dev_err(&dev->dev, "SMBus region 0x%x already in use!\n",
sch_smba);
return -EBUSY;
}
+
+ sch_smba = res->start;
+
dev_dbg(&dev->dev, "SMBA = 0x%X\n", sch_smba);
/* set up the sysfs linkage to our parent device */
@@ -298,37 +277,43 @@ static int __devinit sch_probe(struct pci_dev *dev,
retval = i2c_add_adapter(&sch_adapter);
if (retval) {
dev_err(&dev->dev, "Couldn't register adapter!\n");
- release_region(sch_smba, SMBIOSIZE);
+ release_region(res->start, resource_size(res));
sch_smba = 0;
}
return retval;
}
-static void __devexit sch_remove(struct pci_dev *dev)
+static int __devexit smbus_sch_remove(struct platform_device *pdev)
{
+ struct resource *res;
if (sch_smba) {
i2c_del_adapter(&sch_adapter);
- release_region(sch_smba, SMBIOSIZE);
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ release_region(res->start, resource_size(res));
sch_smba = 0;
}
+
+ return 0;
}
-static struct pci_driver sch_driver = {
- .name = "isch_smbus",
- .id_table = sch_ids,
- .probe = sch_probe,
- .remove = __devexit_p(sch_remove),
+static struct platform_driver smbus_sch_driver = {
+ .driver = {
+ .name = "isch_smbus",
+ .owner = THIS_MODULE,
+ },
+ .probe = smbus_sch_probe,
+ .remove = __devexit_p(smbus_sch_remove),
};
static int __init i2c_sch_init(void)
{
- return pci_register_driver(&sch_driver);
+ return platform_driver_register(&smbus_sch_driver);
}
static void __exit i2c_sch_exit(void)
{
- pci_unregister_driver(&sch_driver);
+ platform_driver_unregister(&smbus_sch_driver);
}
MODULE_AUTHOR("Jacob Pan <jacob.jun.pan@intel.com>");
@@ -337,3 +322,4 @@ MODULE_LICENSE("GPL");
module_init(i2c_sch_init);
module_exit(i2c_sch_exit);
+MODULE_ALIAS("platform:isch_smbus");
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index f627001108b..78a15af3294 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -31,6 +31,9 @@
#define DRV_NAME "mpc-i2c"
+#define MPC_I2C_CLOCK_LEGACY 0
+#define MPC_I2C_CLOCK_PRESERVE (~0U)
+
#define MPC_I2C_FDR 0x04
#define MPC_I2C_CR 0x08
#define MPC_I2C_SR 0x0c
@@ -66,10 +69,9 @@ struct mpc_i2c_divider {
u16 fdr; /* including dfsrr */
};
-struct mpc_i2c_match_data {
- void (*setclock)(struct device_node *node,
- struct mpc_i2c *i2c,
- u32 clock, u32 prescaler);
+struct mpc_i2c_data {
+ void (*setup)(struct device_node *node, struct mpc_i2c *i2c,
+ u32 clock, u32 prescaler);
u32 prescaler;
};
@@ -164,8 +166,8 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
return 0;
}
-#ifdef CONFIG_PPC_MPC52xx
-static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] = {
+#if defined(CONFIG_PPC_MPC52xx) || defined(CONFIG_PPC_MPC512x)
+static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] __devinitconst = {
{20, 0x20}, {22, 0x21}, {24, 0x22}, {26, 0x23},
{28, 0x24}, {30, 0x01}, {32, 0x25}, {34, 0x02},
{36, 0x26}, {40, 0x27}, {44, 0x04}, {48, 0x28},
@@ -186,14 +188,15 @@ static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] = {
{10240, 0x9d}, {12288, 0x9e}, {15360, 0x9f}
};
-int mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock, int prescaler)
+static int __devinit mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock,
+ int prescaler)
{
const struct mpc_i2c_divider *div = NULL;
unsigned int pvr = mfspr(SPRN_PVR);
u32 divider;
int i;
- if (!clock)
+ if (clock == MPC_I2C_CLOCK_LEGACY)
return -EINVAL;
/* Determine divider value */
@@ -215,12 +218,18 @@ int mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock, int prescaler)
return div ? (int)div->fdr : -EINVAL;
}
-static void mpc_i2c_setclock_52xx(struct device_node *node,
- struct mpc_i2c *i2c,
- u32 clock, u32 prescaler)
+static void __devinit mpc_i2c_setup_52xx(struct device_node *node,
+ struct mpc_i2c *i2c,
+ u32 clock, u32 prescaler)
{
int ret, fdr;
+ if (clock == MPC_I2C_CLOCK_PRESERVE) {
+ dev_dbg(i2c->dev, "using fdr %d\n",
+ readb(i2c->base + MPC_I2C_FDR));
+ return;
+ }
+
ret = mpc_i2c_get_fdr_52xx(node, clock, prescaler);
fdr = (ret >= 0) ? ret : 0x3f; /* backward compatibility */
@@ -229,16 +238,52 @@ static void mpc_i2c_setclock_52xx(struct device_node *node,
if (ret >= 0)
dev_info(i2c->dev, "clock %d Hz (fdr=%d)\n", clock, fdr);
}
-#else /* !CONFIG_PPC_MPC52xx */
-static void mpc_i2c_setclock_52xx(struct device_node *node,
- struct mpc_i2c *i2c,
- u32 clock, u32 prescaler)
+#else /* !(CONFIG_PPC_MPC52xx || CONFIG_PPC_MPC512x) */
+static void __devinit mpc_i2c_setup_52xx(struct device_node *node,
+ struct mpc_i2c *i2c,
+ u32 clock, u32 prescaler)
+{
+}
+#endif /* CONFIG_PPC_MPC52xx || CONFIG_PPC_MPC512x */
+
+#ifdef CONFIG_PPC_MPC512x
+static void __devinit mpc_i2c_setup_512x(struct device_node *node,
+ struct mpc_i2c *i2c,
+ u32 clock, u32 prescaler)
+{
+ struct device_node *node_ctrl;
+ void __iomem *ctrl;
+ const u32 *pval;
+ u32 idx;
+
+ /* Enable I2C interrupts for mpc5121 */
+ node_ctrl = of_find_compatible_node(NULL, NULL,
+ "fsl,mpc5121-i2c-ctrl");
+ if (node_ctrl) {
+ ctrl = of_iomap(node_ctrl, 0);
+ if (ctrl) {
+ /* Interrupt enable bits for i2c-0/1/2: bit 24/26/28 */
+ pval = of_get_property(node, "reg", NULL);
+ idx = (*pval & 0xff) / 0x20;
+ setbits32(ctrl, 1 << (24 + idx * 2));
+ iounmap(ctrl);
+ }
+ of_node_put(node_ctrl);
+ }
+
+ /* The clock setup for the 52xx works also fine for the 512x */
+ mpc_i2c_setup_52xx(node, i2c, clock, prescaler);
+}
+#else /* CONFIG_PPC_MPC512x */
+static void __devinit mpc_i2c_setup_512x(struct device_node *node,
+ struct mpc_i2c *i2c,
+ u32 clock, u32 prescaler)
{
}
-#endif /* CONFIG_PPC_MPC52xx*/
+#endif /* CONFIG_PPC_MPC512x */
#ifdef CONFIG_FSL_SOC
-static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] = {
+static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] __devinitconst = {
{160, 0x0120}, {192, 0x0121}, {224, 0x0122}, {256, 0x0123},
{288, 0x0100}, {320, 0x0101}, {352, 0x0601}, {384, 0x0102},
{416, 0x0602}, {448, 0x0126}, {480, 0x0103}, {512, 0x0127},
@@ -258,7 +303,7 @@ static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] = {
{49152, 0x011e}, {61440, 0x011f}
};
-u32 mpc_i2c_get_sec_cfg_8xxx(void)
+static u32 __devinit mpc_i2c_get_sec_cfg_8xxx(void)
{
struct device_node *node = NULL;
u32 __iomem *reg;
@@ -287,13 +332,14 @@ u32 mpc_i2c_get_sec_cfg_8xxx(void)
return val;
}
-int mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock, u32 prescaler)
+static int __devinit mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock,
+ u32 prescaler)
{
const struct mpc_i2c_divider *div = NULL;
u32 divider;
int i;
- if (!clock)
+ if (clock == MPC_I2C_CLOCK_LEGACY)
return -EINVAL;
/* Determine proper divider value */
@@ -320,12 +366,19 @@ int mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock, u32 prescaler)
return div ? (int)div->fdr : -EINVAL;
}
-static void mpc_i2c_setclock_8xxx(struct device_node *node,
- struct mpc_i2c *i2c,
- u32 clock, u32 prescaler)
+static void __devinit mpc_i2c_setup_8xxx(struct device_node *node,
+ struct mpc_i2c *i2c,
+ u32 clock, u32 prescaler)
{
int ret, fdr;
+ if (clock == MPC_I2C_CLOCK_PRESERVE) {
+ dev_dbg(i2c->dev, "using dfsrr %d, fdr %d\n",
+ readb(i2c->base + MPC_I2C_DFSRR),
+ readb(i2c->base + MPC_I2C_FDR));
+ return;
+ }
+
ret = mpc_i2c_get_fdr_8xxx(node, clock, prescaler);
fdr = (ret >= 0) ? ret : 0x1031; /* backward compatibility */
@@ -338,9 +391,9 @@ static void mpc_i2c_setclock_8xxx(struct device_node *node,
}
#else /* !CONFIG_FSL_SOC */
-static void mpc_i2c_setclock_8xxx(struct device_node *node,
- struct mpc_i2c *i2c,
- u32 clock, u32 prescaler)
+static void __devinit mpc_i2c_setup_8xxx(struct device_node *node,
+ struct mpc_i2c *i2c,
+ u32 clock, u32 prescaler)
{
}
#endif /* CONFIG_FSL_SOC */
@@ -494,7 +547,7 @@ static int __devinit fsl_i2c_probe(struct of_device *op,
{
struct mpc_i2c *i2c;
const u32 *prop;
- u32 clock = 0;
+ u32 clock = MPC_I2C_CLOCK_LEGACY;
int result = 0;
int plen;
@@ -523,21 +576,21 @@ static int __devinit fsl_i2c_probe(struct of_device *op,
}
}
- if (!of_get_property(op->node, "fsl,preserve-clocking", NULL)) {
+ if (of_get_property(op->node, "fsl,preserve-clocking", NULL)) {
+ clock = MPC_I2C_CLOCK_PRESERVE;
+ } else {
prop = of_get_property(op->node, "clock-frequency", &plen);
if (prop && plen == sizeof(u32))
clock = *prop;
+ }
- if (match->data) {
- struct mpc_i2c_match_data *data =
- (struct mpc_i2c_match_data *)match->data;
- data->setclock(op->node, i2c, clock, data->prescaler);
- } else {
- /* Backwards compatibility */
- if (of_get_property(op->node, "dfsrr", NULL))
- mpc_i2c_setclock_8xxx(op->node, i2c,
- clock, 0);
- }
+ if (match->data) {
+ struct mpc_i2c_data *data = match->data;
+ data->setup(op->node, i2c, clock, data->prescaler);
+ } else {
+ /* Backwards compatibility */
+ if (of_get_property(op->node, "dfsrr", NULL))
+ mpc_i2c_setup_8xxx(op->node, i2c, clock, 0);
}
dev_set_drvdata(&op->dev, i2c);
@@ -582,47 +635,42 @@ static int __devexit fsl_i2c_remove(struct of_device *op)
return 0;
};
+static struct mpc_i2c_data mpc_i2c_data_512x __devinitdata = {
+ .setup = mpc_i2c_setup_512x,
+};
+
+static struct mpc_i2c_data mpc_i2c_data_52xx __devinitdata = {
+ .setup = mpc_i2c_setup_52xx,
+};
+
+static struct mpc_i2c_data mpc_i2c_data_8313 __devinitdata = {
+ .setup = mpc_i2c_setup_8xxx,
+};
+
+static struct mpc_i2c_data mpc_i2c_data_8543 __devinitdata = {
+ .setup = mpc_i2c_setup_8xxx,
+ .prescaler = 2,
+};
+
+static struct mpc_i2c_data mpc_i2c_data_8544 __devinitdata = {
+ .setup = mpc_i2c_setup_8xxx,
+ .prescaler = 3,
+};
+
static const struct of_device_id mpc_i2c_of_match[] = {
- {.compatible = "mpc5200-i2c",
- .data = &(struct mpc_i2c_match_data) {
- .setclock = mpc_i2c_setclock_52xx,
- },
- },
- {.compatible = "fsl,mpc5200b-i2c",
- .data = &(struct mpc_i2c_match_data) {
- .setclock = mpc_i2c_setclock_52xx,
- },
- },
- {.compatible = "fsl,mpc5200-i2c",
- .data = &(struct mpc_i2c_match_data) {
- .setclock = mpc_i2c_setclock_52xx,
- },
- },
- {.compatible = "fsl,mpc8313-i2c",
- .data = &(struct mpc_i2c_match_data) {
- .setclock = mpc_i2c_setclock_8xxx,
- },
- },
- {.compatible = "fsl,mpc8543-i2c",
- .data = &(struct mpc_i2c_match_data) {
- .setclock = mpc_i2c_setclock_8xxx,
- .prescaler = 2,
- },
- },
- {.compatible = "fsl,mpc8544-i2c",
- .data = &(struct mpc_i2c_match_data) {
- .setclock = mpc_i2c_setclock_8xxx,
- .prescaler = 3,
- },
+ {.compatible = "mpc5200-i2c", .data = &mpc_i2c_data_52xx, },
+ {.compatible = "fsl,mpc5200b-i2c", .data = &mpc_i2c_data_52xx, },
+ {.compatible = "fsl,mpc5200-i2c", .data = &mpc_i2c_data_52xx, },
+ {.compatible = "fsl,mpc5121-i2c", .data = &mpc_i2c_data_512x, },
+ {.compatible = "fsl,mpc8313-i2c", .data = &mpc_i2c_data_8313, },
+ {.compatible = "fsl,mpc8543-i2c", .data = &mpc_i2c_data_8543, },
+ {.compatible = "fsl,mpc8544-i2c", .data = &mpc_i2c_data_8544, },
/* Backward compatibility */
- },
{.compatible = "fsl-i2c", },
{},
};
-
MODULE_DEVICE_TABLE(of, mpc_i2c_of_match);
-
/* Structure for a device driver */
static struct of_platform_driver mpc_i2c_driver = {
.match_table = mpc_i2c_of_match,
@@ -655,5 +703,5 @@ module_exit(fsl_i2c_exit);
MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>");
MODULE_DESCRIPTION("I2C-Bus adapter for MPC107 bridge and "
- "MPC824x/85xx/52xx processors");
+ "MPC824x/83xx/85xx/86xx/512x/52xx processors");
MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c
new file mode 100644
index 00000000000..a15f731fa45
--- /dev/null
+++ b/drivers/i2c/busses/i2c-nomadik.c
@@ -0,0 +1,959 @@
+/*
+ * Copyright (C) 2009 ST-Ericsson
+ * Copyright (C) 2009 STMicroelectronics
+ *
+ * I2C master mode controller driver, used in Nomadik 8815
+ * and Ux500 platforms.
+ *
+ * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
+ * Author: Sachin Verma <sachin.verma@st.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/platform_device.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <plat/i2c.h>
+
+#define DRIVER_NAME "nmk-i2c"
+
+/* I2C Controller register offsets */
+#define I2C_CR (0x000)
+#define I2C_SCR (0x004)
+#define I2C_HSMCR (0x008)
+#define I2C_MCR (0x00C)
+#define I2C_TFR (0x010)
+#define I2C_SR (0x014)
+#define I2C_RFR (0x018)
+#define I2C_TFTR (0x01C)
+#define I2C_RFTR (0x020)
+#define I2C_DMAR (0x024)
+#define I2C_BRCR (0x028)
+#define I2C_IMSCR (0x02C)
+#define I2C_RISR (0x030)
+#define I2C_MISR (0x034)
+#define I2C_ICR (0x038)
+
+/* Control registers */
+#define I2C_CR_PE (0x1 << 0) /* Peripheral Enable */
+#define I2C_CR_OM (0x3 << 1) /* Operating mode */
+#define I2C_CR_SAM (0x1 << 3) /* Slave addressing mode */
+#define I2C_CR_SM (0x3 << 4) /* Speed mode */
+#define I2C_CR_SGCM (0x1 << 6) /* Slave general call mode */
+#define I2C_CR_FTX (0x1 << 7) /* Flush Transmit */
+#define I2C_CR_FRX (0x1 << 8) /* Flush Receive */
+#define I2C_CR_DMA_TX_EN (0x1 << 9) /* DMA Tx enable */
+#define I2C_CR_DMA_RX_EN (0x1 << 10) /* DMA Rx Enable */
+#define I2C_CR_DMA_SLE (0x1 << 11) /* DMA sync. logic enable */
+#define I2C_CR_LM (0x1 << 12) /* Loopback mode */
+#define I2C_CR_FON (0x3 << 13) /* Filtering on */
+#define I2C_CR_FS (0x3 << 15) /* Force stop enable */
+
+/* Master controller (MCR) register */
+#define I2C_MCR_OP (0x1 << 0) /* Operation */
+#define I2C_MCR_A7 (0x7f << 1) /* 7-bit address */
+#define I2C_MCR_EA10 (0x7 << 8) /* 10-bit Extended address */
+#define I2C_MCR_SB (0x1 << 11) /* Extended address */
+#define I2C_MCR_AM (0x3 << 12) /* Address type */
+#define I2C_MCR_STOP (0x1 << 14) /* Stop condition */
+#define I2C_MCR_LENGTH (0x7ff << 15) /* Transaction length */
+
+/* Status register (SR) */
+#define I2C_SR_OP (0x3 << 0) /* Operation */
+#define I2C_SR_STATUS (0x3 << 2) /* controller status */
+#define I2C_SR_CAUSE (0x7 << 4) /* Abort cause */
+#define I2C_SR_TYPE (0x3 << 7) /* Receive type */
+#define I2C_SR_LENGTH (0x7ff << 9) /* Transfer length */
+
+/* Interrupt mask set/clear (IMSCR) bits */
+#define I2C_IT_TXFE (0x1 << 0)
+#define I2C_IT_TXFNE (0x1 << 1)
+#define I2C_IT_TXFF (0x1 << 2)
+#define I2C_IT_TXFOVR (0x1 << 3)
+#define I2C_IT_RXFE (0x1 << 4)
+#define I2C_IT_RXFNF (0x1 << 5)
+#define I2C_IT_RXFF (0x1 << 6)
+#define I2C_IT_RFSR (0x1 << 16)
+#define I2C_IT_RFSE (0x1 << 17)
+#define I2C_IT_WTSR (0x1 << 18)
+#define I2C_IT_MTD (0x1 << 19)
+#define I2C_IT_STD (0x1 << 20)
+#define I2C_IT_MAL (0x1 << 24)
+#define I2C_IT_BERR (0x1 << 25)
+#define I2C_IT_MTDWS (0x1 << 28)
+
+#define GEN_MASK(val, mask, sb) (((val) << (sb)) & (mask))
+
+/* some bits in ICR are reserved */
+#define I2C_CLEAR_ALL_INTS 0x131f007f
+
+/* first three msb bits are reserved */
+#define IRQ_MASK(mask) (mask & 0x1fffffff)
+
+/* maximum threshold value */
+#define MAX_I2C_FIFO_THRESHOLD 15
+
+enum i2c_status {
+ I2C_NOP,
+ I2C_ON_GOING,
+ I2C_OK,
+ I2C_ABORT
+};
+
+/* operation */
+enum i2c_operation {
+ I2C_NO_OPERATION = 0xff,
+ I2C_WRITE = 0x00,
+ I2C_READ = 0x01
+};
+
+/* controller response timeout in ms */
+#define I2C_TIMEOUT_MS 500
+
+/**
+ * struct i2c_nmk_client - client specific data
+ * @slave_adr: 7-bit slave address
+ * @count: no. bytes to be transfered
+ * @buffer: client data buffer
+ * @xfer_bytes: bytes transfered till now
+ * @operation: current I2C operation
+ */
+struct i2c_nmk_client {
+ unsigned short slave_adr;
+ unsigned long count;
+ unsigned char *buffer;
+ unsigned long xfer_bytes;
+ enum i2c_operation operation;
+};
+
+/**
+ * struct nmk_i2c_dev - private data structure of the controller
+ * @pdev: parent platform device
+ * @adap: corresponding I2C adapter
+ * @irq: interrupt line for the controller
+ * @virtbase: virtual io memory area
+ * @clk: hardware i2c block clock
+ * @cfg: machine provided controller configuration
+ * @cli: holder of client specific data
+ * @stop: stop condition
+ * @xfer_complete: acknowledge completion for a I2C message
+ * @result: controller propogated result
+ */
+struct nmk_i2c_dev {
+ struct platform_device *pdev;
+ struct i2c_adapter adap;
+ int irq;
+ void __iomem *virtbase;
+ struct clk *clk;
+ struct nmk_i2c_controller cfg;
+ struct i2c_nmk_client cli;
+ int stop;
+ struct completion xfer_complete;
+ int result;
+};
+
+/* controller's abort causes */
+static const char *abort_causes[] = {
+ "no ack received after address transmission",
+ "no ack received during data phase",
+ "ack received after xmission of master code",
+ "master lost arbitration",
+ "slave restarts",
+ "slave reset",
+ "overflow, maxsize is 2047 bytes",
+};
+
+static inline void i2c_set_bit(void __iomem *reg, u32 mask)
+{
+ writel(readl(reg) | mask, reg);
+}
+
+static inline void i2c_clr_bit(void __iomem *reg, u32 mask)
+{
+ writel(readl(reg) & ~mask, reg);
+}
+
+/**
+ * flush_i2c_fifo() - This function flushes the I2C FIFO
+ * @dev: private data of I2C Driver
+ *
+ * This function flushes the I2C Tx and Rx FIFOs. It returns
+ * 0 on successful flushing of FIFO
+ */
+static int flush_i2c_fifo(struct nmk_i2c_dev *dev)
+{
+#define LOOP_ATTEMPTS 10
+ int i;
+ unsigned long timeout;
+
+ /*
+ * flush the transmit and receive FIFO. The flushing
+ * operation takes several cycles before to be completed.
+ * On the completion, the I2C internal logic clears these
+ * bits, until then no one must access Tx, Rx FIFO and
+ * should poll on these bits waiting for the completion.
+ */
+ writel((I2C_CR_FTX | I2C_CR_FRX), dev->virtbase + I2C_CR);
+
+ for (i = 0; i < LOOP_ATTEMPTS; i++) {
+ timeout = jiffies + msecs_to_jiffies(I2C_TIMEOUT_MS);
+
+ while (!time_after(jiffies, timeout)) {
+ if ((readl(dev->virtbase + I2C_CR) &
+ (I2C_CR_FTX | I2C_CR_FRX)) == 0)
+ return 0;
+ }
+ }
+
+ dev_err(&dev->pdev->dev, "flushing operation timed out "
+ "giving up after %d attempts", LOOP_ATTEMPTS);
+
+ return -ETIMEDOUT;
+}
+
+/**
+ * disable_all_interrupts() - Disable all interrupts of this I2c Bus
+ * @dev: private data of I2C Driver
+ */
+static void disable_all_interrupts(struct nmk_i2c_dev *dev)
+{
+ u32 mask = IRQ_MASK(0);
+ writel(mask, dev->virtbase + I2C_IMSCR);
+}
+
+/**
+ * clear_all_interrupts() - Clear all interrupts of I2C Controller
+ * @dev: private data of I2C Driver
+ */
+static void clear_all_interrupts(struct nmk_i2c_dev *dev)
+{
+ u32 mask;
+ mask = IRQ_MASK(I2C_CLEAR_ALL_INTS);
+ writel(mask, dev->virtbase + I2C_ICR);
+}
+
+/**
+ * init_hw() - initialize the I2C hardware
+ * @dev: private data of I2C Driver
+ */
+static int init_hw(struct nmk_i2c_dev *dev)
+{
+ int stat;
+
+ stat = flush_i2c_fifo(dev);
+ if (stat)
+ return stat;
+
+ /* disable the controller */
+ i2c_clr_bit(dev->virtbase + I2C_CR , I2C_CR_PE);
+
+ disable_all_interrupts(dev);
+
+ clear_all_interrupts(dev);
+
+ dev->cli.operation = I2C_NO_OPERATION;
+
+ return 0;
+}
+
+/* enable peripheral, master mode operation */
+#define DEFAULT_I2C_REG_CR ((1 << 1) | I2C_CR_PE)
+
+/**
+ * load_i2c_mcr_reg() - load the MCR register
+ * @dev: private data of controller
+ */
+static u32 load_i2c_mcr_reg(struct nmk_i2c_dev *dev)
+{
+ u32 mcr = 0;
+
+ /* 7-bit address transaction */
+ mcr |= GEN_MASK(1, I2C_MCR_AM, 12);
+ mcr |= GEN_MASK(dev->cli.slave_adr, I2C_MCR_A7, 1);
+
+ /* start byte procedure not applied */
+ mcr |= GEN_MASK(0, I2C_MCR_SB, 11);
+
+ /* check the operation, master read/write? */
+ if (dev->cli.operation == I2C_WRITE)
+ mcr |= GEN_MASK(I2C_WRITE, I2C_MCR_OP, 0);
+ else
+ mcr |= GEN_MASK(I2C_READ, I2C_MCR_OP, 0);
+
+ /* stop or repeated start? */
+ if (dev->stop)
+ mcr |= GEN_MASK(1, I2C_MCR_STOP, 14);
+ else
+ mcr &= ~(GEN_MASK(1, I2C_MCR_STOP, 14));
+
+ mcr |= GEN_MASK(dev->cli.count, I2C_MCR_LENGTH, 15);
+
+ return mcr;
+}
+
+/**
+ * setup_i2c_controller() - setup the controller
+ * @dev: private data of controller
+ */
+static void setup_i2c_controller(struct nmk_i2c_dev *dev)
+{
+ u32 brcr1, brcr2;
+ u32 i2c_clk, div;
+
+ writel(0x0, dev->virtbase + I2C_CR);
+ writel(0x0, dev->virtbase + I2C_HSMCR);
+ writel(0x0, dev->virtbase + I2C_TFTR);
+ writel(0x0, dev->virtbase + I2C_RFTR);
+ writel(0x0, dev->virtbase + I2C_DMAR);
+
+ /*
+ * set the slsu:
+ *
+ * slsu defines the data setup time after SCL clock
+ * stretching in terms of i2c clk cycles. The
+ * needed setup time for the three modes are 250ns,
+ * 100ns, 10ns repectively thus leading to the values
+ * of 14, 6, 2 for a 48 MHz i2c clk.
+ */
+ writel(dev->cfg.slsu << 16, dev->virtbase + I2C_SCR);
+
+ i2c_clk = clk_get_rate(dev->clk);
+
+ /* fallback to std. mode if machine has not provided it */
+ if (dev->cfg.clk_freq == 0)
+ dev->cfg.clk_freq = 100000;
+
+ /*
+ * The spec says, in case of std. mode the divider is
+ * 2 whereas it is 3 for fast and fastplus mode of
+ * operation. TODO - high speed support.
+ */
+ div = (dev->cfg.clk_freq > 100000) ? 3 : 2;
+
+ /*
+ * generate the mask for baud rate counters. The controller
+ * has two baud rate counters. One is used for High speed
+ * operation, and the other is for std, fast mode, fast mode
+ * plus operation. Currently we do not supprt high speed mode
+ * so set brcr1 to 0.
+ */
+ brcr1 = 0 << 16;
+ brcr2 = (i2c_clk/(dev->cfg.clk_freq * div)) & 0xffff;
+
+ /* set the baud rate counter register */
+ writel((brcr1 | brcr2), dev->virtbase + I2C_BRCR);
+
+ /*
+ * set the speed mode. Currently we support
+ * only standard and fast mode of operation
+ * TODO - support for fast mode plus (upto 1Mb/s)
+ * and high speed (up to 3.4 Mb/s)
+ */
+ if (dev->cfg.sm > I2C_FREQ_MODE_FAST) {
+ dev_err(&dev->pdev->dev, "do not support this mode "
+ "defaulting to std. mode\n");
+ brcr2 = i2c_clk/(100000 * 2) & 0xffff;
+ writel((brcr1 | brcr2), dev->virtbase + I2C_BRCR);
+ writel(I2C_FREQ_MODE_STANDARD << 4,
+ dev->virtbase + I2C_CR);
+ }
+ writel(dev->cfg.sm << 4, dev->virtbase + I2C_CR);
+
+ /* set the Tx and Rx FIFO threshold */
+ writel(dev->cfg.tft, dev->virtbase + I2C_TFTR);
+ writel(dev->cfg.rft, dev->virtbase + I2C_RFTR);
+}
+
+/**
+ * read_i2c() - Read from I2C client device
+ * @dev: private data of I2C Driver
+ *
+ * This function reads from i2c client device when controller is in
+ * master mode. There is a completion timeout. If there is no transfer
+ * before timeout error is returned.
+ */
+static int read_i2c(struct nmk_i2c_dev *dev)
+{
+ u32 status = 0;
+ u32 mcr;
+ u32 irq_mask = 0;
+ int timeout;
+
+ mcr = load_i2c_mcr_reg(dev);
+ writel(mcr, dev->virtbase + I2C_MCR);
+
+ /* load the current CR value */
+ writel(readl(dev->virtbase + I2C_CR) | DEFAULT_I2C_REG_CR,
+ dev->virtbase + I2C_CR);
+
+ /* enable the controller */
+ i2c_set_bit(dev->virtbase + I2C_CR, I2C_CR_PE);
+
+ init_completion(&dev->xfer_complete);
+
+ /* enable interrupts by setting the mask */
+ irq_mask = (I2C_IT_RXFNF | I2C_IT_RXFF |
+ I2C_IT_MAL | I2C_IT_BERR);
+
+ if (dev->stop)
+ irq_mask |= I2C_IT_MTD;
+ else
+ irq_mask |= I2C_IT_MTDWS;
+
+ irq_mask = I2C_CLEAR_ALL_INTS & IRQ_MASK(irq_mask);
+
+ writel(readl(dev->virtbase + I2C_IMSCR) | irq_mask,
+ dev->virtbase + I2C_IMSCR);
+
+ timeout = wait_for_completion_interruptible_timeout(
+ &dev->xfer_complete, msecs_to_jiffies(I2C_TIMEOUT_MS));
+
+ if (timeout < 0) {
+ dev_err(&dev->pdev->dev,
+ "wait_for_completion_interruptible_timeout"
+ "returned %d waiting for event\n", timeout);
+ status = timeout;
+ }
+
+ if (timeout == 0) {
+ /* controler has timedout, re-init the h/w */
+ dev_err(&dev->pdev->dev, "controller timed out, re-init h/w\n");
+ (void) init_hw(dev);
+ status = -ETIMEDOUT;
+ }
+
+ return status;
+}
+
+/**
+ * write_i2c() - Write data to I2C client.
+ * @dev: private data of I2C Driver
+ *
+ * This function writes data to I2C client
+ */
+static int write_i2c(struct nmk_i2c_dev *dev)
+{
+ u32 status = 0;
+ u32 mcr;
+ u32 irq_mask = 0;
+ int timeout;
+
+ mcr = load_i2c_mcr_reg(dev);
+
+ writel(mcr, dev->virtbase + I2C_MCR);
+
+ /* load the current CR value */
+ writel(readl(dev->virtbase + I2C_CR) | DEFAULT_I2C_REG_CR,
+ dev->virtbase + I2C_CR);
+
+ /* enable the controller */
+ i2c_set_bit(dev->virtbase + I2C_CR , I2C_CR_PE);
+
+ init_completion(&dev->xfer_complete);
+
+ /* enable interrupts by settings the masks */
+ irq_mask = (I2C_IT_TXFNE | I2C_IT_TXFOVR |
+ I2C_IT_MAL | I2C_IT_BERR);
+
+ /*
+ * check if we want to transfer a single or multiple bytes, if so
+ * set the MTDWS bit (Master Transaction Done Without Stop)
+ * to start repeated start operation
+ */
+ if (dev->stop)
+ irq_mask |= I2C_IT_MTD;
+ else
+ irq_mask |= I2C_IT_MTDWS;
+
+ irq_mask = I2C_CLEAR_ALL_INTS & IRQ_MASK(irq_mask);
+
+ writel(readl(dev->virtbase + I2C_IMSCR) | irq_mask,
+ dev->virtbase + I2C_IMSCR);
+
+ timeout = wait_for_completion_interruptible_timeout(
+ &dev->xfer_complete, msecs_to_jiffies(I2C_TIMEOUT_MS));
+
+ if (timeout < 0) {
+ dev_err(&dev->pdev->dev,
+ "wait_for_completion_interruptible_timeout"
+ "returned %d waiting for event\n", timeout);
+ status = timeout;
+ }
+
+ if (timeout == 0) {
+ /* controler has timedout, re-init the h/w */
+ dev_err(&dev->pdev->dev, "controller timed out, re-init h/w\n");
+ (void) init_hw(dev);
+ status = -ETIMEDOUT;
+ }
+
+ return status;
+}
+
+/**
+ * nmk_i2c_xfer() - I2C transfer function used by kernel framework
+ * @i2c_adap - Adapter pointer to the controller
+ * @msgs[] - Pointer to data to be written.
+ * @num_msgs - Number of messages to be executed
+ *
+ * This is the function called by the generic kernel i2c_transfer()
+ * or i2c_smbus...() API calls. Note that this code is protected by the
+ * semaphore set in the kernel i2c_transfer() function.
+ *
+ * NOTE:
+ * READ TRANSFER : We impose a restriction of the first message to be the
+ * index message for any read transaction.
+ * - a no index is coded as '0',
+ * - 2byte big endian index is coded as '3'
+ * !!! msg[0].buf holds the actual index.
+ * This is compatible with generic messages of smbus emulator
+ * that send a one byte index.
+ * eg. a I2C transation to read 2 bytes from index 0
+ * idx = 0;
+ * msg[0].addr = client->addr;
+ * msg[0].flags = 0x0;
+ * msg[0].len = 1;
+ * msg[0].buf = &idx;
+ *
+ * msg[1].addr = client->addr;
+ * msg[1].flags = I2C_M_RD;
+ * msg[1].len = 2;
+ * msg[1].buf = rd_buff
+ * i2c_transfer(adap, msg, 2);
+ *
+ * WRITE TRANSFER : The I2C standard interface interprets all data as payload.
+ * If you want to emulate an SMBUS write transaction put the
+ * index as first byte(or first and second) in the payload.
+ * eg. a I2C transation to write 2 bytes from index 1
+ * wr_buff[0] = 0x1;
+ * wr_buff[1] = 0x23;
+ * wr_buff[2] = 0x46;
+ * msg[0].flags = 0x0;
+ * msg[0].len = 3;
+ * msg[0].buf = wr_buff;
+ * i2c_transfer(adap, msg, 1);
+ *
+ * To read or write a block of data (multiple bytes) using SMBUS emulation
+ * please use the i2c_smbus_read_i2c_block_data()
+ * or i2c_smbus_write_i2c_block_data() API
+ */
+static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
+ struct i2c_msg msgs[], int num_msgs)
+{
+ int status;
+ int i;
+ u32 cause;
+ struct nmk_i2c_dev *dev = i2c_get_adapdata(i2c_adap);
+
+ status = init_hw(dev);
+ if (status)
+ return status;
+
+ /* setup the i2c controller */
+ setup_i2c_controller(dev);
+
+ for (i = 0; i < num_msgs; i++) {
+ if (unlikely(msgs[i].flags & I2C_M_TEN)) {
+ dev_err(&dev->pdev->dev, "10 bit addressing"
+ "not supported\n");
+ return -EINVAL;
+ }
+ dev->cli.slave_adr = msgs[i].addr;
+ dev->cli.buffer = msgs[i].buf;
+ dev->cli.count = msgs[i].len;
+ dev->stop = (i < (num_msgs - 1)) ? 0 : 1;
+ dev->result = 0;
+
+ if (msgs[i].flags & I2C_M_RD) {
+ /* it is a read operation */
+ dev->cli.operation = I2C_READ;
+ status = read_i2c(dev);
+ } else {
+ /* write operation */
+ dev->cli.operation = I2C_WRITE;
+ status = write_i2c(dev);
+ }
+ if (status || (dev->result)) {
+ /* get the abort cause */
+ cause = (readl(dev->virtbase + I2C_SR) >> 4) & 0x7;
+ dev_err(&dev->pdev->dev, "error during I2C"
+ "message xfer: %d\n", cause);
+ dev_err(&dev->pdev->dev, "%s\n",
+ cause >= ARRAY_SIZE(abort_causes)
+ ? "unknown reason" : abort_causes[cause]);
+ return status;
+ }
+ mdelay(1);
+ }
+ /* return the no. messages processed */
+ if (status)
+ return status;
+ else
+ return num_msgs;
+}
+
+/**
+ * disable_interrupts() - disable the interrupts
+ * @dev: private data of controller
+ */
+static int disable_interrupts(struct nmk_i2c_dev *dev, u32 irq)
+{
+ irq = IRQ_MASK(irq);
+ writel(readl(dev->virtbase + I2C_IMSCR) & ~(I2C_CLEAR_ALL_INTS & irq),
+ dev->virtbase + I2C_IMSCR);
+ return 0;
+}
+
+/**
+ * i2c_irq_handler() - interrupt routine
+ * @irq: interrupt number
+ * @arg: data passed to the handler
+ *
+ * This is the interrupt handler for the i2c driver. Currently
+ * it handles the major interrupts like Rx & Tx FIFO management
+ * interrupts, master transaction interrupts, arbitration and
+ * bus error interrupts. The rest of the interrupts are treated as
+ * unhandled.
+ */
+static irqreturn_t i2c_irq_handler(int irq, void *arg)
+{
+ struct nmk_i2c_dev *dev = arg;
+ u32 tft, rft;
+ u32 count;
+ u32 misr;
+ u32 src = 0;
+
+ /* load Tx FIFO and Rx FIFO threshold values */
+ tft = readl(dev->virtbase + I2C_TFTR);
+ rft = readl(dev->virtbase + I2C_RFTR);
+
+ /* read interrupt status register */
+ misr = readl(dev->virtbase + I2C_MISR);
+
+ src = __ffs(misr);
+ switch ((1 << src)) {
+
+ /* Transmit FIFO nearly empty interrupt */
+ case I2C_IT_TXFNE:
+ {
+ if (dev->cli.operation == I2C_READ) {
+ /*
+ * in read operation why do we care for writing?
+ * so disable the Transmit FIFO interrupt
+ */
+ disable_interrupts(dev, I2C_IT_TXFNE);
+ } else {
+ for (count = (MAX_I2C_FIFO_THRESHOLD - tft - 2);
+ (count > 0) &&
+ (dev->cli.count != 0);
+ count--) {
+ /* write to the Tx FIFO */
+ writeb(*dev->cli.buffer,
+ dev->virtbase + I2C_TFR);
+ dev->cli.buffer++;
+ dev->cli.count--;
+ dev->cli.xfer_bytes++;
+ }
+ /*
+ * if done, close the transfer by disabling the
+ * corresponding TXFNE interrupt
+ */
+ if (dev->cli.count == 0)
+ disable_interrupts(dev, I2C_IT_TXFNE);
+ }
+ }
+ break;
+
+ /*
+ * Rx FIFO nearly full interrupt.
+ * This is set when the numer of entries in Rx FIFO is
+ * greater or equal than the threshold value programmed
+ * in RFT
+ */
+ case I2C_IT_RXFNF:
+ for (count = rft; count > 0; count--) {
+ /* Read the Rx FIFO */
+ *dev->cli.buffer = readb(dev->virtbase + I2C_RFR);
+ dev->cli.buffer++;
+ }
+ dev->cli.count -= rft;
+ dev->cli.xfer_bytes += rft;
+ break;
+
+ /* Rx FIFO full */
+ case I2C_IT_RXFF:
+ for (count = MAX_I2C_FIFO_THRESHOLD; count > 0; count--) {
+ *dev->cli.buffer = readb(dev->virtbase + I2C_RFR);
+ dev->cli.buffer++;
+ }
+ dev->cli.count -= MAX_I2C_FIFO_THRESHOLD;
+ dev->cli.xfer_bytes += MAX_I2C_FIFO_THRESHOLD;
+ break;
+
+ /* Master Transaction Done with/without stop */
+ case I2C_IT_MTD:
+ case I2C_IT_MTDWS:
+ if (dev->cli.operation == I2C_READ) {
+ while (!readl(dev->virtbase + I2C_RISR) & I2C_IT_RXFE) {
+ if (dev->cli.count == 0)
+ break;
+ *dev->cli.buffer =
+ readb(dev->virtbase + I2C_RFR);
+ dev->cli.buffer++;
+ dev->cli.count--;
+ dev->cli.xfer_bytes++;
+ }
+ }
+
+ i2c_set_bit(dev->virtbase + I2C_ICR, I2C_IT_MTD);
+ i2c_set_bit(dev->virtbase + I2C_ICR, I2C_IT_MTDWS);
+
+ disable_interrupts(dev,
+ (I2C_IT_TXFNE | I2C_IT_TXFE | I2C_IT_TXFF
+ | I2C_IT_TXFOVR | I2C_IT_RXFNF
+ | I2C_IT_RXFF | I2C_IT_RXFE));
+
+ if (dev->cli.count) {
+ dev->result = -1;
+ dev_err(&dev->pdev->dev, "%lu bytes still remain to be"
+ "xfered\n", dev->cli.count);
+ (void) init_hw(dev);
+ }
+ complete(&dev->xfer_complete);
+
+ break;
+
+ /* Master Arbitration lost interrupt */
+ case I2C_IT_MAL:
+ dev->result = -1;
+ (void) init_hw(dev);
+
+ i2c_set_bit(dev->virtbase + I2C_ICR, I2C_IT_MAL);
+ complete(&dev->xfer_complete);
+
+ break;
+
+ /*
+ * Bus Error interrupt.
+ * This happens when an unexpected start/stop condition occurs
+ * during the transaction.
+ */
+ case I2C_IT_BERR:
+ dev->result = -1;
+ /* get the status */
+ if (((readl(dev->virtbase + I2C_SR) >> 2) & 0x3) == I2C_ABORT)
+ (void) init_hw(dev);
+
+ i2c_set_bit(dev->virtbase + I2C_ICR, I2C_IT_BERR);
+ complete(&dev->xfer_complete);
+
+ break;
+
+ /*
+ * Tx FIFO overrun interrupt.
+ * This is set when a write operation in Tx FIFO is performed and
+ * the Tx FIFO is full.
+ */
+ case I2C_IT_TXFOVR:
+ dev->result = -1;
+ (void) init_hw(dev);
+
+ dev_err(&dev->pdev->dev, "Tx Fifo Over run\n");
+ complete(&dev->xfer_complete);
+
+ break;
+
+ /* unhandled interrupts by this driver - TODO*/
+ case I2C_IT_TXFE:
+ case I2C_IT_TXFF:
+ case I2C_IT_RXFE:
+ case I2C_IT_RFSR:
+ case I2C_IT_RFSE:
+ case I2C_IT_WTSR:
+ case I2C_IT_STD:
+ dev_err(&dev->pdev->dev, "unhandled Interrupt\n");
+ break;
+ default:
+ dev_err(&dev->pdev->dev, "spurious Interrupt..\n");
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static unsigned int nmk_i2c_functionality(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C
+ | I2C_FUNC_SMBUS_BYTE_DATA
+ | I2C_FUNC_SMBUS_WORD_DATA
+ | I2C_FUNC_SMBUS_I2C_BLOCK;
+}
+
+static const struct i2c_algorithm nmk_i2c_algo = {
+ .master_xfer = nmk_i2c_xfer,
+ .functionality = nmk_i2c_functionality
+};
+
+static int __devinit nmk_i2c_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct resource *res;
+ struct nmk_i2c_controller *pdata =
+ pdev->dev.platform_data;
+ struct nmk_i2c_dev *dev;
+ struct i2c_adapter *adap;
+
+ dev = kzalloc(sizeof(struct nmk_i2c_dev), GFP_KERNEL);
+ if (!dev) {
+ dev_err(&pdev->dev, "cannot allocate memory\n");
+ ret = -ENOMEM;
+ goto err_no_mem;
+ }
+
+ dev->pdev = pdev;
+ platform_set_drvdata(pdev, dev);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ret = -ENOENT;
+ goto err_no_resource;
+ }
+
+ if (request_mem_region(res->start, resource_size(res),
+ DRIVER_NAME "I/O region") == NULL) {
+ ret = -EBUSY;
+ goto err_no_region;
+ }
+
+ dev->virtbase = ioremap(res->start, resource_size(res));
+ if (!dev->virtbase) {
+ ret = -ENOMEM;
+ goto err_no_ioremap;
+ }
+
+ dev->irq = platform_get_irq(pdev, 0);
+ ret = request_irq(dev->irq, i2c_irq_handler, IRQF_DISABLED,
+ DRIVER_NAME, dev);
+ if (ret) {
+ dev_err(&pdev->dev, "cannot claim the irq %d\n", dev->irq);
+ goto err_irq;
+ }
+
+ dev->clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(dev->clk)) {
+ dev_err(&pdev->dev, "could not get i2c clock\n");
+ ret = PTR_ERR(dev->clk);
+ goto err_no_clk;
+ }
+
+ clk_enable(dev->clk);
+
+ adap = &dev->adap;
+ adap->dev.parent = &pdev->dev;
+ adap->owner = THIS_MODULE;
+ adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+ adap->algo = &nmk_i2c_algo;
+
+ /* fetch the controller id */
+ adap->nr = pdev->id;
+
+ /* fetch the controller configuration from machine */
+ dev->cfg.clk_freq = pdata->clk_freq;
+ dev->cfg.slsu = pdata->slsu;
+ dev->cfg.tft = pdata->tft;
+ dev->cfg.rft = pdata->rft;
+ dev->cfg.sm = pdata->sm;
+
+ i2c_set_adapdata(adap, dev);
+
+ ret = init_hw(dev);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "error in initializing i2c hardware\n");
+ goto err_init_hw;
+ }
+
+ dev_dbg(&pdev->dev, "initialize I2C%d bus on virtual "
+ "base %p\n", pdev->id, dev->virtbase);
+
+ ret = i2c_add_numbered_adapter(adap);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add adapter\n");
+ goto err_add_adap;
+ }
+
+ return 0;
+
+ err_init_hw:
+ clk_disable(dev->clk);
+ err_add_adap:
+ clk_put(dev->clk);
+ err_no_clk:
+ free_irq(dev->irq, dev);
+ err_irq:
+ iounmap(dev->virtbase);
+ err_no_ioremap:
+ release_mem_region(res->start, resource_size(res));
+ err_no_region:
+ platform_set_drvdata(pdev, NULL);
+ err_no_resource:
+ kfree(dev);
+ err_no_mem:
+
+ return ret;
+}
+
+static int __devexit nmk_i2c_remove(struct platform_device *pdev)
+{
+ struct nmk_i2c_dev *dev = platform_get_drvdata(pdev);
+
+ i2c_del_adapter(&dev->adap);
+ flush_i2c_fifo(dev);
+ disable_all_interrupts(dev);
+ clear_all_interrupts(dev);
+ /* disable the controller */
+ i2c_clr_bit(dev->virtbase + I2C_CR, I2C_CR_PE);
+ free_irq(dev->irq, dev);
+ iounmap(dev->virtbase);
+ clk_disable(dev->clk);
+ clk_put(dev->clk);
+ platform_set_drvdata(pdev, NULL);
+ kfree(dev);
+
+ return 0;
+}
+
+static struct platform_driver nmk_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRIVER_NAME,
+ },
+ .probe = nmk_i2c_probe,
+ .remove = __devexit_p(nmk_i2c_remove),
+};
+
+static int __init nmk_i2c_init(void)
+{
+ return platform_driver_register(&nmk_i2c_driver);
+}
+
+static void __exit nmk_i2c_exit(void)
+{
+ platform_driver_unregister(&nmk_i2c_driver);
+}
+
+subsys_initcall(nmk_i2c_init);
+module_exit(nmk_i2c_exit);
+
+MODULE_AUTHOR("Sachin Verma, Srinidhi KASAGAR");
+MODULE_DESCRIPTION("Nomadik/Ux500 I2C driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 0037e31076b..c7c237537f8 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -49,24 +49,24 @@
#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
#define OMAP_I2C_REV_REG 0x00
-#define OMAP_I2C_IE_REG 0x04
-#define OMAP_I2C_STAT_REG 0x08
-#define OMAP_I2C_IV_REG 0x0c
+#define OMAP_I2C_IE_REG 0x01
+#define OMAP_I2C_STAT_REG 0x02
+#define OMAP_I2C_IV_REG 0x03
/* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */
-#define OMAP_I2C_WE_REG 0x0c
-#define OMAP_I2C_SYSS_REG 0x10
-#define OMAP_I2C_BUF_REG 0x14
-#define OMAP_I2C_CNT_REG 0x18
-#define OMAP_I2C_DATA_REG 0x1c
-#define OMAP_I2C_SYSC_REG 0x20
-#define OMAP_I2C_CON_REG 0x24
-#define OMAP_I2C_OA_REG 0x28
-#define OMAP_I2C_SA_REG 0x2c
-#define OMAP_I2C_PSC_REG 0x30
-#define OMAP_I2C_SCLL_REG 0x34
-#define OMAP_I2C_SCLH_REG 0x38
-#define OMAP_I2C_SYSTEST_REG 0x3c
-#define OMAP_I2C_BUFSTAT_REG 0x40
+#define OMAP_I2C_WE_REG 0x03
+#define OMAP_I2C_SYSS_REG 0x04
+#define OMAP_I2C_BUF_REG 0x05
+#define OMAP_I2C_CNT_REG 0x06
+#define OMAP_I2C_DATA_REG 0x07
+#define OMAP_I2C_SYSC_REG 0x08
+#define OMAP_I2C_CON_REG 0x09
+#define OMAP_I2C_OA_REG 0x0a
+#define OMAP_I2C_SA_REG 0x0b
+#define OMAP_I2C_PSC_REG 0x0c
+#define OMAP_I2C_SCLL_REG 0x0d
+#define OMAP_I2C_SCLH_REG 0x0e
+#define OMAP_I2C_SYSTEST_REG 0x0f
+#define OMAP_I2C_BUFSTAT_REG 0x10
/* I2C Interrupt Enable Register (OMAP_I2C_IE): */
#define OMAP_I2C_IE_XDR (1 << 14) /* TX Buffer drain int enable */
@@ -161,6 +161,7 @@ struct omap_i2c_dev {
struct device *dev;
void __iomem *base; /* virtual */
int irq;
+ int reg_shift; /* bit shift for I2C register addresses */
struct clk *iclk; /* Interface clock */
struct clk *fclk; /* Functional clock */
struct completion cmd_complete;
@@ -189,12 +190,12 @@ struct omap_i2c_dev {
static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,
int reg, u16 val)
{
- __raw_writew(val, i2c_dev->base + reg);
+ __raw_writew(val, i2c_dev->base + (reg << i2c_dev->reg_shift));
}
static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
{
- return __raw_readw(i2c_dev->base + reg);
+ return __raw_readw(i2c_dev->base + (reg << i2c_dev->reg_shift));
}
static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev)
@@ -849,7 +850,7 @@ static const struct i2c_algorithm omap_i2c_algo = {
.functionality = omap_i2c_func,
};
-static int __init
+static int __devinit
omap_i2c_probe(struct platform_device *pdev)
{
struct omap_i2c_dev *dev;
@@ -924,6 +925,11 @@ omap_i2c_probe(struct platform_device *pdev)
dev->b_hw = 1; /* Enable hardware fixes */
}
+ if (cpu_is_omap7xx())
+ dev->reg_shift = 1;
+ else
+ dev->reg_shift = 2;
+
/* reset ASAP, clearing any IRQs */
omap_i2c_init(dev);
diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
index 2b0bd0b042d..9532dee6b58 100644
--- a/drivers/i2c/busses/i2c-pnx.c
+++ b/drivers/i2c/busses/i2c-pnx.c
@@ -172,12 +172,6 @@ static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data)
/* We still have something to talk about... */
val = *alg_data->mif.buf++;
- if (alg_data->mif.len == 1) {
- val |= stop_bit;
- if (!alg_data->last)
- val |= start_bit;
- }
-
alg_data->mif.len--;
iowrite32(val, I2C_REG_TX(alg_data));
@@ -251,11 +245,6 @@ static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data)
__func__);
if (alg_data->mif.len == 1) {
- /* Last byte, do not acknowledge next rcv. */
- val |= stop_bit;
- if (!alg_data->last)
- val |= start_bit;
-
/*
* Enable interrupt RFDAIE (data in Rx fifo),
* and disable DRMIE (need data for Tx)
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
new file mode 100644
index 00000000000..eece39a5a30
--- /dev/null
+++ b/drivers/i2c/busses/i2c-xiic.c
@@ -0,0 +1,824 @@
+/*
+ * i2c-xiic.c
+ * Copyright (c) 2002-2007 Xilinx Inc.
+ * Copyright (c) 2009-2010 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * This code was implemented by Mocean Laboratories AB when porting linux
+ * to the automotive development board Russellville. The copyright holder
+ * as seen in the header is Intel corporation.
+ * Mocean Laboratories forked off the GNU/Linux platform work into a
+ * separate company called Pelagicore AB, which commited the code to the
+ * kernel.
+ */
+
+/* Supports:
+ * Xilinx IIC
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/i2c-xiic.h>
+#include <linux/io.h>
+
+#define DRIVER_NAME "xiic-i2c"
+
+enum xilinx_i2c_state {
+ STATE_DONE,
+ STATE_ERROR,
+ STATE_START
+};
+
+/**
+ * struct xiic_i2c - Internal representation of the XIIC I2C bus
+ * @base: Memory base of the HW registers
+ * @wait: Wait queue for callers
+ * @adap: Kernel adapter representation
+ * @tx_msg: Messages from above to be sent
+ * @lock: Mutual exclusion
+ * @tx_pos: Current pos in TX message
+ * @nmsgs: Number of messages in tx_msg
+ * @state: See STATE_
+ * @rx_msg: Current RX message
+ * @rx_pos: Position within current RX message
+ */
+struct xiic_i2c {
+ void __iomem *base;
+ wait_queue_head_t wait;
+ struct i2c_adapter adap;
+ struct i2c_msg *tx_msg;
+ spinlock_t lock;
+ unsigned int tx_pos;
+ unsigned int nmsgs;
+ enum xilinx_i2c_state state;
+ struct i2c_msg *rx_msg;
+ int rx_pos;
+};
+
+
+#define XIIC_MSB_OFFSET 0
+#define XIIC_REG_OFFSET (0x100+XIIC_MSB_OFFSET)
+
+/*
+ * Register offsets in bytes from RegisterBase. Three is added to the
+ * base offset to access LSB (IBM style) of the word
+ */
+#define XIIC_CR_REG_OFFSET (0x00+XIIC_REG_OFFSET) /* Control Register */
+#define XIIC_SR_REG_OFFSET (0x04+XIIC_REG_OFFSET) /* Status Register */
+#define XIIC_DTR_REG_OFFSET (0x08+XIIC_REG_OFFSET) /* Data Tx Register */
+#define XIIC_DRR_REG_OFFSET (0x0C+XIIC_REG_OFFSET) /* Data Rx Register */
+#define XIIC_ADR_REG_OFFSET (0x10+XIIC_REG_OFFSET) /* Address Register */
+#define XIIC_TFO_REG_OFFSET (0x14+XIIC_REG_OFFSET) /* Tx FIFO Occupancy */
+#define XIIC_RFO_REG_OFFSET (0x18+XIIC_REG_OFFSET) /* Rx FIFO Occupancy */
+#define XIIC_TBA_REG_OFFSET (0x1C+XIIC_REG_OFFSET) /* 10 Bit Address reg */
+#define XIIC_RFD_REG_OFFSET (0x20+XIIC_REG_OFFSET) /* Rx FIFO Depth reg */
+#define XIIC_GPO_REG_OFFSET (0x24+XIIC_REG_OFFSET) /* Output Register */
+
+/* Control Register masks */
+#define XIIC_CR_ENABLE_DEVICE_MASK 0x01 /* Device enable = 1 */
+#define XIIC_CR_TX_FIFO_RESET_MASK 0x02 /* Transmit FIFO reset=1 */
+#define XIIC_CR_MSMS_MASK 0x04 /* Master starts Txing=1 */
+#define XIIC_CR_DIR_IS_TX_MASK 0x08 /* Dir of tx. Txing=1 */
+#define XIIC_CR_NO_ACK_MASK 0x10 /* Tx Ack. NO ack = 1 */
+#define XIIC_CR_REPEATED_START_MASK 0x20 /* Repeated start = 1 */
+#define XIIC_CR_GENERAL_CALL_MASK 0x40 /* Gen Call enabled = 1 */
+
+/* Status Register masks */
+#define XIIC_SR_GEN_CALL_MASK 0x01 /* 1=a mstr issued a GC */
+#define XIIC_SR_ADDR_AS_SLAVE_MASK 0x02 /* 1=when addr as slave */
+#define XIIC_SR_BUS_BUSY_MASK 0x04 /* 1 = bus is busy */
+#define XIIC_SR_MSTR_RDING_SLAVE_MASK 0x08 /* 1=Dir: mstr <-- slave */
+#define XIIC_SR_TX_FIFO_FULL_MASK 0x10 /* 1 = Tx FIFO full */
+#define XIIC_SR_RX_FIFO_FULL_MASK 0x20 /* 1 = Rx FIFO full */
+#define XIIC_SR_RX_FIFO_EMPTY_MASK 0x40 /* 1 = Rx FIFO empty */
+#define XIIC_SR_TX_FIFO_EMPTY_MASK 0x80 /* 1 = Tx FIFO empty */
+
+/* Interrupt Status Register masks Interrupt occurs when... */
+#define XIIC_INTR_ARB_LOST_MASK 0x01 /* 1 = arbitration lost */
+#define XIIC_INTR_TX_ERROR_MASK 0x02 /* 1=Tx error/msg complete */
+#define XIIC_INTR_TX_EMPTY_MASK 0x04 /* 1 = Tx FIFO/reg empty */
+#define XIIC_INTR_RX_FULL_MASK 0x08 /* 1=Rx FIFO/reg=OCY level */
+#define XIIC_INTR_BNB_MASK 0x10 /* 1 = Bus not busy */
+#define XIIC_INTR_AAS_MASK 0x20 /* 1 = when addr as slave */
+#define XIIC_INTR_NAAS_MASK 0x40 /* 1 = not addr as slave */
+#define XIIC_INTR_TX_HALF_MASK 0x80 /* 1 = TX FIFO half empty */
+
+/* The following constants specify the depth of the FIFOs */
+#define IIC_RX_FIFO_DEPTH 16 /* Rx fifo capacity */
+#define IIC_TX_FIFO_DEPTH 16 /* Tx fifo capacity */
+
+/* The following constants specify groups of interrupts that are typically
+ * enabled or disables at the same time
+ */
+#define XIIC_TX_INTERRUPTS \
+(XIIC_INTR_TX_ERROR_MASK | XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK)
+
+#define XIIC_TX_RX_INTERRUPTS (XIIC_INTR_RX_FULL_MASK | XIIC_TX_INTERRUPTS)
+
+/* The following constants are used with the following macros to specify the
+ * operation, a read or write operation.
+ */
+#define XIIC_READ_OPERATION 1
+#define XIIC_WRITE_OPERATION 0
+
+/*
+ * Tx Fifo upper bit masks.
+ */
+#define XIIC_TX_DYN_START_MASK 0x0100 /* 1 = Set dynamic start */
+#define XIIC_TX_DYN_STOP_MASK 0x0200 /* 1 = Set dynamic stop */
+
+/*
+ * The following constants define the register offsets for the Interrupt
+ * registers. There are some holes in the memory map for reserved addresses
+ * to allow other registers to be added and still match the memory map of the
+ * interrupt controller registers
+ */
+#define XIIC_DGIER_OFFSET 0x1C /* Device Global Interrupt Enable Register */
+#define XIIC_IISR_OFFSET 0x20 /* Interrupt Status Register */
+#define XIIC_IIER_OFFSET 0x28 /* Interrupt Enable Register */
+#define XIIC_RESETR_OFFSET 0x40 /* Reset Register */
+
+#define XIIC_RESET_MASK 0xAUL
+
+/*
+ * The following constant is used for the device global interrupt enable
+ * register, to enable all interrupts for the device, this is the only bit
+ * in the register
+ */
+#define XIIC_GINTR_ENABLE_MASK 0x80000000UL
+
+#define xiic_tx_space(i2c) ((i2c)->tx_msg->len - (i2c)->tx_pos)
+#define xiic_rx_space(i2c) ((i2c)->rx_msg->len - (i2c)->rx_pos)
+
+static void xiic_start_xfer(struct xiic_i2c *i2c);
+static void __xiic_start_xfer(struct xiic_i2c *i2c);
+
+static inline void xiic_setreg8(struct xiic_i2c *i2c, int reg, u8 value)
+{
+ iowrite8(value, i2c->base + reg);
+}
+
+static inline u8 xiic_getreg8(struct xiic_i2c *i2c, int reg)
+{
+ return ioread8(i2c->base + reg);
+}
+
+static inline void xiic_setreg16(struct xiic_i2c *i2c, int reg, u16 value)
+{
+ iowrite16(value, i2c->base + reg);
+}
+
+static inline void xiic_setreg32(struct xiic_i2c *i2c, int reg, int value)
+{
+ iowrite32(value, i2c->base + reg);
+}
+
+static inline int xiic_getreg32(struct xiic_i2c *i2c, int reg)
+{
+ return ioread32(i2c->base + reg);
+}
+
+static inline void xiic_irq_dis(struct xiic_i2c *i2c, u32 mask)
+{
+ u32 ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET);
+ xiic_setreg32(i2c, XIIC_IIER_OFFSET, ier & ~mask);
+}
+
+static inline void xiic_irq_en(struct xiic_i2c *i2c, u32 mask)
+{
+ u32 ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET);
+ xiic_setreg32(i2c, XIIC_IIER_OFFSET, ier | mask);
+}
+
+static inline void xiic_irq_clr(struct xiic_i2c *i2c, u32 mask)
+{
+ u32 isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET);
+ xiic_setreg32(i2c, XIIC_IISR_OFFSET, isr & mask);
+}
+
+static inline void xiic_irq_clr_en(struct xiic_i2c *i2c, u32 mask)
+{
+ xiic_irq_clr(i2c, mask);
+ xiic_irq_en(i2c, mask);
+}
+
+static void xiic_clear_rx_fifo(struct xiic_i2c *i2c)
+{
+ u8 sr;
+ for (sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET);
+ !(sr & XIIC_SR_RX_FIFO_EMPTY_MASK);
+ sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET))
+ xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET);
+}
+
+static void xiic_reinit(struct xiic_i2c *i2c)
+{
+ xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK);
+
+ /* Set receive Fifo depth to maximum (zero based). */
+ xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, IIC_RX_FIFO_DEPTH - 1);
+
+ /* Reset Tx Fifo. */
+ xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_TX_FIFO_RESET_MASK);
+
+ /* Enable IIC Device, remove Tx Fifo reset & disable general call. */
+ xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_ENABLE_DEVICE_MASK);
+
+ /* make sure RX fifo is empty */
+ xiic_clear_rx_fifo(i2c);
+
+ /* Enable interrupts */
+ xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK);
+
+ xiic_irq_clr_en(i2c, XIIC_INTR_AAS_MASK | XIIC_INTR_ARB_LOST_MASK);
+}
+
+static void xiic_deinit(struct xiic_i2c *i2c)
+{
+ u8 cr;
+
+ xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK);
+
+ /* Disable IIC Device. */
+ cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET);
+ xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr & ~XIIC_CR_ENABLE_DEVICE_MASK);
+}
+
+static void xiic_read_rx(struct xiic_i2c *i2c)
+{
+ u8 bytes_in_fifo;
+ int i;
+
+ bytes_in_fifo = xiic_getreg8(i2c, XIIC_RFO_REG_OFFSET) + 1;
+
+ dev_dbg(i2c->adap.dev.parent, "%s entry, bytes in fifo: %d, msg: %d"
+ ", SR: 0x%x, CR: 0x%x\n",
+ __func__, bytes_in_fifo, xiic_rx_space(i2c),
+ xiic_getreg8(i2c, XIIC_SR_REG_OFFSET),
+ xiic_getreg8(i2c, XIIC_CR_REG_OFFSET));
+
+ if (bytes_in_fifo > xiic_rx_space(i2c))
+ bytes_in_fifo = xiic_rx_space(i2c);
+
+ for (i = 0; i < bytes_in_fifo; i++)
+ i2c->rx_msg->buf[i2c->rx_pos++] =
+ xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET);
+
+ xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET,
+ (xiic_rx_space(i2c) > IIC_RX_FIFO_DEPTH) ?
+ IIC_RX_FIFO_DEPTH - 1 : xiic_rx_space(i2c) - 1);
+}
+
+static int xiic_tx_fifo_space(struct xiic_i2c *i2c)
+{
+ /* return the actual space left in the FIFO */
+ return IIC_TX_FIFO_DEPTH - xiic_getreg8(i2c, XIIC_TFO_REG_OFFSET) - 1;
+}
+
+static void xiic_fill_tx_fifo(struct xiic_i2c *i2c)
+{
+ u8 fifo_space = xiic_tx_fifo_space(i2c);
+ int len = xiic_tx_space(i2c);
+
+ len = (len > fifo_space) ? fifo_space : len;
+
+ dev_dbg(i2c->adap.dev.parent, "%s entry, len: %d, fifo space: %d\n",
+ __func__, len, fifo_space);
+
+ while (len--) {
+ u16 data = i2c->tx_msg->buf[i2c->tx_pos++];
+ if ((xiic_tx_space(i2c) == 0) && (i2c->nmsgs == 1)) {
+ /* last message in transfer -> STOP */
+ data |= XIIC_TX_DYN_STOP_MASK;
+ dev_dbg(i2c->adap.dev.parent, "%s TX STOP\n", __func__);
+
+ xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data);
+ } else
+ xiic_setreg8(i2c, XIIC_DTR_REG_OFFSET, data);
+ }
+}
+
+static void xiic_wakeup(struct xiic_i2c *i2c, int code)
+{
+ i2c->tx_msg = NULL;
+ i2c->rx_msg = NULL;
+ i2c->nmsgs = 0;
+ i2c->state = code;
+ wake_up(&i2c->wait);
+}
+
+static void xiic_process(struct xiic_i2c *i2c)
+{
+ u32 pend, isr, ier;
+ u32 clr = 0;
+
+ /* Get the interrupt Status from the IPIF. There is no clearing of
+ * interrupts in the IPIF. Interrupts must be cleared at the source.
+ * To find which interrupts are pending; AND interrupts pending with
+ * interrupts masked.
+ */
+ isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET);
+ ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET);
+ pend = isr & ier;
+
+ dev_dbg(i2c->adap.dev.parent, "%s entry, IER: 0x%x, ISR: 0x%x, "
+ "pend: 0x%x, SR: 0x%x, msg: %p, nmsgs: %d\n",
+ __func__, ier, isr, pend, xiic_getreg8(i2c, XIIC_SR_REG_OFFSET),
+ i2c->tx_msg, i2c->nmsgs);
+
+ /* Do not processes a devices interrupts if the device has no
+ * interrupts pending
+ */
+ if (!pend)
+ return;
+
+ /* Service requesting interrupt */
+ if ((pend & XIIC_INTR_ARB_LOST_MASK) ||
+ ((pend & XIIC_INTR_TX_ERROR_MASK) &&
+ !(pend & XIIC_INTR_RX_FULL_MASK))) {
+ /* bus arbritration lost, or...
+ * Transmit error _OR_ RX completed
+ * if this happens when RX_FULL is not set
+ * this is probably a TX error
+ */
+
+ dev_dbg(i2c->adap.dev.parent, "%s error\n", __func__);
+
+ /* dynamic mode seem to suffer from problems if we just flushes
+ * fifos and the next message is a TX with len 0 (only addr)
+ * reset the IP instead of just flush fifos
+ */
+ xiic_reinit(i2c);
+
+ if (i2c->tx_msg)
+ xiic_wakeup(i2c, STATE_ERROR);
+
+ } else if (pend & XIIC_INTR_RX_FULL_MASK) {
+ /* Receive register/FIFO is full */
+
+ clr = XIIC_INTR_RX_FULL_MASK;
+ if (!i2c->rx_msg) {
+ dev_dbg(i2c->adap.dev.parent,
+ "%s unexpexted RX IRQ\n", __func__);
+ xiic_clear_rx_fifo(i2c);
+ goto out;
+ }
+
+ xiic_read_rx(i2c);
+ if (xiic_rx_space(i2c) == 0) {
+ /* this is the last part of the message */
+ i2c->rx_msg = NULL;
+
+ /* also clear TX error if there (RX complete) */
+ clr |= (isr & XIIC_INTR_TX_ERROR_MASK);
+
+ dev_dbg(i2c->adap.dev.parent,
+ "%s end of message, nmsgs: %d\n",
+ __func__, i2c->nmsgs);
+
+ /* send next message if this wasn't the last,
+ * otherwise the transfer will be finialise when
+ * receiving the bus not busy interrupt
+ */
+ if (i2c->nmsgs > 1) {
+ i2c->nmsgs--;
+ i2c->tx_msg++;
+ dev_dbg(i2c->adap.dev.parent,
+ "%s will start next...\n", __func__);
+
+ __xiic_start_xfer(i2c);
+ }
+ }
+ } else if (pend & XIIC_INTR_BNB_MASK) {
+ /* IIC bus has transitioned to not busy */
+ clr = XIIC_INTR_BNB_MASK;
+
+ /* The bus is not busy, disable BusNotBusy interrupt */
+ xiic_irq_dis(i2c, XIIC_INTR_BNB_MASK);
+
+ if (!i2c->tx_msg)
+ goto out;
+
+ if ((i2c->nmsgs == 1) && !i2c->rx_msg &&
+ xiic_tx_space(i2c) == 0)
+ xiic_wakeup(i2c, STATE_DONE);
+ else
+ xiic_wakeup(i2c, STATE_ERROR);
+
+ } else if (pend & (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK)) {
+ /* Transmit register/FIFO is empty or ½ empty */
+
+ clr = pend &
+ (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK);
+
+ if (!i2c->tx_msg) {
+ dev_dbg(i2c->adap.dev.parent,
+ "%s unexpexted TX IRQ\n", __func__);
+ goto out;
+ }
+
+ xiic_fill_tx_fifo(i2c);
+
+ /* current message sent and there is space in the fifo */
+ if (!xiic_tx_space(i2c) && xiic_tx_fifo_space(i2c) >= 2) {
+ dev_dbg(i2c->adap.dev.parent,
+ "%s end of message sent, nmsgs: %d\n",
+ __func__, i2c->nmsgs);
+ if (i2c->nmsgs > 1) {
+ i2c->nmsgs--;
+ i2c->tx_msg++;
+ __xiic_start_xfer(i2c);
+ } else {
+ xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK);
+
+ dev_dbg(i2c->adap.dev.parent,
+ "%s Got TX IRQ but no more to do...\n",
+ __func__);
+ }
+ } else if (!xiic_tx_space(i2c) && (i2c->nmsgs == 1))
+ /* current frame is sent and is last,
+ * make sure to disable tx half
+ */
+ xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK);
+ } else {
+ /* got IRQ which is not acked */
+ dev_err(i2c->adap.dev.parent, "%s Got unexpected IRQ\n",
+ __func__);
+ clr = pend;
+ }
+out:
+ dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr);
+
+ xiic_setreg32(i2c, XIIC_IISR_OFFSET, clr);
+}
+
+static int xiic_bus_busy(struct xiic_i2c *i2c)
+{
+ u8 sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET);
+
+ return (sr & XIIC_SR_BUS_BUSY_MASK) ? -EBUSY : 0;
+}
+
+static int xiic_busy(struct xiic_i2c *i2c)
+{
+ int tries = 3;
+ int err;
+
+ if (i2c->tx_msg)
+ return -EBUSY;
+
+ /* for instance if previous transfer was terminated due to TX error
+ * it might be that the bus is on it's way to become available
+ * give it at most 3 ms to wake
+ */
+ err = xiic_bus_busy(i2c);
+ while (err && tries--) {
+ mdelay(1);
+ err = xiic_bus_busy(i2c);
+ }
+
+ return err;
+}
+
+static void xiic_start_recv(struct xiic_i2c *i2c)
+{
+ u8 rx_watermark;
+ struct i2c_msg *msg = i2c->rx_msg = i2c->tx_msg;
+
+ /* Clear and enable Rx full interrupt. */
+ xiic_irq_clr_en(i2c, XIIC_INTR_RX_FULL_MASK | XIIC_INTR_TX_ERROR_MASK);
+
+ /* we want to get all but last byte, because the TX_ERROR IRQ is used
+ * to inidicate error ACK on the address, and negative ack on the last
+ * received byte, so to not mix them receive all but last.
+ * In the case where there is only one byte to receive
+ * we can check if ERROR and RX full is set at the same time
+ */
+ rx_watermark = msg->len;
+ if (rx_watermark > IIC_RX_FIFO_DEPTH)
+ rx_watermark = IIC_RX_FIFO_DEPTH;
+ xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, rx_watermark - 1);
+
+ if (!(msg->flags & I2C_M_NOSTART))
+ /* write the address */
+ xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET,
+ (msg->addr << 1) | XIIC_READ_OPERATION |
+ XIIC_TX_DYN_START_MASK);
+
+ xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK);
+
+ xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET,
+ msg->len | ((i2c->nmsgs == 1) ? XIIC_TX_DYN_STOP_MASK : 0));
+ if (i2c->nmsgs == 1)
+ /* very last, enable bus not busy as well */
+ xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK);
+
+ /* the message is tx:ed */
+ i2c->tx_pos = msg->len;
+}
+
+static void xiic_start_send(struct xiic_i2c *i2c)
+{
+ struct i2c_msg *msg = i2c->tx_msg;
+
+ xiic_irq_clr(i2c, XIIC_INTR_TX_ERROR_MASK);
+
+ dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, len: %d, "
+ "ISR: 0x%x, CR: 0x%x\n",
+ __func__, msg, msg->len, xiic_getreg32(i2c, XIIC_IISR_OFFSET),
+ xiic_getreg8(i2c, XIIC_CR_REG_OFFSET));
+
+ if (!(msg->flags & I2C_M_NOSTART)) {
+ /* write the address */
+ u16 data = ((msg->addr << 1) & 0xfe) | XIIC_WRITE_OPERATION |
+ XIIC_TX_DYN_START_MASK;
+ if ((i2c->nmsgs == 1) && msg->len == 0)
+ /* no data and last message -> add STOP */
+ data |= XIIC_TX_DYN_STOP_MASK;
+
+ xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data);
+ }
+
+ xiic_fill_tx_fifo(i2c);
+
+ /* Clear any pending Tx empty, Tx Error and then enable them. */
+ xiic_irq_clr_en(i2c, XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_ERROR_MASK |
+ XIIC_INTR_BNB_MASK);
+}
+
+static irqreturn_t xiic_isr(int irq, void *dev_id)
+{
+ struct xiic_i2c *i2c = dev_id;
+
+ spin_lock(&i2c->lock);
+ /* disable interrupts globally */
+ xiic_setreg32(i2c, XIIC_DGIER_OFFSET, 0);
+
+ dev_dbg(i2c->adap.dev.parent, "%s entry\n", __func__);
+
+ xiic_process(i2c);
+
+ xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK);
+ spin_unlock(&i2c->lock);
+
+ return IRQ_HANDLED;
+}
+
+static void __xiic_start_xfer(struct xiic_i2c *i2c)
+{
+ int first = 1;
+ int fifo_space = xiic_tx_fifo_space(i2c);
+ dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, fifos space: %d\n",
+ __func__, i2c->tx_msg, fifo_space);
+
+ if (!i2c->tx_msg)
+ return;
+
+ i2c->rx_pos = 0;
+ i2c->tx_pos = 0;
+ i2c->state = STATE_START;
+ while ((fifo_space >= 2) && (first || (i2c->nmsgs > 1))) {
+ if (!first) {
+ i2c->nmsgs--;
+ i2c->tx_msg++;
+ i2c->tx_pos = 0;
+ } else
+ first = 0;
+
+ if (i2c->tx_msg->flags & I2C_M_RD) {
+ /* we dont date putting several reads in the FIFO */
+ xiic_start_recv(i2c);
+ return;
+ } else {
+ xiic_start_send(i2c);
+ if (xiic_tx_space(i2c) != 0) {
+ /* the message could not be completely sent */
+ break;
+ }
+ }
+
+ fifo_space = xiic_tx_fifo_space(i2c);
+ }
+
+ /* there are more messages or the current one could not be completely
+ * put into the FIFO, also enable the half empty interrupt
+ */
+ if (i2c->nmsgs > 1 || xiic_tx_space(i2c))
+ xiic_irq_clr_en(i2c, XIIC_INTR_TX_HALF_MASK);
+
+}
+
+static void xiic_start_xfer(struct xiic_i2c *i2c)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&i2c->lock, flags);
+ xiic_reinit(i2c);
+ /* disable interrupts globally */
+ xiic_setreg32(i2c, XIIC_DGIER_OFFSET, 0);
+ spin_unlock_irqrestore(&i2c->lock, flags);
+
+ __xiic_start_xfer(i2c);
+ xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK);
+}
+
+static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+ struct xiic_i2c *i2c = i2c_get_adapdata(adap);
+ int err;
+
+ dev_dbg(adap->dev.parent, "%s entry SR: 0x%x\n", __func__,
+ xiic_getreg8(i2c, XIIC_SR_REG_OFFSET));
+
+ err = xiic_busy(i2c);
+ if (err)
+ return err;
+
+ i2c->tx_msg = msgs;
+ i2c->nmsgs = num;
+
+ xiic_start_xfer(i2c);
+
+ if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) ||
+ (i2c->state == STATE_DONE), HZ))
+ return (i2c->state == STATE_DONE) ? num : -EIO;
+ else {
+ i2c->tx_msg = NULL;
+ i2c->rx_msg = NULL;
+ i2c->nmsgs = 0;
+ return -ETIMEDOUT;
+ }
+}
+
+static u32 xiic_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm xiic_algorithm = {
+ .master_xfer = xiic_xfer,
+ .functionality = xiic_func,
+};
+
+static struct i2c_adapter xiic_adapter = {
+ .owner = THIS_MODULE,
+ .name = DRIVER_NAME,
+ .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
+ .algo = &xiic_algorithm,
+};
+
+
+static int __devinit xiic_i2c_probe(struct platform_device *pdev)
+{
+ struct xiic_i2c *i2c;
+ struct xiic_i2c_platform_data *pdata;
+ struct resource *res;
+ int ret, irq;
+ u8 i;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ goto resource_missing;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ goto resource_missing;
+
+ pdata = (struct xiic_i2c_platform_data *) pdev->dev.platform_data;
+ if (!pdata)
+ return -EINVAL;
+
+ i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
+ if (!i2c)
+ return -ENOMEM;
+
+ if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
+ dev_err(&pdev->dev, "Memory region busy\n");
+ ret = -EBUSY;
+ goto request_mem_failed;
+ }
+
+ i2c->base = ioremap(res->start, resource_size(res));
+ if (!i2c->base) {
+ dev_err(&pdev->dev, "Unable to map registers\n");
+ ret = -EIO;
+ goto map_failed;
+ }
+
+ /* hook up driver to tree */
+ platform_set_drvdata(pdev, i2c);
+ i2c->adap = xiic_adapter;
+ i2c_set_adapdata(&i2c->adap, i2c);
+ i2c->adap.dev.parent = &pdev->dev;
+
+ xiic_reinit(i2c);
+
+ spin_lock_init(&i2c->lock);
+ init_waitqueue_head(&i2c->wait);
+ ret = request_irq(irq, xiic_isr, 0, pdev->name, i2c);
+ if (ret) {
+ dev_err(&pdev->dev, "Cannot claim IRQ\n");
+ goto request_irq_failed;
+ }
+
+ /* add i2c adapter to i2c tree */
+ ret = i2c_add_adapter(&i2c->adap);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to add adapter\n");
+ goto add_adapter_failed;
+ }
+
+ /* add in known devices to the bus */
+ for (i = 0; i < pdata->num_devices; i++)
+ i2c_new_device(&i2c->adap, pdata->devices + i);
+
+ return 0;
+
+add_adapter_failed:
+ free_irq(irq, i2c);
+request_irq_failed:
+ xiic_deinit(i2c);
+ iounmap(i2c->base);
+map_failed:
+ release_mem_region(res->start, resource_size(res));
+request_mem_failed:
+ kfree(i2c);
+
+ return ret;
+resource_missing:
+ dev_err(&pdev->dev, "IRQ or Memory resource is missing\n");
+ return -ENOENT;
+}
+
+static int __devexit xiic_i2c_remove(struct platform_device* pdev)
+{
+ struct xiic_i2c *i2c = platform_get_drvdata(pdev);
+ struct resource *res;
+
+ /* remove adapter & data */
+ i2c_del_adapter(&i2c->adap);
+
+ xiic_deinit(i2c);
+
+ platform_set_drvdata(pdev, NULL);
+
+ free_irq(platform_get_irq(pdev, 0), i2c);
+
+ iounmap(i2c->base);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res)
+ release_mem_region(res->start, resource_size(res));
+
+ kfree(i2c);
+
+ return 0;
+}
+
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:"DRIVER_NAME);
+
+static struct platform_driver xiic_i2c_driver = {
+ .probe = xiic_i2c_probe,
+ .remove = __devexit_p(xiic_i2c_remove),
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = DRIVER_NAME,
+ },
+};
+
+static int __init xiic_i2c_init(void)
+{
+ return platform_driver_register(&xiic_i2c_driver);
+}
+
+static void __exit xiic_i2c_exit(void)
+{
+ platform_driver_unregister(&xiic_i2c_driver);
+}
+
+module_init(xiic_i2c_init);
+module_exit(xiic_i2c_exit);
+
+MODULE_AUTHOR("info@mocean-labs.com");
+MODULE_DESCRIPTION("Xilinx I2C bus driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index 5122b5a8aa2..18350213479 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -19,7 +19,6 @@
#include <linux/moduleparam.h>
#include <linux/mutex.h>
#include <linux/freezer.h>
-#include <linux/semaphore.h>
#include <asm/atomic.h>
#include "csr.h"
@@ -1397,9 +1396,9 @@ static int update_pdrv(struct device *dev, void *data)
pdrv = container_of(drv, struct hpsb_protocol_driver,
driver);
if (pdrv->update) {
- down(&ud->device.sem);
+ device_lock(&ud->device);
error = pdrv->update(ud);
- up(&ud->device.sem);
+ device_unlock(&ud->device);
}
if (error)
device_release_driver(&ud->device);
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 5130fc55b8e..764787ebe8d 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -3597,7 +3597,7 @@ static ssize_t cm_show_counter(struct kobject *obj, struct attribute *attr,
atomic_long_read(&group->counter[cm_attr->index]));
}
-static struct sysfs_ops cm_counter_ops = {
+static const struct sysfs_ops cm_counter_ops = {
.show = cm_show_counter
};
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 7522008fda8..58463da814d 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -1193,10 +1193,7 @@ static int method_in_use(struct ib_mad_mgmt_method_table **method,
{
int i;
- for (i = find_first_bit(mad_reg_req->method_mask, IB_MGMT_MAX_METHODS);
- i < IB_MGMT_MAX_METHODS;
- i = find_next_bit(mad_reg_req->method_mask, IB_MGMT_MAX_METHODS,
- 1+i)) {
+ for_each_set_bit(i, mad_reg_req->method_mask, IB_MGMT_MAX_METHODS) {
if ((*method)->agent[i]) {
printk(KERN_ERR PFX "Method %d already in use\n", i);
return -EINVAL;
@@ -1330,13 +1327,9 @@ static int add_nonoui_reg_req(struct ib_mad_reg_req *mad_reg_req,
goto error3;
/* Finally, add in methods being registered */
- for (i = find_first_bit(mad_reg_req->method_mask,
- IB_MGMT_MAX_METHODS);
- i < IB_MGMT_MAX_METHODS;
- i = find_next_bit(mad_reg_req->method_mask, IB_MGMT_MAX_METHODS,
- 1+i)) {
+ for_each_set_bit(i, mad_reg_req->method_mask, IB_MGMT_MAX_METHODS)
(*method)->agent[i] = agent_priv;
- }
+
return 0;
error3:
@@ -1429,13 +1422,9 @@ check_in_use:
goto error4;
/* Finally, add in methods being registered */
- for (i = find_first_bit(mad_reg_req->method_mask,
- IB_MGMT_MAX_METHODS);
- i < IB_MGMT_MAX_METHODS;
- i = find_next_bit(mad_reg_req->method_mask, IB_MGMT_MAX_METHODS,
- 1+i)) {
+ for_each_set_bit(i, mad_reg_req->method_mask, IB_MGMT_MAX_METHODS)
(*method)->agent[i] = agent_priv;
- }
+
return 0;
error4:
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 158a214da2f..1558bb7fc74 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -79,7 +79,7 @@ static ssize_t port_attr_show(struct kobject *kobj,
return port_attr->show(p, port_attr, buf);
}
-static struct sysfs_ops port_sysfs_ops = {
+static const struct sysfs_ops port_sysfs_ops = {
.show = port_attr_show
};
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index 1b09b735c5a..017d6e24448 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -1336,11 +1336,8 @@ static void ib_ucm_remove_one(struct ib_device *device)
device_unregister(&ucm_dev->dev);
}
-static ssize_t show_abi_version(struct class *class, char *buf)
-{
- return sprintf(buf, "%d\n", IB_USER_CM_ABI_VERSION);
-}
-static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
+static CLASS_ATTR_STRING(abi_version, S_IRUGO,
+ __stringify(IB_USER_CM_ABI_VERSION));
static int __init ib_ucm_init(void)
{
@@ -1353,7 +1350,7 @@ static int __init ib_ucm_init(void)
goto error1;
}
- ret = class_create_file(&cm_class, &class_attr_abi_version);
+ ret = class_create_file(&cm_class, &class_attr_abi_version.attr);
if (ret) {
printk(KERN_ERR "ucm: couldn't create abi_version attribute\n");
goto error2;
@@ -1367,7 +1364,7 @@ static int __init ib_ucm_init(void)
return 0;
error3:
- class_remove_file(&cm_class, &class_attr_abi_version);
+ class_remove_file(&cm_class, &class_attr_abi_version.attr);
error2:
unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES);
error1:
@@ -1377,7 +1374,7 @@ error1:
static void __exit ib_ucm_cleanup(void)
{
ib_unregister_client(&ucm_client);
- class_remove_file(&cm_class, &class_attr_abi_version);
+ class_remove_file(&cm_class, &class_attr_abi_version.attr);
unregister_chrdev_region(IB_UCM_BASE_DEV, IB_UCM_MAX_DEVICES);
if (overflow_maj)
unregister_chrdev_region(overflow_maj, IB_UCM_MAX_DEVICES);
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 02d360cfc2f..04b585e86cb 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -965,11 +965,8 @@ static ssize_t show_port(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
-static ssize_t show_abi_version(struct class *class, char *buf)
-{
- return sprintf(buf, "%d\n", IB_USER_MAD_ABI_VERSION);
-}
-static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
+static CLASS_ATTR_STRING(abi_version, S_IRUGO,
+ __stringify(IB_USER_MAD_ABI_VERSION));
static dev_t overflow_maj;
static DECLARE_BITMAP(overflow_map, IB_UMAD_MAX_PORTS);
@@ -1194,7 +1191,7 @@ static int __init ib_umad_init(void)
goto out_chrdev;
}
- ret = class_create_file(umad_class, &class_attr_abi_version);
+ ret = class_create_file(umad_class, &class_attr_abi_version.attr);
if (ret) {
printk(KERN_ERR "user_mad: couldn't create abi_version attribute\n");
goto out_class;
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 4fa2e651644..d805cf365c8 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -691,11 +691,8 @@ static ssize_t show_dev_abi_version(struct device *device,
}
static DEVICE_ATTR(abi_version, S_IRUGO, show_dev_abi_version, NULL);
-static ssize_t show_abi_version(struct class *class, char *buf)
-{
- return sprintf(buf, "%d\n", IB_USER_VERBS_ABI_VERSION);
-}
-static CLASS_ATTR(abi_version, S_IRUGO, show_abi_version, NULL);
+static CLASS_ATTR_STRING(abi_version, S_IRUGO,
+ __stringify(IB_USER_VERBS_ABI_VERSION));
static dev_t overflow_maj;
static DECLARE_BITMAP(overflow_map, IB_UVERBS_MAX_DEVICES);
@@ -841,7 +838,7 @@ static int __init ib_uverbs_init(void)
goto out_chrdev;
}
- ret = class_create_file(uverbs_class, &class_attr_abi_version);
+ ret = class_create_file(uverbs_class, &class_attr_abi_version.attr);
if (ret) {
printk(KERN_ERR "user_verbs: couldn't create abi_version attribute\n");
goto out_class;
diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c
new file mode 100644
index 00000000000..69a48e8701b
--- /dev/null
+++ b/drivers/input/misc/88pm860x_onkey.c
@@ -0,0 +1,155 @@
+/*
+ * 88pm860x_onkey.c - Marvell 88PM860x ONKEY driver
+ *
+ * Copyright (C) 2009-2010 Marvell International Ltd.
+ * Haojian Zhuang <haojian.zhuang@marvell.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/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/88pm860x.h>
+
+#define PM8607_WAKEUP 0x0b
+
+#define LONG_ONKEY_EN (1 << 1)
+#define ONKEY_STATUS (1 << 0)
+
+struct pm860x_onkey_info {
+ struct input_dev *idev;
+ struct pm860x_chip *chip;
+ struct i2c_client *i2c;
+ struct device *dev;
+ int irq;
+};
+
+/* 88PM860x gives us an interrupt when ONKEY is held */
+static irqreturn_t pm860x_onkey_handler(int irq, void *data)
+{
+ struct pm860x_onkey_info *info = data;
+ int ret;
+
+ ret = pm860x_reg_read(info->i2c, PM8607_STATUS_2);
+ ret &= ONKEY_STATUS;
+ input_report_key(info->idev, KEY_POWER, ret);
+ input_sync(info->idev);
+
+ /* Enable 8-second long onkey detection */
+ pm860x_set_bits(info->i2c, PM8607_WAKEUP, 3, LONG_ONKEY_EN);
+ return IRQ_HANDLED;
+}
+
+static int __devinit pm860x_onkey_probe(struct platform_device *pdev)
+{
+ struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ struct pm860x_onkey_info *info;
+ int irq, ret;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "No IRQ resource!\n");
+ return -EINVAL;
+ }
+
+ info = kzalloc(sizeof(struct pm860x_onkey_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+ info->chip = chip;
+ info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
+ info->dev = &pdev->dev;
+ info->irq = irq + chip->irq_base;
+
+ info->idev = input_allocate_device();
+ if (!info->idev) {
+ dev_err(chip->dev, "Failed to allocate input dev\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ info->idev->name = "88pm860x_on";
+ info->idev->phys = "88pm860x_on/input0";
+ info->idev->id.bustype = BUS_I2C;
+ info->idev->dev.parent = &pdev->dev;
+ info->irq = irq;
+ info->idev->evbit[0] = BIT_MASK(EV_KEY);
+ info->idev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER);
+
+ ret = input_register_device(info->idev);
+ if (ret) {
+ dev_err(chip->dev, "Can't register input device: %d\n", ret);
+ goto out_reg;
+ }
+
+ ret = request_threaded_irq(info->irq, NULL, pm860x_onkey_handler,
+ IRQF_ONESHOT, "onkey", info);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
+ info->irq, ret);
+ goto out_irq;
+ }
+
+ platform_set_drvdata(pdev, info);
+ return 0;
+
+out_irq:
+ input_unregister_device(info->idev);
+ kfree(info);
+ return ret;
+
+out_reg:
+ input_free_device(info->idev);
+out:
+ kfree(info);
+ return ret;
+}
+
+static int __devexit pm860x_onkey_remove(struct platform_device *pdev)
+{
+ struct pm860x_onkey_info *info = platform_get_drvdata(pdev);
+
+ free_irq(info->irq, info);
+ input_unregister_device(info->idev);
+ kfree(info);
+ return 0;
+}
+
+static struct platform_driver pm860x_onkey_driver = {
+ .driver = {
+ .name = "88pm860x-onkey",
+ .owner = THIS_MODULE,
+ },
+ .probe = pm860x_onkey_probe,
+ .remove = __devexit_p(pm860x_onkey_remove),
+};
+
+static int __init pm860x_onkey_init(void)
+{
+ return platform_driver_register(&pm860x_onkey_driver);
+}
+module_init(pm860x_onkey_init);
+
+static void __exit pm860x_onkey_exit(void)
+{
+ platform_driver_unregister(&pm860x_onkey_driver);
+}
+module_exit(pm860x_onkey_exit);
+
+MODULE_DESCRIPTION("Marvell 88PM860x ONKEY driver");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 16ec5233441..7097bfe581d 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -12,6 +12,16 @@ menuconfig INPUT_MISC
if INPUT_MISC
+config INPUT_88PM860X_ONKEY
+ tristate "88PM860x ONKEY support"
+ depends on MFD_88PM860X
+ help
+ Support the ONKEY of Marvell 88PM860x PMICs as an input device
+ reporting power button status.
+
+ To compile this driver as a module, choose M here: the module
+ will be called 88pm860x_onkey.
+
config INPUT_PCSPKR
tristate "PC Speaker support"
depends on PCSPKR_PLATFORM
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index a8b84854fb7..b611615e24a 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -4,6 +4,7 @@
# Each configuration option enables a list of files.
+obj-$(CONFIG_INPUT_88PM860X_ONKEY) += 88pm860x_onkey.o
obj-$(CONFIG_INPUT_APANEL) += apanel.o
obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o
obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o
diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c
new file mode 100644
index 00000000000..286bb490a9f
--- /dev/null
+++ b/drivers/input/touchscreen/88pm860x-ts.c
@@ -0,0 +1,236 @@
+/*
+ * Touchscreen driver for Marvell 88PM860x
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ * Haojian Zhuang <haojian.zhuang@marvell.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/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/mfd/88pm860x.h>
+
+#define MEAS_LEN (8)
+#define ACCURATE_BIT (12)
+
+/* touch register */
+#define MEAS_EN3 (0x52)
+
+#define MEAS_TSIX_1 (0x8D)
+#define MEAS_TSIX_2 (0x8E)
+#define MEAS_TSIY_1 (0x8F)
+#define MEAS_TSIY_2 (0x90)
+#define MEAS_TSIZ1_1 (0x91)
+#define MEAS_TSIZ1_2 (0x92)
+#define MEAS_TSIZ2_1 (0x93)
+#define MEAS_TSIZ2_2 (0x94)
+
+/* bit definitions of touch */
+#define MEAS_PD_EN (1 << 3)
+#define MEAS_TSIX_EN (1 << 4)
+#define MEAS_TSIY_EN (1 << 5)
+#define MEAS_TSIZ1_EN (1 << 6)
+#define MEAS_TSIZ2_EN (1 << 7)
+
+struct pm860x_touch {
+ struct input_dev *idev;
+ struct i2c_client *i2c;
+ struct pm860x_chip *chip;
+ int irq;
+ int res_x; /* resistor of Xplate */
+};
+
+static irqreturn_t pm860x_touch_handler(int irq, void *data)
+{
+ struct pm860x_touch *touch = data;
+ struct pm860x_chip *chip = touch->chip;
+ unsigned char buf[MEAS_LEN];
+ int x, y, pen_down;
+ int z1, z2, rt = 0;
+ int ret;
+
+ ret = pm860x_bulk_read(touch->i2c, MEAS_TSIX_1, MEAS_LEN, buf);
+ if (ret < 0)
+ goto out;
+
+ pen_down = buf[1] & (1 << 6);
+ x = ((buf[0] & 0xFF) << 4) | (buf[1] & 0x0F);
+ y = ((buf[2] & 0xFF) << 4) | (buf[3] & 0x0F);
+ z1 = ((buf[4] & 0xFF) << 4) | (buf[5] & 0x0F);
+ z2 = ((buf[6] & 0xFF) << 4) | (buf[7] & 0x0F);
+
+ if (pen_down) {
+ if ((x != 0) && (z1 != 0) && (touch->res_x != 0)) {
+ rt = z2 / z1 - 1;
+ rt = (rt * touch->res_x * x) >> ACCURATE_BIT;
+ dev_dbg(chip->dev, "z1:%d, z2:%d, rt:%d\n",
+ z1, z2, rt);
+ }
+ input_report_abs(touch->idev, ABS_X, x);
+ input_report_abs(touch->idev, ABS_Y, y);
+ input_report_abs(touch->idev, ABS_PRESSURE, rt);
+ input_report_key(touch->idev, BTN_TOUCH, 1);
+ dev_dbg(chip->dev, "pen down at [%d, %d].\n", x, y);
+ } else {
+ input_report_abs(touch->idev, ABS_PRESSURE, 0);
+ input_report_key(touch->idev, BTN_TOUCH, 0);
+ dev_dbg(chip->dev, "pen release\n");
+ }
+ input_sync(touch->idev);
+
+out:
+ return IRQ_HANDLED;
+}
+
+static int pm860x_touch_open(struct input_dev *dev)
+{
+ struct pm860x_touch *touch = input_get_drvdata(dev);
+ int data, ret;
+
+ data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN
+ | MEAS_TSIZ1_EN | MEAS_TSIZ2_EN;
+ ret = pm860x_set_bits(touch->i2c, MEAS_EN3, data, data);
+ if (ret < 0)
+ goto out;
+ return 0;
+out:
+ return ret;
+}
+
+static void pm860x_touch_close(struct input_dev *dev)
+{
+ struct pm860x_touch *touch = input_get_drvdata(dev);
+ int data;
+
+ data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN
+ | MEAS_TSIZ1_EN | MEAS_TSIZ2_EN;
+ pm860x_set_bits(touch->i2c, MEAS_EN3, data, 0);
+}
+
+static int __devinit pm860x_touch_probe(struct platform_device *pdev)
+{
+ struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ struct pm860x_platform_data *pm860x_pdata = \
+ pdev->dev.parent->platform_data;
+ struct pm860x_touch_pdata *pdata = NULL;
+ struct pm860x_touch *touch;
+ int irq, ret;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_err(&pdev->dev, "No IRQ resource!\n");
+ return -EINVAL;
+ }
+
+ if (!pm860x_pdata) {
+ dev_err(&pdev->dev, "platform data is missing\n");
+ return -EINVAL;
+ }
+
+ pdata = pm860x_pdata->touch;
+ if (!pdata) {
+ dev_err(&pdev->dev, "touchscreen data is missing\n");
+ return -EINVAL;
+ }
+
+ touch = kzalloc(sizeof(struct pm860x_touch), GFP_KERNEL);
+ if (touch == NULL)
+ return -ENOMEM;
+ dev_set_drvdata(&pdev->dev, touch);
+
+ touch->idev = input_allocate_device();
+ if (touch->idev == NULL) {
+ dev_err(&pdev->dev, "Failed to allocate input device!\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ touch->idev->name = "88pm860x-touch";
+ touch->idev->phys = "88pm860x/input0";
+ touch->idev->id.bustype = BUS_I2C;
+ touch->idev->dev.parent = &pdev->dev;
+ touch->idev->open = pm860x_touch_open;
+ touch->idev->close = pm860x_touch_close;
+ touch->chip = chip;
+ touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
+ touch->irq = irq + chip->irq_base;
+ touch->res_x = pdata->res_x;
+ input_set_drvdata(touch->idev, touch);
+
+ ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler,
+ IRQF_ONESHOT, "touch", touch);
+ if (ret < 0)
+ goto out_irq;
+
+ __set_bit(EV_ABS, touch->idev->evbit);
+ __set_bit(ABS_X, touch->idev->absbit);
+ __set_bit(ABS_Y, touch->idev->absbit);
+ __set_bit(ABS_PRESSURE, touch->idev->absbit);
+ __set_bit(EV_SYN, touch->idev->evbit);
+ __set_bit(EV_KEY, touch->idev->evbit);
+ __set_bit(BTN_TOUCH, touch->idev->keybit);
+
+ input_set_abs_params(touch->idev, ABS_X, 0, 1 << ACCURATE_BIT, 0, 0);
+ input_set_abs_params(touch->idev, ABS_Y, 0, 1 << ACCURATE_BIT, 0, 0);
+ input_set_abs_params(touch->idev, ABS_PRESSURE, 0, 1 << ACCURATE_BIT,
+ 0, 0);
+
+ ret = input_register_device(touch->idev);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to register touch!\n");
+ goto out_rg;
+ }
+
+ platform_set_drvdata(pdev, touch);
+ return 0;
+out_rg:
+ free_irq(touch->irq, touch);
+out_irq:
+ input_free_device(touch->idev);
+out:
+ kfree(touch);
+ return ret;
+}
+
+static int __devexit pm860x_touch_remove(struct platform_device *pdev)
+{
+ struct pm860x_touch *touch = platform_get_drvdata(pdev);
+
+ input_unregister_device(touch->idev);
+ free_irq(touch->irq, touch);
+ platform_set_drvdata(pdev, NULL);
+ kfree(touch);
+ return 0;
+}
+
+static struct platform_driver pm860x_touch_driver = {
+ .driver = {
+ .name = "88pm860x-touch",
+ .owner = THIS_MODULE,
+ },
+ .probe = pm860x_touch_probe,
+ .remove = __devexit_p(pm860x_touch_remove),
+};
+
+static int __init pm860x_touch_init(void)
+{
+ return platform_driver_register(&pm860x_touch_driver);
+}
+module_init(pm860x_touch_init);
+
+static void __exit pm860x_touch_exit(void)
+{
+ platform_driver_unregister(&pm860x_touch_driver);
+}
+module_exit(pm860x_touch_exit);
+
+MODULE_DESCRIPTION("Touchscreen driver for Marvell Semiconductor 88PM860x");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:88pm860x-touch");
+
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 6457e060ae4..7208654a94a 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -11,6 +11,18 @@ menuconfig INPUT_TOUCHSCREEN
if INPUT_TOUCHSCREEN
+config TOUCHSCREEN_88PM860X
+ tristate "Marvell 88PM860x touchscreen"
+ depends on MFD_88PM860X
+ help
+ Say Y here if you have a 88PM860x PMIC and want to enable
+ support for the built-in touchscreen.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called 88pm860x-ts.
+
config TOUCHSCREEN_ADS7846
tristate "ADS7846/TSC2046 and ADS7843 based touchscreens"
depends on SPI_MASTER
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index d61a3b4def9..7fef7d5cca2 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -6,6 +6,7 @@
wm97xx-ts-y := wm97xx-core.o
+obj-$(CONFIG_TOUCHSCREEN_88PM860X) += 88pm860x-ts.o
obj-$(CONFIG_TOUCHSCREEN_AD7877) += ad7877.o
obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o
obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c
index be115b3b65e..be54fd639ac 100644
--- a/drivers/input/touchscreen/mc13783_ts.c
+++ b/drivers/input/touchscreen/mc13783_ts.c
@@ -44,7 +44,7 @@ static irqreturn_t mc13783_ts_handler(int irq, void *data)
{
struct mc13783_ts_priv *priv = data;
- mc13783_ackirq(priv->mc13783, irq);
+ mc13783_irq_ack(priv->mc13783, irq);
/*
* Kick off reading coordinates. Note that if work happens already
@@ -135,7 +135,7 @@ static int mc13783_ts_open(struct input_dev *dev)
mc13783_lock(priv->mc13783);
- mc13783_ackirq(priv->mc13783, MC13783_IRQ_TS);
+ mc13783_irq_ack(priv->mc13783, MC13783_IRQ_TS);
ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_TS,
mc13783_ts_handler, MC13783_TS_NAME, priv);
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 8a0e1ec95e4..e0b64312e66 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -17,6 +17,13 @@ config LEDS_CLASS
comment "LED drivers"
+config LEDS_88PM860X
+ tristate "LED Support for Marvell 88PM860x PMIC"
+ depends on LEDS_CLASS && MFD_88PM860X
+ help
+ This option enables support for on-chip LED drivers found on Marvell
+ Semiconductor 88PM8606 PMIC.
+
config LEDS_ATMEL_PWM
tristate "LED Support using Atmel PWM outputs"
depends on LEDS_CLASS && ATMEL_PWM
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 9e63869d7c0..d76fb32b77c 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_LEDS_CLASS) += led-class.o
obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o
# LED Platform Drivers
+obj-$(CONFIG_LEDS_88PM860X) += leds-88pm860x.o
obj-$(CONFIG_LEDS_ATMEL_PWM) += leds-atmel-pwm.o
obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o
obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c
new file mode 100644
index 00000000000..d196073a6ae
--- /dev/null
+++ b/drivers/leds/leds-88pm860x.c
@@ -0,0 +1,325 @@
+/*
+ * LED driver for Marvell 88PM860x
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ * Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/workqueue.h>
+#include <linux/mfd/88pm860x.h>
+
+#define LED_PWM_SHIFT (3)
+#define LED_PWM_MASK (0x1F)
+#define LED_CURRENT_MASK (0x07 << 5)
+
+#define LED_BLINK_ON_MASK (0x07)
+#define LED_BLINK_PERIOD_MASK (0x0F << 3)
+#define LED_BLINK_MASK (0x7F)
+
+#define LED_BLINK_ON(x) ((x & 0x7) * 66 + 66)
+#define LED_BLINK_PERIOD(x) ((x & 0xF) * 530 + 930)
+#define LED_BLINK_ON_MIN LED_BLINK_ON(0)
+#define LED_BLINK_ON_MAX LED_BLINK_ON(0x7)
+#define LED_BLINK_PERIOD_MIN LED_BLINK_PERIOD(0)
+#define LED_BLINK_PERIOD_MAX LED_BLINK_PERIOD(0xE)
+#define LED_TO_ON(x) ((x - 66) / 66)
+#define LED_TO_PERIOD(x) ((x - 930) / 530)
+
+#define LED1_BLINK_EN (1 << 1)
+#define LED2_BLINK_EN (1 << 2)
+
+enum {
+ SET_BRIGHTNESS,
+ SET_BLINK,
+};
+
+struct pm860x_led {
+ struct led_classdev cdev;
+ struct i2c_client *i2c;
+ struct work_struct work;
+ struct pm860x_chip *chip;
+ struct mutex lock;
+ char name[MFD_NAME_SIZE];
+
+ int port;
+ int iset;
+ int command;
+ int offset;
+ unsigned char brightness;
+ unsigned char current_brightness;
+
+ int blink_data;
+ int blink_time;
+ int blink_on;
+ int blink_off;
+};
+
+/* return offset of color register */
+static inline int __led_off(int port)
+{
+ int ret = -EINVAL;
+
+ switch (port) {
+ case PM8606_LED1_RED:
+ case PM8606_LED1_GREEN:
+ case PM8606_LED1_BLUE:
+ ret = port - PM8606_LED1_RED + PM8606_RGB1B;
+ break;
+ case PM8606_LED2_RED:
+ case PM8606_LED2_GREEN:
+ case PM8606_LED2_BLUE:
+ ret = port - PM8606_LED2_RED + PM8606_RGB2B;
+ break;
+ }
+ return ret;
+}
+
+/* return offset of blink register */
+static inline int __blink_off(int port)
+{
+ int ret = -EINVAL;
+
+ switch (port) {
+ case PM8606_LED1_RED:
+ case PM8606_LED1_GREEN:
+ case PM8606_LED1_BLUE:
+ ret = PM8606_RGB1A;
+ case PM8606_LED2_RED:
+ case PM8606_LED2_GREEN:
+ case PM8606_LED2_BLUE:
+ ret = PM8606_RGB2A;
+ }
+ return ret;
+}
+
+static inline int __blink_ctl_mask(int port)
+{
+ int ret = -EINVAL;
+
+ switch (port) {
+ case PM8606_LED1_RED:
+ case PM8606_LED1_GREEN:
+ case PM8606_LED1_BLUE:
+ ret = LED1_BLINK_EN;
+ break;
+ case PM8606_LED2_RED:
+ case PM8606_LED2_GREEN:
+ case PM8606_LED2_BLUE:
+ ret = LED2_BLINK_EN;
+ break;
+ }
+ return ret;
+}
+
+static int __led_set(struct pm860x_led *led, int command)
+{
+ struct pm860x_chip *chip = led->chip;
+ int mask, ret;
+
+ mutex_lock(&led->lock);
+ switch (command) {
+ case SET_BRIGHTNESS:
+ if ((led->current_brightness == 0) && led->brightness) {
+ if (led->iset) {
+ ret = pm860x_set_bits(led->i2c, led->offset,
+ LED_CURRENT_MASK, led->iset);
+ if (ret < 0)
+ goto out;
+ }
+ } else if (led->brightness == 0) {
+ ret = pm860x_set_bits(led->i2c, led->offset,
+ LED_CURRENT_MASK, 0);
+ if (ret < 0)
+ goto out;
+ }
+ ret = pm860x_set_bits(led->i2c, led->offset, LED_PWM_MASK,
+ led->brightness);
+ if (ret < 0)
+ goto out;
+ led->current_brightness = led->brightness;
+ dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n",
+ led->offset, led->brightness);
+ break;
+ case SET_BLINK:
+ ret = pm860x_set_bits(led->i2c, led->offset,
+ LED_BLINK_MASK, led->blink_data);
+ if (ret < 0)
+ goto out;
+
+ mask = __blink_ctl_mask(led->port);
+ ret = pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask);
+ if (ret < 0)
+ goto out;
+ dev_dbg(chip->dev, "LED blink delay on:%dms, delay off:%dms\n",
+ led->blink_on, led->blink_off);
+ break;
+ }
+out:
+ mutex_unlock(&led->lock);
+ return 0;
+}
+
+static void pm860x_led_work(struct work_struct *work)
+{
+ struct pm860x_led *led;
+
+ led = container_of(work, struct pm860x_led, work);
+ __led_set(led, led->command);
+}
+
+static void pm860x_led_set(struct led_classdev *cdev,
+ enum led_brightness value)
+{
+ struct pm860x_led *data = container_of(cdev, struct pm860x_led, cdev);
+
+ data->offset = __led_off(data->port);
+ data->brightness = value >> 3;
+ data->command = SET_BRIGHTNESS;
+ schedule_work(&data->work);
+}
+
+static int pm860x_led_blink(struct led_classdev *cdev,
+ unsigned long *delay_on,
+ unsigned long *delay_off)
+{
+ struct pm860x_led *data = container_of(cdev, struct pm860x_led, cdev);
+ int period, on;
+
+ on = *delay_on;
+ if ((on < LED_BLINK_ON_MIN) || (on > LED_BLINK_ON_MAX))
+ return -EINVAL;
+
+ on = LED_TO_ON(on);
+ on = LED_BLINK_ON(on);
+
+ period = on + *delay_off;
+ if ((period < LED_BLINK_PERIOD_MIN) || (period > LED_BLINK_PERIOD_MAX))
+ return -EINVAL;
+ period = LED_TO_PERIOD(period);
+ period = LED_BLINK_PERIOD(period);
+
+ data->offset = __blink_off(data->port);
+ data->blink_on = on;
+ data->blink_off = period - data->blink_on;
+ data->blink_data = (period << 3) | data->blink_on;
+ data->command = SET_BLINK;
+ schedule_work(&data->work);
+
+ return 0;
+}
+
+static int __check_device(struct pm860x_led_pdata *pdata, char *name)
+{
+ struct pm860x_led_pdata *p = pdata;
+ int ret = -EINVAL;
+
+ while (p && p->id) {
+ if ((p->id != PM8606_ID_LED) || (p->flags < 0))
+ break;
+
+ if (!strncmp(name, pm860x_led_name[p->flags],
+ MFD_NAME_SIZE)) {
+ ret = (int)p->flags;
+ break;
+ }
+ p++;
+ }
+ return ret;
+}
+
+static int pm860x_led_probe(struct platform_device *pdev)
+{
+ struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ struct pm860x_platform_data *pm860x_pdata;
+ struct pm860x_led_pdata *pdata;
+ struct pm860x_led *data;
+ struct resource *res;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "No I/O resource!\n");
+ return -EINVAL;
+ }
+
+ if (pdev->dev.parent->platform_data) {
+ pm860x_pdata = pdev->dev.parent->platform_data;
+ pdata = pm860x_pdata->led;
+ } else
+ pdata = NULL;
+
+ data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+ strncpy(data->name, res->name, MFD_NAME_SIZE);
+ dev_set_drvdata(&pdev->dev, data);
+ data->chip = chip;
+ data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion;
+ data->iset = pdata->iset;
+ data->port = __check_device(pdata, data->name);
+ if (data->port < 0)
+ return -EINVAL;
+
+ data->current_brightness = 0;
+ data->cdev.name = data->name;
+ data->cdev.brightness_set = pm860x_led_set;
+ data->cdev.blink_set = pm860x_led_blink;
+ mutex_init(&data->lock);
+ INIT_WORK(&data->work, pm860x_led_work);
+
+ ret = led_classdev_register(chip->dev, &data->cdev);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to register LED: %d\n", ret);
+ goto out;
+ }
+ return 0;
+out:
+ kfree(data);
+ return ret;
+}
+
+static int pm860x_led_remove(struct platform_device *pdev)
+{
+ struct pm860x_led *data = platform_get_drvdata(pdev);
+
+ led_classdev_unregister(&data->cdev);
+ kfree(data);
+
+ return 0;
+}
+
+static struct platform_driver pm860x_led_driver = {
+ .driver = {
+ .name = "88pm860x-led",
+ .owner = THIS_MODULE,
+ },
+ .probe = pm860x_led_probe,
+ .remove = pm860x_led_remove,
+};
+
+static int __devinit pm860x_led_init(void)
+{
+ return platform_driver_register(&pm860x_led_driver);
+}
+module_init(pm860x_led_init);
+
+static void __devexit pm860x_led_exit(void)
+{
+ platform_driver_unregister(&pm860x_led_driver);
+}
+module_exit(pm860x_led_exit);
+
+MODULE_DESCRIPTION("LED driver for Marvell PM860x");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:88pm860x-led");
diff --git a/drivers/macintosh/windfarm_core.c b/drivers/macintosh/windfarm_core.c
index 437f55c5d18..419795f4a2a 100644
--- a/drivers/macintosh/windfarm_core.c
+++ b/drivers/macintosh/windfarm_core.c
@@ -321,6 +321,7 @@ int wf_register_sensor(struct wf_sensor *new_sr)
kref_init(&new_sr->ref);
list_add(&new_sr->link, &wf_sensors);
+ sysfs_attr_init(&new_sr->attr.attr);
new_sr->attr.attr.name = new_sr->name;
new_sr->attr.attr.mode = 0444;
new_sr->attr.show = wf_show_sensor;
diff --git a/drivers/macintosh/windfarm_smu_controls.c b/drivers/macintosh/windfarm_smu_controls.c
index 6c68b9e5f5c..43137b421f9 100644
--- a/drivers/macintosh/windfarm_smu_controls.c
+++ b/drivers/macintosh/windfarm_smu_controls.c
@@ -173,6 +173,7 @@ static struct smu_fan_control *smu_fan_create(struct device_node *node,
fct->fan_type = pwm_fan;
fct->ctrl.type = pwm_fan ? WF_CONTROL_PWM_FAN : WF_CONTROL_RPM_FAN;
+ sysfs_attr_init(&fct->ctrl.attr.attr);
/* We use the name & location here the same way we do for SMU sensors,
* see the comment in windfarm_smu_sensors.c. The locations are a bit
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index a93637223c8..3bdbb611570 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -1160,8 +1160,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
}
cc->start = tmpll;
- if (dm_get_device(ti, argv[3], cc->start, ti->len,
- dm_table_get_mode(ti->table), &cc->dev)) {
+ if (dm_get_device(ti, argv[3], dm_table_get_mode(ti->table), &cc->dev)) {
ti->error = "Device lookup failed";
goto bad_device;
}
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c
index ebe7381f47c..852052880d7 100644
--- a/drivers/md/dm-delay.c
+++ b/drivers/md/dm-delay.c
@@ -156,8 +156,8 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad;
}
- if (dm_get_device(ti, argv[0], dc->start_read, ti->len,
- dm_table_get_mode(ti->table), &dc->dev_read)) {
+ if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
+ &dc->dev_read)) {
ti->error = "Device lookup failed";
goto bad;
}
@@ -177,8 +177,8 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad_dev_read;
}
- if (dm_get_device(ti, argv[3], dc->start_write, ti->len,
- dm_table_get_mode(ti->table), &dc->dev_write)) {
+ if (dm_get_device(ti, argv[3], dm_table_get_mode(ti->table),
+ &dc->dev_write)) {
ti->error = "Write device lookup failed";
goto bad_dev_read;
}
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 1d669322b27..d7500e1c26f 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -285,7 +285,8 @@ retry:
up_write(&_hash_lock);
}
-static int dm_hash_rename(uint32_t cookie, const char *old, const char *new)
+static int dm_hash_rename(uint32_t cookie, uint32_t *flags, const char *old,
+ const char *new)
{
char *new_name, *old_name;
struct hash_cell *hc;
@@ -344,7 +345,8 @@ static int dm_hash_rename(uint32_t cookie, const char *old, const char *new)
dm_table_put(table);
}
- dm_kobject_uevent(hc->md, KOBJ_CHANGE, cookie);
+ if (!dm_kobject_uevent(hc->md, KOBJ_CHANGE, cookie))
+ *flags |= DM_UEVENT_GENERATED_FLAG;
dm_put(hc->md);
up_write(&_hash_lock);
@@ -736,10 +738,10 @@ static int dev_remove(struct dm_ioctl *param, size_t param_size)
__hash_remove(hc);
up_write(&_hash_lock);
- dm_kobject_uevent(md, KOBJ_REMOVE, param->event_nr);
+ if (!dm_kobject_uevent(md, KOBJ_REMOVE, param->event_nr))
+ param->flags |= DM_UEVENT_GENERATED_FLAG;
dm_put(md);
- param->data_size = 0;
return 0;
}
@@ -773,7 +775,9 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size)
return r;
param->data_size = 0;
- return dm_hash_rename(param->event_nr, param->name, new_name);
+
+ return dm_hash_rename(param->event_nr, &param->flags, param->name,
+ new_name);
}
static int dev_set_geometry(struct dm_ioctl *param, size_t param_size)
@@ -897,16 +901,17 @@ static int do_resume(struct dm_ioctl *param)
set_disk_ro(dm_disk(md), 1);
}
- if (dm_suspended_md(md))
+ if (dm_suspended_md(md)) {
r = dm_resume(md);
+ if (!r && !dm_kobject_uevent(md, KOBJ_CHANGE, param->event_nr))
+ param->flags |= DM_UEVENT_GENERATED_FLAG;
+ }
if (old_map)
dm_table_destroy(old_map);
- if (!r) {
- dm_kobject_uevent(md, KOBJ_CHANGE, param->event_nr);
+ if (!r)
r = __dev_status(md, param);
- }
dm_put(md);
return r;
@@ -1476,6 +1481,7 @@ static int validate_params(uint cmd, struct dm_ioctl *param)
{
/* Always clear this flag */
param->flags &= ~DM_BUFFER_FULL_FLAG;
+ param->flags &= ~DM_UEVENT_GENERATED_FLAG;
/* Ignores parameters */
if (cmd == DM_REMOVE_ALL_CMD ||
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 82f7d6e6b1e..9200dbf2391 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -47,8 +47,7 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
}
lc->start = tmp;
- if (dm_get_device(ti, argv[0], lc->start, ti->len,
- dm_table_get_mode(ti->table), &lc->dev)) {
+ if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &lc->dev)) {
ti->error = "dm-linear: Device lookup failed";
goto bad;
}
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c
index 7035582786f..5a08be0222d 100644
--- a/drivers/md/dm-log.c
+++ b/drivers/md/dm-log.c
@@ -543,8 +543,7 @@ static int disk_ctr(struct dm_dirty_log *log, struct dm_target *ti,
return -EINVAL;
}
- r = dm_get_device(ti, argv[0], 0, 0 /* FIXME */,
- FMODE_READ | FMODE_WRITE, &dev);
+ r = dm_get_device(ti, argv[0], FMODE_READ | FMODE_WRITE, &dev);
if (r)
return r;
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index e81345a1d08..826bce7343b 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -69,6 +69,7 @@ struct multipath {
struct list_head priority_groups;
unsigned pg_init_required; /* pg_init needs calling? */
unsigned pg_init_in_progress; /* Only one pg_init allowed at once */
+ wait_queue_head_t pg_init_wait; /* Wait for pg_init completion */
unsigned nr_valid_paths; /* Total number of usable paths */
struct pgpath *current_pgpath;
@@ -95,8 +96,6 @@ struct multipath {
mempool_t *mpio_pool;
struct mutex work_mutex;
-
- unsigned suspended; /* Don't create new I/O internally when set. */
};
/*
@@ -202,6 +201,7 @@ 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_waitqueue_head(&m->pg_init_wait);
mutex_init(&m->work_mutex);
m->mpio_pool = mempool_create_slab_pool(MIN_IOS, _mpio_cache);
if (!m->mpio_pool) {
@@ -235,6 +235,21 @@ static void free_multipath(struct multipath *m)
* Path selection
*-----------------------------------------------*/
+static void __pg_init_all_paths(struct multipath *m)
+{
+ struct pgpath *pgpath;
+
+ m->pg_init_count++;
+ m->pg_init_required = 0;
+ list_for_each_entry(pgpath, &m->current_pg->pgpaths, list) {
+ /* Skip failed paths */
+ if (!pgpath->is_active)
+ continue;
+ if (queue_work(kmpath_handlerd, &pgpath->activate_path))
+ m->pg_init_in_progress++;
+ }
+}
+
static void __switch_pg(struct multipath *m, struct pgpath *pgpath)
{
m->current_pg = pgpath->pg;
@@ -439,7 +454,7 @@ static void process_queued_ios(struct work_struct *work)
{
struct multipath *m =
container_of(work, struct multipath, process_queued_ios);
- struct pgpath *pgpath = NULL, *tmp;
+ struct pgpath *pgpath = NULL;
unsigned must_queue = 1;
unsigned long flags;
@@ -457,14 +472,9 @@ static void process_queued_ios(struct work_struct *work)
(!pgpath && !m->queue_if_no_path))
must_queue = 0;
- if (m->pg_init_required && !m->pg_init_in_progress && pgpath) {
- m->pg_init_count++;
- m->pg_init_required = 0;
- list_for_each_entry(tmp, &pgpath->pg->pgpaths, list) {
- if (queue_work(kmpath_handlerd, &tmp->activate_path))
- m->pg_init_in_progress++;
- }
- }
+ if (m->pg_init_required && !m->pg_init_in_progress && pgpath)
+ __pg_init_all_paths(m);
+
out:
spin_unlock_irqrestore(&m->lock, flags);
if (!must_queue)
@@ -597,8 +607,8 @@ static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
if (!p)
return ERR_PTR(-ENOMEM);
- r = dm_get_device(ti, shift(as), ti->begin, ti->len,
- dm_table_get_mode(ti->table), &p->path.dev);
+ r = dm_get_device(ti, shift(as), dm_table_get_mode(ti->table),
+ &p->path.dev);
if (r) {
ti->error = "error getting device";
goto bad;
@@ -890,9 +900,34 @@ static int multipath_ctr(struct dm_target *ti, unsigned int argc,
return r;
}
-static void flush_multipath_work(void)
+static void multipath_wait_for_pg_init_completion(struct multipath *m)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ unsigned long flags;
+
+ add_wait_queue(&m->pg_init_wait, &wait);
+
+ while (1) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+
+ spin_lock_irqsave(&m->lock, flags);
+ if (!m->pg_init_in_progress) {
+ spin_unlock_irqrestore(&m->lock, flags);
+ break;
+ }
+ spin_unlock_irqrestore(&m->lock, flags);
+
+ io_schedule();
+ }
+ set_current_state(TASK_RUNNING);
+
+ remove_wait_queue(&m->pg_init_wait, &wait);
+}
+
+static void flush_multipath_work(struct multipath *m)
{
flush_workqueue(kmpath_handlerd);
+ multipath_wait_for_pg_init_completion(m);
flush_workqueue(kmultipathd);
flush_scheduled_work();
}
@@ -901,7 +936,7 @@ static void multipath_dtr(struct dm_target *ti)
{
struct multipath *m = ti->private;
- flush_multipath_work();
+ flush_multipath_work(m);
free_multipath(m);
}
@@ -1128,8 +1163,7 @@ static int pg_init_limit_reached(struct multipath *m, struct pgpath *pgpath)
static void pg_init_done(void *data, int errors)
{
- struct dm_path *path = data;
- struct pgpath *pgpath = path_to_pgpath(path);
+ struct pgpath *pgpath = data;
struct priority_group *pg = pgpath->pg;
struct multipath *m = pg->m;
unsigned long flags;
@@ -1143,8 +1177,8 @@ static void pg_init_done(void *data, int errors)
errors = 0;
break;
}
- DMERR("Cannot failover device because scsi_dh_%s was not "
- "loaded.", m->hw_handler_name);
+ DMERR("Could not failover the device: Handler scsi_dh_%s "
+ "Error %d.", m->hw_handler_name, errors);
/*
* Fail path for now, so we do not ping pong
*/
@@ -1181,14 +1215,24 @@ static void pg_init_done(void *data, int errors)
m->current_pgpath = NULL;
m->current_pg = NULL;
}
- } else if (!m->pg_init_required) {
- m->queue_io = 0;
+ } else if (!m->pg_init_required)
pg->bypassed = 0;
- }
- m->pg_init_in_progress--;
- if (!m->pg_init_in_progress)
- queue_work(kmultipathd, &m->process_queued_ios);
+ if (--m->pg_init_in_progress)
+ /* Activations of other paths are still on going */
+ goto out;
+
+ if (!m->pg_init_required)
+ m->queue_io = 0;
+
+ queue_work(kmultipathd, &m->process_queued_ios);
+
+ /*
+ * Wake up any thread waiting to suspend.
+ */
+ wake_up(&m->pg_init_wait);
+
+out:
spin_unlock_irqrestore(&m->lock, flags);
}
@@ -1198,7 +1242,7 @@ static void activate_path(struct work_struct *work)
container_of(work, struct pgpath, activate_path);
scsi_dh_activate(bdev_get_queue(pgpath->path.dev->bdev),
- pg_init_done, &pgpath->path);
+ pg_init_done, pgpath);
}
/*
@@ -1276,8 +1320,7 @@ static void multipath_postsuspend(struct dm_target *ti)
struct multipath *m = ti->private;
mutex_lock(&m->work_mutex);
- m->suspended = 1;
- flush_multipath_work();
+ flush_multipath_work(m);
mutex_unlock(&m->work_mutex);
}
@@ -1289,10 +1332,6 @@ static void multipath_resume(struct dm_target *ti)
struct multipath *m = (struct multipath *) ti->private;
unsigned long flags;
- mutex_lock(&m->work_mutex);
- m->suspended = 0;
- mutex_unlock(&m->work_mutex);
-
spin_lock_irqsave(&m->lock, flags);
m->queue_if_no_path = m->saved_queue_if_no_path;
spin_unlock_irqrestore(&m->lock, flags);
@@ -1428,11 +1467,6 @@ static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
mutex_lock(&m->work_mutex);
- if (m->suspended) {
- r = -EBUSY;
- goto out;
- }
-
if (dm_suspended(ti)) {
r = -EBUSY;
goto out;
@@ -1471,8 +1505,7 @@ static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
goto out;
}
- r = dm_get_device(ti, argv[1], ti->begin, ti->len,
- dm_table_get_mode(ti->table), &dev);
+ r = dm_get_device(ti, argv[1], dm_table_get_mode(ti->table), &dev);
if (r) {
DMWARN("message: error getting device %s",
argv[1]);
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 6c1046df81f..ddda531723d 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -465,9 +465,17 @@ static void map_region(struct dm_io_region *io, struct mirror *m,
static void hold_bio(struct mirror_set *ms, struct bio *bio)
{
/*
- * If device is suspended, complete the bio.
+ * Lock is required to avoid race condition during suspend
+ * process.
*/
+ spin_lock_irq(&ms->lock);
+
if (atomic_read(&ms->suspend)) {
+ spin_unlock_irq(&ms->lock);
+
+ /*
+ * If device is suspended, complete the bio.
+ */
if (dm_noflush_suspending(ms->ti))
bio_endio(bio, DM_ENDIO_REQUEUE);
else
@@ -478,7 +486,6 @@ static void hold_bio(struct mirror_set *ms, struct bio *bio)
/*
* Hold bio until the suspend is complete.
*/
- spin_lock_irq(&ms->lock);
bio_list_add(&ms->holds, bio);
spin_unlock_irq(&ms->lock);
}
@@ -737,9 +744,12 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
dm_rh_delay(ms->rh, bio);
while ((bio = bio_list_pop(&nosync))) {
- if (unlikely(ms->leg_failure) && errors_handled(ms))
- hold_bio(ms, bio);
- else {
+ if (unlikely(ms->leg_failure) && errors_handled(ms)) {
+ spin_lock_irq(&ms->lock);
+ bio_list_add(&ms->failures, bio);
+ spin_unlock_irq(&ms->lock);
+ wakeup_mirrord(ms);
+ } else {
map_bio(get_default_mirror(ms), bio);
generic_make_request(bio);
}
@@ -917,8 +927,7 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
return -EINVAL;
}
- if (dm_get_device(ti, argv[0], offset, ti->len,
- dm_table_get_mode(ti->table),
+ if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
&ms->mirror[mirror].dev)) {
ti->error = "Device lookup failure";
return -ENXIO;
@@ -1259,6 +1268,20 @@ static void mirror_presuspend(struct dm_target *ti)
atomic_set(&ms->suspend, 1);
/*
+ * Process bios in the hold list to start recovery waiting
+ * for bios in the hold list. After the process, no bio has
+ * a chance to be added in the hold list because ms->suspend
+ * is set.
+ */
+ spin_lock_irq(&ms->lock);
+ holds = ms->holds;
+ bio_list_init(&ms->holds);
+ spin_unlock_irq(&ms->lock);
+
+ while ((bio = bio_list_pop(&holds)))
+ hold_bio(ms, bio);
+
+ /*
* We must finish up all the work that we've
* generated (i.e. recovery work).
*/
@@ -1278,22 +1301,6 @@ static void mirror_presuspend(struct dm_target *ti)
* we know that all of our I/O has been pushed.
*/
flush_workqueue(ms->kmirrord_wq);
-
- /*
- * Now set ms->suspend is set and the workqueue flushed, no more
- * entries can be added to ms->hold list, so process it.
- *
- * Bios can still arrive concurrently with or after this
- * presuspend function, but they cannot join the hold list
- * because ms->suspend is set.
- */
- spin_lock_irq(&ms->lock);
- holds = ms->holds;
- bio_list_init(&ms->holds);
- spin_unlock_irq(&ms->lock);
-
- while ((bio = bio_list_pop(&holds)))
- hold_bio(ms, bio);
}
static void mirror_postsuspend(struct dm_target *ti)
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index ee8eb283650..54853773510 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -83,10 +83,10 @@ struct dm_snapshot {
/* Whether or not owning mapped_device is suspended */
int suspended;
- mempool_t *pending_pool;
-
atomic_t pending_exceptions_count;
+ mempool_t *pending_pool;
+
struct dm_exception_table pending;
struct dm_exception_table complete;
@@ -96,6 +96,11 @@ struct dm_snapshot {
*/
spinlock_t pe_lock;
+ /* Chunks with outstanding reads */
+ spinlock_t tracked_chunk_lock;
+ mempool_t *tracked_chunk_pool;
+ struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE];
+
/* The on disk metadata handler */
struct dm_exception_store *store;
@@ -105,10 +110,12 @@ struct dm_snapshot {
struct bio_list queued_bios;
struct work_struct queued_bios_work;
- /* Chunks with outstanding reads */
- mempool_t *tracked_chunk_pool;
- spinlock_t tracked_chunk_lock;
- struct hlist_head tracked_chunk_hash[DM_TRACKED_CHUNK_HASH_SIZE];
+ /* Wait for events based on state_bits */
+ unsigned long state_bits;
+
+ /* Range of chunks currently being merged. */
+ chunk_t first_merging_chunk;
+ int num_merging_chunks;
/*
* The merge operation failed if this flag is set.
@@ -125,13 +132,6 @@ struct dm_snapshot {
*/
int merge_failed;
- /* Wait for events based on state_bits */
- unsigned long state_bits;
-
- /* Range of chunks currently being merged. */
- chunk_t first_merging_chunk;
- int num_merging_chunks;
-
/*
* Incoming bios that overlap with chunks being merged must wait
* for them to be committed.
@@ -1081,8 +1081,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
argv++;
argc--;
- r = dm_get_device(ti, cow_path, 0, 0,
- FMODE_READ | FMODE_WRITE, &s->cow);
+ r = dm_get_device(ti, cow_path, FMODE_READ | FMODE_WRITE, &s->cow);
if (r) {
ti->error = "Cannot get COW device";
goto bad_cow;
@@ -1098,7 +1097,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
argv += args_used;
argc -= args_used;
- r = dm_get_device(ti, origin_path, 0, ti->len, origin_mode, &s->origin);
+ r = dm_get_device(ti, origin_path, origin_mode, &s->origin);
if (r) {
ti->error = "Cannot get origin device";
goto bad_origin;
@@ -2100,8 +2099,7 @@ static int origin_ctr(struct dm_target *ti, unsigned int argc, char **argv)
return -EINVAL;
}
- r = dm_get_device(ti, argv[0], 0, ti->len,
- dm_table_get_mode(ti->table), &dev);
+ r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &dev);
if (r) {
ti->error = "Cannot get target device";
return r;
diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
index bd58703ee8f..e610725db76 100644
--- a/drivers/md/dm-stripe.c
+++ b/drivers/md/dm-stripe.c
@@ -80,8 +80,7 @@ static int get_stripe(struct dm_target *ti, struct stripe_c *sc,
if (sscanf(argv[1], "%llu", &start) != 1)
return -EINVAL;
- if (dm_get_device(ti, argv[0], start, sc->stripe_width,
- dm_table_get_mode(ti->table),
+ if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
&sc->stripe[stripe].dev))
return -ENXIO;
diff --git a/drivers/md/dm-sysfs.c b/drivers/md/dm-sysfs.c
index f91b40942e0..84d2b91e4ef 100644
--- a/drivers/md/dm-sysfs.c
+++ b/drivers/md/dm-sysfs.c
@@ -75,7 +75,7 @@ static struct attribute *dm_attrs[] = {
NULL,
};
-static struct sysfs_ops dm_sysfs_ops = {
+static const struct sysfs_ops dm_sysfs_ops = {
.show = dm_attr_show,
};
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 4b22feb01a0..9924ea23032 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -429,8 +429,7 @@ static int upgrade_mode(struct dm_dev_internal *dd, fmode_t new_mode,
* it's already present.
*/
static int __table_get_device(struct dm_table *t, struct dm_target *ti,
- const char *path, sector_t start, sector_t len,
- fmode_t mode, struct dm_dev **result)
+ const char *path, fmode_t mode, struct dm_dev **result)
{
int r;
dev_t uninitialized_var(dev);
@@ -527,11 +526,10 @@ int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,
}
EXPORT_SYMBOL_GPL(dm_set_device_limits);
-int dm_get_device(struct dm_target *ti, const char *path, sector_t start,
- sector_t len, fmode_t mode, struct dm_dev **result)
+int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
+ struct dm_dev **result)
{
- return __table_get_device(ti->table, ti, path,
- start, len, mode, result);
+ return __table_get_device(ti->table, ti, path, mode, result);
}
@@ -1231,8 +1229,6 @@ void dm_table_unplug_all(struct dm_table *t)
struct mapped_device *dm_table_get_md(struct dm_table *t)
{
- dm_get(t->md);
-
return t->md;
}
diff --git a/drivers/md/dm-uevent.c b/drivers/md/dm-uevent.c
index c7c555a8c7b..6b1e3b61b25 100644
--- a/drivers/md/dm-uevent.c
+++ b/drivers/md/dm-uevent.c
@@ -187,7 +187,7 @@ void dm_path_uevent(enum dm_uevent_type event_type, struct dm_target *ti,
if (event_type >= ARRAY_SIZE(_dm_uevent_type_names)) {
DMERR("%s: Invalid event_type %d", __func__, event_type);
- goto out;
+ return;
}
event = dm_build_path_uevent(md, ti,
@@ -195,12 +195,9 @@ void dm_path_uevent(enum dm_uevent_type event_type, struct dm_target *ti,
_dm_uevent_type_names[event_type].name,
path, nr_valid_paths);
if (IS_ERR(event))
- goto out;
+ return;
dm_uevent_add(md, &event->elist);
-
-out:
- dm_put(md);
}
EXPORT_SYMBOL_GPL(dm_path_uevent);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index aa4e2aa86d4..d21e1284604 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -635,8 +635,10 @@ static void dec_pending(struct dm_io *io, int error)
if (!md->barrier_error && io_error != -EOPNOTSUPP)
md->barrier_error = io_error;
end_io_acct(io);
+ free_io(md, io);
} else {
end_io_acct(io);
+ free_io(md, io);
if (io_error != DM_ENDIO_REQUEUE) {
trace_block_bio_complete(md->queue, bio);
@@ -644,8 +646,6 @@ static void dec_pending(struct dm_io *io, int error)
bio_endio(bio, io_error);
}
}
-
- free_io(md, io);
}
}
@@ -2618,18 +2618,19 @@ out:
/*-----------------------------------------------------------------
* Event notification.
*---------------------------------------------------------------*/
-void dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
+int dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
unsigned cookie)
{
char udev_cookie[DM_COOKIE_LENGTH];
char *envp[] = { udev_cookie, NULL };
if (!cookie)
- kobject_uevent(&disk_to_dev(md->disk)->kobj, action);
+ return kobject_uevent(&disk_to_dev(md->disk)->kobj, action);
else {
snprintf(udev_cookie, DM_COOKIE_LENGTH, "%s=%u",
DM_COOKIE_ENV_VAR_NAME, cookie);
- kobject_uevent_env(&disk_to_dev(md->disk)->kobj, action, envp);
+ return kobject_uevent_env(&disk_to_dev(md->disk)->kobj,
+ action, envp);
}
}
@@ -2699,23 +2700,13 @@ int dm_suspended_md(struct mapped_device *md)
int dm_suspended(struct dm_target *ti)
{
- struct mapped_device *md = dm_table_get_md(ti->table);
- int r = dm_suspended_md(md);
-
- dm_put(md);
-
- return r;
+ return dm_suspended_md(dm_table_get_md(ti->table));
}
EXPORT_SYMBOL_GPL(dm_suspended);
int dm_noflush_suspending(struct dm_target *ti)
{
- struct mapped_device *md = dm_table_get_md(ti->table);
- int r = __noflush_suspending(md);
-
- dm_put(md);
-
- return r;
+ return __noflush_suspending(dm_table_get_md(ti->table));
}
EXPORT_SYMBOL_GPL(dm_noflush_suspending);
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 8dadaa5bc39..bad1724d486 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -125,8 +125,8 @@ void dm_stripe_exit(void);
int dm_open_count(struct mapped_device *md);
int dm_lock_for_deletion(struct mapped_device *md);
-void dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
- unsigned cookie);
+int dm_kobject_uevent(struct mapped_device *md, enum kobject_action action,
+ unsigned cookie);
int dm_io_init(void);
void dm_io_exit(void);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index a20a71e5efd..fdc1890b6ac 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2642,7 +2642,7 @@ static void rdev_free(struct kobject *ko)
mdk_rdev_t *rdev = container_of(ko, mdk_rdev_t, kobj);
kfree(rdev);
}
-static struct sysfs_ops rdev_sysfs_ops = {
+static const struct sysfs_ops rdev_sysfs_ops = {
.show = rdev_attr_show,
.store = rdev_attr_store,
};
@@ -4059,7 +4059,7 @@ static void md_free(struct kobject *ko)
kfree(mddev);
}
-static struct sysfs_ops md_sysfs_ops = {
+static const struct sysfs_ops md_sysfs_ops = {
.show = md_attr_show,
.store = md_attr_store,
};
diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c
index 7400eacb4d6..142c327afb3 100644
--- a/drivers/media/video/omap24xxcam.c
+++ b/drivers/media/video/omap24xxcam.c
@@ -1735,7 +1735,7 @@ static struct v4l2_int_device omap24xxcam = {
*
*/
-static int __init omap24xxcam_probe(struct platform_device *pdev)
+static int __devinit omap24xxcam_probe(struct platform_device *pdev)
{
struct omap24xxcam_device *cam;
struct resource *mem;
diff --git a/drivers/mfd/88pm8607.c b/drivers/mfd/88pm8607.c
deleted file mode 100644
index 7e3f6590799..00000000000
--- a/drivers/mfd/88pm8607.c
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Base driver for Marvell 88PM8607
- *
- * Copyright (C) 2009 Marvell International Ltd.
- * Haojian Zhuang <haojian.zhuang@marvell.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/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/i2c.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/88pm8607.h>
-
-
-#define PM8607_REG_RESOURCE(_start, _end) \
-{ \
- .start = PM8607_##_start, \
- .end = PM8607_##_end, \
- .flags = IORESOURCE_IO, \
-}
-
-static struct resource pm8607_regulator_resources[] = {
- PM8607_REG_RESOURCE(BUCK1, BUCK1),
- PM8607_REG_RESOURCE(BUCK2, BUCK2),
- PM8607_REG_RESOURCE(BUCK3, BUCK3),
- PM8607_REG_RESOURCE(LDO1, LDO1),
- PM8607_REG_RESOURCE(LDO2, LDO2),
- PM8607_REG_RESOURCE(LDO3, LDO3),
- PM8607_REG_RESOURCE(LDO4, LDO4),
- PM8607_REG_RESOURCE(LDO5, LDO5),
- PM8607_REG_RESOURCE(LDO6, LDO6),
- PM8607_REG_RESOURCE(LDO7, LDO7),
- PM8607_REG_RESOURCE(LDO8, LDO8),
- PM8607_REG_RESOURCE(LDO9, LDO9),
- PM8607_REG_RESOURCE(LDO10, LDO10),
- PM8607_REG_RESOURCE(LDO12, LDO12),
- PM8607_REG_RESOURCE(LDO14, LDO14),
-};
-
-#define PM8607_REG_DEVS(_name, _id) \
-{ \
- .name = "88pm8607-" #_name, \
- .num_resources = 1, \
- .resources = &pm8607_regulator_resources[PM8607_ID_##_id], \
-}
-
-static struct mfd_cell pm8607_devs[] = {
- PM8607_REG_DEVS(buck1, BUCK1),
- PM8607_REG_DEVS(buck2, BUCK2),
- PM8607_REG_DEVS(buck3, BUCK3),
- PM8607_REG_DEVS(ldo1, LDO1),
- PM8607_REG_DEVS(ldo2, LDO2),
- PM8607_REG_DEVS(ldo3, LDO3),
- PM8607_REG_DEVS(ldo4, LDO4),
- PM8607_REG_DEVS(ldo5, LDO5),
- PM8607_REG_DEVS(ldo6, LDO6),
- PM8607_REG_DEVS(ldo7, LDO7),
- PM8607_REG_DEVS(ldo8, LDO8),
- PM8607_REG_DEVS(ldo9, LDO9),
- PM8607_REG_DEVS(ldo10, LDO10),
- PM8607_REG_DEVS(ldo12, LDO12),
- PM8607_REG_DEVS(ldo14, LDO14),
-};
-
-static inline int pm8607_read_device(struct pm8607_chip *chip,
- int reg, int bytes, void *dest)
-{
- struct i2c_client *i2c = chip->client;
- unsigned char data;
- int ret;
-
- data = (unsigned char)reg;
- ret = i2c_master_send(i2c, &data, 1);
- if (ret < 0)
- return ret;
-
- ret = i2c_master_recv(i2c, dest, bytes);
- if (ret < 0)
- return ret;
- return 0;
-}
-
-static inline int pm8607_write_device(struct pm8607_chip *chip,
- int reg, int bytes, void *src)
-{
- struct i2c_client *i2c = chip->client;
- unsigned char buf[bytes + 1];
- int ret;
-
- buf[0] = (unsigned char)reg;
- memcpy(&buf[1], src, bytes);
-
- ret = i2c_master_send(i2c, buf, bytes + 1);
- if (ret < 0)
- return ret;
- return 0;
-}
-
-int pm8607_reg_read(struct pm8607_chip *chip, int reg)
-{
- unsigned char data;
- int ret;
-
- mutex_lock(&chip->io_lock);
- ret = chip->read(chip, reg, 1, &data);
- mutex_unlock(&chip->io_lock);
-
- if (ret < 0)
- return ret;
- else
- return (int)data;
-}
-EXPORT_SYMBOL(pm8607_reg_read);
-
-int pm8607_reg_write(struct pm8607_chip *chip, int reg,
- unsigned char data)
-{
- int ret;
-
- mutex_lock(&chip->io_lock);
- ret = chip->write(chip, reg, 1, &data);
- mutex_unlock(&chip->io_lock);
-
- return ret;
-}
-EXPORT_SYMBOL(pm8607_reg_write);
-
-int pm8607_bulk_read(struct pm8607_chip *chip, int reg,
- int count, unsigned char *buf)
-{
- int ret;
-
- mutex_lock(&chip->io_lock);
- ret = chip->read(chip, reg, count, buf);
- mutex_unlock(&chip->io_lock);
-
- return ret;
-}
-EXPORT_SYMBOL(pm8607_bulk_read);
-
-int pm8607_bulk_write(struct pm8607_chip *chip, int reg,
- int count, unsigned char *buf)
-{
- int ret;
-
- mutex_lock(&chip->io_lock);
- ret = chip->write(chip, reg, count, buf);
- mutex_unlock(&chip->io_lock);
-
- return ret;
-}
-EXPORT_SYMBOL(pm8607_bulk_write);
-
-int pm8607_set_bits(struct pm8607_chip *chip, int reg,
- unsigned char mask, unsigned char data)
-{
- unsigned char value;
- int ret;
-
- mutex_lock(&chip->io_lock);
- ret = chip->read(chip, reg, 1, &value);
- if (ret < 0)
- goto out;
- value &= ~mask;
- value |= data;
- ret = chip->write(chip, reg, 1, &value);
-out:
- mutex_unlock(&chip->io_lock);
- return ret;
-}
-EXPORT_SYMBOL(pm8607_set_bits);
-
-
-static const struct i2c_device_id pm8607_id_table[] = {
- { "88PM8607", 0 },
- {}
-};
-MODULE_DEVICE_TABLE(i2c, pm8607_id_table);
-
-
-static int __devinit pm8607_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct pm8607_platform_data *pdata = client->dev.platform_data;
- struct pm8607_chip *chip;
- int i, count;
- int ret;
-
- chip = kzalloc(sizeof(struct pm8607_chip), GFP_KERNEL);
- if (chip == NULL)
- return -ENOMEM;
-
- chip->client = client;
- chip->dev = &client->dev;
- chip->read = pm8607_read_device;
- chip->write = pm8607_write_device;
- i2c_set_clientdata(client, chip);
-
- mutex_init(&chip->io_lock);
- dev_set_drvdata(chip->dev, chip);
-
- ret = pm8607_reg_read(chip, PM8607_CHIP_ID);
- if (ret < 0) {
- dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret);
- goto out;
- }
- if ((ret & CHIP_ID_MASK) == CHIP_ID)
- dev_info(chip->dev, "Marvell 88PM8607 (ID: %02x) detected\n",
- ret);
- else {
- dev_err(chip->dev, "Failed to detect Marvell 88PM8607. "
- "Chip ID: %02x\n", ret);
- goto out;
- }
- chip->chip_id = ret;
-
- ret = pm8607_reg_read(chip, PM8607_BUCK3);
- if (ret < 0) {
- dev_err(chip->dev, "Failed to read BUCK3 register: %d\n", ret);
- goto out;
- }
- if (ret & PM8607_BUCK3_DOUBLE)
- chip->buck3_double = 1;
-
- ret = pm8607_reg_read(chip, PM8607_MISC1);
- if (ret < 0) {
- dev_err(chip->dev, "Failed to read MISC1 register: %d\n", ret);
- goto out;
- }
- if (pdata->i2c_port == PI2C_PORT)
- ret |= PM8607_MISC1_PI2C;
- else
- ret &= ~PM8607_MISC1_PI2C;
- ret = pm8607_reg_write(chip, PM8607_MISC1, ret);
- if (ret < 0) {
- dev_err(chip->dev, "Failed to write MISC1 register: %d\n", ret);
- goto out;
- }
-
-
- count = ARRAY_SIZE(pm8607_devs);
- for (i = 0; i < count; i++) {
- ret = mfd_add_devices(chip->dev, i, &pm8607_devs[i],
- 1, NULL, 0);
- if (ret != 0) {
- dev_err(chip->dev, "Failed to add subdevs\n");
- goto out;
- }
- }
-
- return 0;
-
-out:
- i2c_set_clientdata(client, NULL);
- kfree(chip);
- return ret;
-}
-
-static int __devexit pm8607_remove(struct i2c_client *client)
-{
- struct pm8607_chip *chip = i2c_get_clientdata(client);
-
- mfd_remove_devices(chip->dev);
- kfree(chip);
- return 0;
-}
-
-static struct i2c_driver pm8607_driver = {
- .driver = {
- .name = "88PM8607",
- .owner = THIS_MODULE,
- },
- .probe = pm8607_probe,
- .remove = __devexit_p(pm8607_remove),
- .id_table = pm8607_id_table,
-};
-
-static int __init pm8607_init(void)
-{
- int ret;
- ret = i2c_add_driver(&pm8607_driver);
- if (ret != 0)
- pr_err("Failed to register 88PM8607 I2C driver: %d\n", ret);
- return ret;
-}
-subsys_initcall(pm8607_init);
-
-static void __exit pm8607_exit(void)
-{
- i2c_del_driver(&pm8607_driver);
-}
-module_exit(pm8607_exit);
-
-MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM8607");
-MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/88pm860x-core.c b/drivers/mfd/88pm860x-core.c
new file mode 100644
index 00000000000..6a14d2b1ccf
--- /dev/null
+++ b/drivers/mfd/88pm860x-core.c
@@ -0,0 +1,740 @@
+/*
+ * Base driver for Marvell 88PM8607
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ * Haojian Zhuang <haojian.zhuang@marvell.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/i2c.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/88pm860x.h>
+
+#define INT_STATUS_NUM 3
+
+char pm860x_backlight_name[][MFD_NAME_SIZE] = {
+ "backlight-0",
+ "backlight-1",
+ "backlight-2",
+};
+EXPORT_SYMBOL(pm860x_backlight_name);
+
+char pm860x_led_name[][MFD_NAME_SIZE] = {
+ "led0-red",
+ "led0-green",
+ "led0-blue",
+ "led1-red",
+ "led1-green",
+ "led1-blue",
+};
+EXPORT_SYMBOL(pm860x_led_name);
+
+#define PM8606_BACKLIGHT_RESOURCE(_i, _x) \
+{ \
+ .name = pm860x_backlight_name[_i], \
+ .start = PM8606_##_x, \
+ .end = PM8606_##_x, \
+ .flags = IORESOURCE_IO, \
+}
+
+static struct resource backlight_resources[] = {
+ PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT1, WLED1A),
+ PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT2, WLED2A),
+ PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT3, WLED3A),
+};
+
+#define PM8606_BACKLIGHT_DEVS(_i) \
+{ \
+ .name = "88pm860x-backlight", \
+ .num_resources = 1, \
+ .resources = &backlight_resources[_i], \
+ .id = _i, \
+}
+
+static struct mfd_cell backlight_devs[] = {
+ PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT1),
+ PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT2),
+ PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT3),
+};
+
+#define PM8606_LED_RESOURCE(_i, _x) \
+{ \
+ .name = pm860x_led_name[_i], \
+ .start = PM8606_##_x, \
+ .end = PM8606_##_x, \
+ .flags = IORESOURCE_IO, \
+}
+
+static struct resource led_resources[] = {
+ PM8606_LED_RESOURCE(PM8606_LED1_RED, RGB2B),
+ PM8606_LED_RESOURCE(PM8606_LED1_GREEN, RGB2C),
+ PM8606_LED_RESOURCE(PM8606_LED1_BLUE, RGB2D),
+ PM8606_LED_RESOURCE(PM8606_LED2_RED, RGB1B),
+ PM8606_LED_RESOURCE(PM8606_LED2_GREEN, RGB1C),
+ PM8606_LED_RESOURCE(PM8606_LED2_BLUE, RGB1D),
+};
+
+#define PM8606_LED_DEVS(_i) \
+{ \
+ .name = "88pm860x-led", \
+ .num_resources = 1, \
+ .resources = &led_resources[_i], \
+ .id = _i, \
+}
+
+static struct mfd_cell led_devs[] = {
+ PM8606_LED_DEVS(PM8606_LED1_RED),
+ PM8606_LED_DEVS(PM8606_LED1_GREEN),
+ PM8606_LED_DEVS(PM8606_LED1_BLUE),
+ PM8606_LED_DEVS(PM8606_LED2_RED),
+ PM8606_LED_DEVS(PM8606_LED2_GREEN),
+ PM8606_LED_DEVS(PM8606_LED2_BLUE),
+};
+
+static struct resource touch_resources[] = {
+ {
+ .start = PM8607_IRQ_PEN,
+ .end = PM8607_IRQ_PEN,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mfd_cell touch_devs[] = {
+ {
+ .name = "88pm860x-touch",
+ .num_resources = 1,
+ .resources = &touch_resources[0],
+ },
+};
+
+#define PM8607_REG_RESOURCE(_start, _end) \
+{ \
+ .start = PM8607_##_start, \
+ .end = PM8607_##_end, \
+ .flags = IORESOURCE_IO, \
+}
+
+static struct resource power_supply_resources[] = {
+ {
+ .name = "88pm860x-power",
+ .start = PM8607_IRQ_CHG,
+ .end = PM8607_IRQ_CHG,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mfd_cell power_devs[] = {
+ {
+ .name = "88pm860x-power",
+ .num_resources = 1,
+ .resources = &power_supply_resources[0],
+ .id = -1,
+ },
+};
+
+static struct resource onkey_resources[] = {
+ {
+ .name = "88pm860x-onkey",
+ .start = PM8607_IRQ_ONKEY,
+ .end = PM8607_IRQ_ONKEY,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct mfd_cell onkey_devs[] = {
+ {
+ .name = "88pm860x-onkey",
+ .num_resources = 1,
+ .resources = &onkey_resources[0],
+ .id = -1,
+ },
+};
+
+static struct resource regulator_resources[] = {
+ PM8607_REG_RESOURCE(BUCK1, BUCK1),
+ PM8607_REG_RESOURCE(BUCK2, BUCK2),
+ PM8607_REG_RESOURCE(BUCK3, BUCK3),
+ PM8607_REG_RESOURCE(LDO1, LDO1),
+ PM8607_REG_RESOURCE(LDO2, LDO2),
+ PM8607_REG_RESOURCE(LDO3, LDO3),
+ PM8607_REG_RESOURCE(LDO4, LDO4),
+ PM8607_REG_RESOURCE(LDO5, LDO5),
+ PM8607_REG_RESOURCE(LDO6, LDO6),
+ PM8607_REG_RESOURCE(LDO7, LDO7),
+ PM8607_REG_RESOURCE(LDO8, LDO8),
+ PM8607_REG_RESOURCE(LDO9, LDO9),
+ PM8607_REG_RESOURCE(LDO10, LDO10),
+ PM8607_REG_RESOURCE(LDO12, LDO12),
+ PM8607_REG_RESOURCE(LDO14, LDO14),
+};
+
+#define PM8607_REG_DEVS(_name, _id) \
+{ \
+ .name = "88pm8607-" #_name, \
+ .num_resources = 1, \
+ .resources = &regulator_resources[PM8607_ID_##_id], \
+ .id = PM8607_ID_##_id, \
+}
+
+static struct mfd_cell regulator_devs[] = {
+ PM8607_REG_DEVS(buck1, BUCK1),
+ PM8607_REG_DEVS(buck2, BUCK2),
+ PM8607_REG_DEVS(buck3, BUCK3),
+ PM8607_REG_DEVS(ldo1, LDO1),
+ PM8607_REG_DEVS(ldo2, LDO2),
+ PM8607_REG_DEVS(ldo3, LDO3),
+ PM8607_REG_DEVS(ldo4, LDO4),
+ PM8607_REG_DEVS(ldo5, LDO5),
+ PM8607_REG_DEVS(ldo6, LDO6),
+ PM8607_REG_DEVS(ldo7, LDO7),
+ PM8607_REG_DEVS(ldo8, LDO8),
+ PM8607_REG_DEVS(ldo9, LDO9),
+ PM8607_REG_DEVS(ldo10, LDO10),
+ PM8607_REG_DEVS(ldo12, LDO12),
+ PM8607_REG_DEVS(ldo14, LDO14),
+};
+
+struct pm860x_irq_data {
+ int reg;
+ int mask_reg;
+ int enable; /* enable or not */
+ int offs; /* bit offset in mask register */
+};
+
+static struct pm860x_irq_data pm860x_irqs[] = {
+ [PM8607_IRQ_ONKEY] = {
+ .reg = PM8607_INT_STATUS1,
+ .mask_reg = PM8607_INT_MASK_1,
+ .offs = 1 << 0,
+ },
+ [PM8607_IRQ_EXTON] = {
+ .reg = PM8607_INT_STATUS1,
+ .mask_reg = PM8607_INT_MASK_1,
+ .offs = 1 << 1,
+ },
+ [PM8607_IRQ_CHG] = {
+ .reg = PM8607_INT_STATUS1,
+ .mask_reg = PM8607_INT_MASK_1,
+ .offs = 1 << 2,
+ },
+ [PM8607_IRQ_BAT] = {
+ .reg = PM8607_INT_STATUS1,
+ .mask_reg = PM8607_INT_MASK_1,
+ .offs = 1 << 3,
+ },
+ [PM8607_IRQ_RTC] = {
+ .reg = PM8607_INT_STATUS1,
+ .mask_reg = PM8607_INT_MASK_1,
+ .offs = 1 << 4,
+ },
+ [PM8607_IRQ_CC] = {
+ .reg = PM8607_INT_STATUS1,
+ .mask_reg = PM8607_INT_MASK_1,
+ .offs = 1 << 5,
+ },
+ [PM8607_IRQ_VBAT] = {
+ .reg = PM8607_INT_STATUS2,
+ .mask_reg = PM8607_INT_MASK_2,
+ .offs = 1 << 0,
+ },
+ [PM8607_IRQ_VCHG] = {
+ .reg = PM8607_INT_STATUS2,
+ .mask_reg = PM8607_INT_MASK_2,
+ .offs = 1 << 1,
+ },
+ [PM8607_IRQ_VSYS] = {
+ .reg = PM8607_INT_STATUS2,
+ .mask_reg = PM8607_INT_MASK_2,
+ .offs = 1 << 2,
+ },
+ [PM8607_IRQ_TINT] = {
+ .reg = PM8607_INT_STATUS2,
+ .mask_reg = PM8607_INT_MASK_2,
+ .offs = 1 << 3,
+ },
+ [PM8607_IRQ_GPADC0] = {
+ .reg = PM8607_INT_STATUS2,
+ .mask_reg = PM8607_INT_MASK_2,
+ .offs = 1 << 4,
+ },
+ [PM8607_IRQ_GPADC1] = {
+ .reg = PM8607_INT_STATUS2,
+ .mask_reg = PM8607_INT_MASK_2,
+ .offs = 1 << 5,
+ },
+ [PM8607_IRQ_GPADC2] = {
+ .reg = PM8607_INT_STATUS2,
+ .mask_reg = PM8607_INT_MASK_2,
+ .offs = 1 << 6,
+ },
+ [PM8607_IRQ_GPADC3] = {
+ .reg = PM8607_INT_STATUS2,
+ .mask_reg = PM8607_INT_MASK_2,
+ .offs = 1 << 7,
+ },
+ [PM8607_IRQ_AUDIO_SHORT] = {
+ .reg = PM8607_INT_STATUS3,
+ .mask_reg = PM8607_INT_MASK_3,
+ .offs = 1 << 0,
+ },
+ [PM8607_IRQ_PEN] = {
+ .reg = PM8607_INT_STATUS3,
+ .mask_reg = PM8607_INT_MASK_3,
+ .offs = 1 << 1,
+ },
+ [PM8607_IRQ_HEADSET] = {
+ .reg = PM8607_INT_STATUS3,
+ .mask_reg = PM8607_INT_MASK_3,
+ .offs = 1 << 2,
+ },
+ [PM8607_IRQ_HOOK] = {
+ .reg = PM8607_INT_STATUS3,
+ .mask_reg = PM8607_INT_MASK_3,
+ .offs = 1 << 3,
+ },
+ [PM8607_IRQ_MICIN] = {
+ .reg = PM8607_INT_STATUS3,
+ .mask_reg = PM8607_INT_MASK_3,
+ .offs = 1 << 4,
+ },
+ [PM8607_IRQ_CHG_FAIL] = {
+ .reg = PM8607_INT_STATUS3,
+ .mask_reg = PM8607_INT_MASK_3,
+ .offs = 1 << 5,
+ },
+ [PM8607_IRQ_CHG_DONE] = {
+ .reg = PM8607_INT_STATUS3,
+ .mask_reg = PM8607_INT_MASK_3,
+ .offs = 1 << 6,
+ },
+ [PM8607_IRQ_CHG_FAULT] = {
+ .reg = PM8607_INT_STATUS3,
+ .mask_reg = PM8607_INT_MASK_3,
+ .offs = 1 << 7,
+ },
+};
+
+static inline struct pm860x_irq_data *irq_to_pm860x(struct pm860x_chip *chip,
+ int irq)
+{
+ return &pm860x_irqs[irq - chip->irq_base];
+}
+
+static irqreturn_t pm860x_irq(int irq, void *data)
+{
+ struct pm860x_chip *chip = data;
+ struct pm860x_irq_data *irq_data;
+ struct i2c_client *i2c;
+ int read_reg = -1, value = 0;
+ int i;
+
+ i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
+ for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
+ irq_data = &pm860x_irqs[i];
+ if (read_reg != irq_data->reg) {
+ read_reg = irq_data->reg;
+ value = pm860x_reg_read(i2c, irq_data->reg);
+ }
+ if (value & irq_data->enable)
+ handle_nested_irq(chip->irq_base + i);
+ }
+ return IRQ_HANDLED;
+}
+
+static void pm860x_irq_lock(unsigned int irq)
+{
+ struct pm860x_chip *chip = get_irq_chip_data(irq);
+
+ mutex_lock(&chip->irq_lock);
+}
+
+static void pm860x_irq_sync_unlock(unsigned int irq)
+{
+ struct pm860x_chip *chip = get_irq_chip_data(irq);
+ struct pm860x_irq_data *irq_data;
+ struct i2c_client *i2c;
+ static unsigned char cached[3] = {0x0, 0x0, 0x0};
+ unsigned char mask[3];
+ int i;
+
+ i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
+ /* Load cached value. In initial, all IRQs are masked */
+ for (i = 0; i < 3; i++)
+ mask[i] = cached[i];
+ for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
+ irq_data = &pm860x_irqs[i];
+ switch (irq_data->mask_reg) {
+ case PM8607_INT_MASK_1:
+ mask[0] &= ~irq_data->offs;
+ mask[0] |= irq_data->enable;
+ break;
+ case PM8607_INT_MASK_2:
+ mask[1] &= ~irq_data->offs;
+ mask[1] |= irq_data->enable;
+ break;
+ case PM8607_INT_MASK_3:
+ mask[2] &= ~irq_data->offs;
+ mask[2] |= irq_data->enable;
+ break;
+ default:
+ dev_err(chip->dev, "wrong IRQ\n");
+ break;
+ }
+ }
+ /* update mask into registers */
+ for (i = 0; i < 3; i++) {
+ if (mask[i] != cached[i]) {
+ cached[i] = mask[i];
+ pm860x_reg_write(i2c, PM8607_INT_MASK_1 + i, mask[i]);
+ }
+ }
+
+ mutex_unlock(&chip->irq_lock);
+}
+
+static void pm860x_irq_enable(unsigned int irq)
+{
+ struct pm860x_chip *chip = get_irq_chip_data(irq);
+ pm860x_irqs[irq - chip->irq_base].enable
+ = pm860x_irqs[irq - chip->irq_base].offs;
+}
+
+static void pm860x_irq_disable(unsigned int irq)
+{
+ struct pm860x_chip *chip = get_irq_chip_data(irq);
+ pm860x_irqs[irq - chip->irq_base].enable = 0;
+}
+
+static struct irq_chip pm860x_irq_chip = {
+ .name = "88pm860x",
+ .bus_lock = pm860x_irq_lock,
+ .bus_sync_unlock = pm860x_irq_sync_unlock,
+ .enable = pm860x_irq_enable,
+ .disable = pm860x_irq_disable,
+};
+
+static int __devinit device_gpadc_init(struct pm860x_chip *chip,
+ struct pm860x_platform_data *pdata)
+{
+ struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
+ : chip->companion;
+ int use_gpadc = 0, data, ret;
+
+ /* initialize GPADC without activating it */
+
+ if (pdata && pdata->touch) {
+ /* set GPADC MISC1 register */
+ data = 0;
+ data |= (pdata->touch->gpadc_prebias << 1)
+ & PM8607_GPADC_PREBIAS_MASK;
+ data |= (pdata->touch->slot_cycle << 3)
+ & PM8607_GPADC_SLOT_CYCLE_MASK;
+ data |= (pdata->touch->off_scale << 5)
+ & PM8607_GPADC_OFF_SCALE_MASK;
+ data |= (pdata->touch->sw_cal << 7)
+ & PM8607_GPADC_SW_CAL_MASK;
+ if (data) {
+ ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data);
+ if (ret < 0)
+ goto out;
+ }
+ /* set tsi prebias time */
+ if (pdata->touch->tsi_prebias) {
+ data = pdata->touch->tsi_prebias;
+ ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data);
+ if (ret < 0)
+ goto out;
+ }
+ /* set prebias & prechg time of pen detect */
+ data = 0;
+ data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK;
+ data |= (pdata->touch->pen_prechg << 5)
+ & PM8607_PD_PRECHG_MASK;
+ if (data) {
+ ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data);
+ if (ret < 0)
+ goto out;
+ }
+
+ use_gpadc = 1;
+ }
+
+ /* turn on GPADC */
+ if (use_gpadc) {
+ ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1,
+ PM8607_GPADC_EN, PM8607_GPADC_EN);
+ }
+out:
+ return ret;
+}
+
+static int __devinit device_irq_init(struct pm860x_chip *chip,
+ struct pm860x_platform_data *pdata)
+{
+ struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \
+ : chip->companion;
+ unsigned char status_buf[INT_STATUS_NUM];
+ unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
+ struct irq_desc *desc;
+ int i, data, mask, ret = -EINVAL;
+ int __irq;
+
+ if (!pdata || !pdata->irq_base) {
+ dev_warn(chip->dev, "No interrupt support on IRQ base\n");
+ return -EINVAL;
+ }
+
+ mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR
+ | PM8607_B0_MISC1_INT_MASK;
+ data = 0;
+ chip->irq_mode = 0;
+ if (pdata && pdata->irq_mode) {
+ /*
+ * irq_mode defines the way of clearing interrupt. If it's 1,
+ * clear IRQ by write. Otherwise, clear it by read.
+ * This control bit is valid from 88PM8607 B0 steping.
+ */
+ data |= PM8607_B0_MISC1_INT_CLEAR;
+ chip->irq_mode = 1;
+ }
+ ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, mask, data);
+ if (ret < 0)
+ goto out;
+
+ /* mask all IRQs */
+ memset(status_buf, 0, INT_STATUS_NUM);
+ ret = pm860x_bulk_write(i2c, PM8607_INT_MASK_1,
+ INT_STATUS_NUM, status_buf);
+ if (ret < 0)
+ goto out;
+
+ if (chip->irq_mode) {
+ /* clear interrupt status by write */
+ memset(status_buf, 0xFF, INT_STATUS_NUM);
+ ret = pm860x_bulk_write(i2c, PM8607_INT_STATUS1,
+ INT_STATUS_NUM, status_buf);
+ } else {
+ /* clear interrupt status by read */
+ ret = pm860x_bulk_read(i2c, PM8607_INT_STATUS1,
+ INT_STATUS_NUM, status_buf);
+ }
+ if (ret < 0)
+ goto out;
+
+ mutex_init(&chip->irq_lock);
+ chip->irq_base = pdata->irq_base;
+ chip->core_irq = i2c->irq;
+ if (!chip->core_irq)
+ goto out;
+
+ desc = irq_to_desc(chip->core_irq);
+
+ /* register IRQ by genirq */
+ for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
+ __irq = i + chip->irq_base;
+ set_irq_chip_data(__irq, chip);
+ set_irq_chip_and_handler(__irq, &pm860x_irq_chip,
+ handle_edge_irq);
+ set_irq_nested_thread(__irq, 1);
+#ifdef CONFIG_ARM
+ set_irq_flags(__irq, IRQF_VALID);
+#else
+ set_irq_noprobe(__irq);
+#endif
+ }
+
+ ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags,
+ "88pm860x", chip);
+ if (ret) {
+ dev_err(chip->dev, "Failed to request IRQ: %d\n", ret);
+ chip->core_irq = 0;
+ }
+
+ return 0;
+out:
+ chip->core_irq = 0;
+ return ret;
+}
+
+static void __devexit device_irq_exit(struct pm860x_chip *chip)
+{
+ if (chip->core_irq)
+ free_irq(chip->core_irq, chip);
+}
+
+static void __devinit device_8606_init(struct pm860x_chip *chip,
+ struct i2c_client *i2c,
+ struct pm860x_platform_data *pdata)
+{
+ int ret;
+
+ if (pdata && pdata->backlight) {
+ ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0],
+ ARRAY_SIZE(backlight_devs),
+ &backlight_resources[0], 0);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to add backlight "
+ "subdev\n");
+ goto out_dev;
+ }
+ }
+
+ if (pdata && pdata->led) {
+ ret = mfd_add_devices(chip->dev, 0, &led_devs[0],
+ ARRAY_SIZE(led_devs),
+ &led_resources[0], 0);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to add led "
+ "subdev\n");
+ goto out_dev;
+ }
+ }
+ return;
+out_dev:
+ mfd_remove_devices(chip->dev);
+ device_irq_exit(chip);
+}
+
+static void __devinit device_8607_init(struct pm860x_chip *chip,
+ struct i2c_client *i2c,
+ struct pm860x_platform_data *pdata)
+{
+ int data, ret;
+
+ ret = pm860x_reg_read(i2c, PM8607_CHIP_ID);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret);
+ goto out;
+ }
+ if ((ret & PM8607_VERSION_MASK) == PM8607_VERSION)
+ dev_info(chip->dev, "Marvell 88PM8607 (ID: %02x) detected\n",
+ ret);
+ else {
+ dev_err(chip->dev, "Failed to detect Marvell 88PM8607. "
+ "Chip ID: %02x\n", ret);
+ goto out;
+ }
+
+ ret = pm860x_reg_read(i2c, PM8607_BUCK3);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to read BUCK3 register: %d\n", ret);
+ goto out;
+ }
+ if (ret & PM8607_BUCK3_DOUBLE)
+ chip->buck3_double = 1;
+
+ ret = pm860x_reg_read(i2c, PM8607_B0_MISC1);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to read MISC1 register: %d\n", ret);
+ goto out;
+ }
+
+ if (pdata && (pdata->i2c_port == PI2C_PORT))
+ data = PM8607_B0_MISC1_PI2C;
+ else
+ data = 0;
+ ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, PM8607_B0_MISC1_PI2C, data);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to access MISC1:%d\n", ret);
+ goto out;
+ }
+
+ ret = device_gpadc_init(chip, pdata);
+ if (ret < 0)
+ goto out;
+
+ ret = device_irq_init(chip, pdata);
+ if (ret < 0)
+ goto out;
+
+ ret = mfd_add_devices(chip->dev, 0, &regulator_devs[0],
+ ARRAY_SIZE(regulator_devs),
+ &regulator_resources[0], 0);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to add regulator subdev\n");
+ goto out_dev;
+ }
+
+ if (pdata && pdata->touch) {
+ ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
+ ARRAY_SIZE(touch_devs),
+ &touch_resources[0], 0);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to add touch "
+ "subdev\n");
+ goto out_dev;
+ }
+ }
+
+ if (pdata && pdata->power) {
+ ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
+ ARRAY_SIZE(power_devs),
+ &power_supply_resources[0], 0);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to add power supply "
+ "subdev\n");
+ goto out_dev;
+ }
+ }
+
+ ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],
+ ARRAY_SIZE(onkey_devs),
+ &onkey_resources[0], 0);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to add onkey subdev\n");
+ goto out_dev;
+ }
+
+ return;
+out_dev:
+ mfd_remove_devices(chip->dev);
+ device_irq_exit(chip);
+out:
+ return;
+}
+
+int pm860x_device_init(struct pm860x_chip *chip,
+ struct pm860x_platform_data *pdata)
+{
+ chip->core_irq = 0;
+
+ switch (chip->id) {
+ case CHIP_PM8606:
+ device_8606_init(chip, chip->client, pdata);
+ break;
+ case CHIP_PM8607:
+ device_8607_init(chip, chip->client, pdata);
+ break;
+ }
+
+ if (chip->companion) {
+ switch (chip->id) {
+ case CHIP_PM8607:
+ device_8606_init(chip, chip->companion, pdata);
+ break;
+ case CHIP_PM8606:
+ device_8607_init(chip, chip->companion, pdata);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+void pm860x_device_exit(struct pm860x_chip *chip)
+{
+ device_irq_exit(chip);
+ mfd_remove_devices(chip->dev);
+}
+
+MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/88pm860x-i2c.c b/drivers/mfd/88pm860x-i2c.c
new file mode 100644
index 00000000000..c37e12bf300
--- /dev/null
+++ b/drivers/mfd/88pm860x-i2c.c
@@ -0,0 +1,236 @@
+/*
+ * I2C driver for Marvell 88PM860x
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ * Haojian Zhuang <haojian.zhuang@marvell.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/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/mfd/88pm860x.h>
+
+static inline int pm860x_read_device(struct i2c_client *i2c,
+ int reg, int bytes, void *dest)
+{
+ unsigned char data;
+ int ret;
+
+ data = (unsigned char)reg;
+ ret = i2c_master_send(i2c, &data, 1);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_master_recv(i2c, dest, bytes);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+static inline int pm860x_write_device(struct i2c_client *i2c,
+ int reg, int bytes, void *src)
+{
+ unsigned char buf[bytes + 1];
+ int ret;
+
+ buf[0] = (unsigned char)reg;
+ memcpy(&buf[1], src, bytes);
+
+ ret = i2c_master_send(i2c, buf, bytes + 1);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+int pm860x_reg_read(struct i2c_client *i2c, int reg)
+{
+ struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+ unsigned char data;
+ int ret;
+
+ mutex_lock(&chip->io_lock);
+ ret = pm860x_read_device(i2c, reg, 1, &data);
+ mutex_unlock(&chip->io_lock);
+
+ if (ret < 0)
+ return ret;
+ else
+ return (int)data;
+}
+EXPORT_SYMBOL(pm860x_reg_read);
+
+int pm860x_reg_write(struct i2c_client *i2c, int reg,
+ unsigned char data)
+{
+ struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+ int ret;
+
+ mutex_lock(&chip->io_lock);
+ ret = pm860x_write_device(i2c, reg, 1, &data);
+ mutex_unlock(&chip->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(pm860x_reg_write);
+
+int pm860x_bulk_read(struct i2c_client *i2c, int reg,
+ int count, unsigned char *buf)
+{
+ struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+ int ret;
+
+ mutex_lock(&chip->io_lock);
+ ret = pm860x_read_device(i2c, reg, count, buf);
+ mutex_unlock(&chip->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(pm860x_bulk_read);
+
+int pm860x_bulk_write(struct i2c_client *i2c, int reg,
+ int count, unsigned char *buf)
+{
+ struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+ int ret;
+
+ mutex_lock(&chip->io_lock);
+ ret = pm860x_write_device(i2c, reg, count, buf);
+ mutex_unlock(&chip->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(pm860x_bulk_write);
+
+int pm860x_set_bits(struct i2c_client *i2c, int reg,
+ unsigned char mask, unsigned char data)
+{
+ struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+ unsigned char value;
+ int ret;
+
+ mutex_lock(&chip->io_lock);
+ ret = pm860x_read_device(i2c, reg, 1, &value);
+ if (ret < 0)
+ goto out;
+ value &= ~mask;
+ value |= data;
+ ret = pm860x_write_device(i2c, reg, 1, &value);
+out:
+ mutex_unlock(&chip->io_lock);
+ return ret;
+}
+EXPORT_SYMBOL(pm860x_set_bits);
+
+
+static const struct i2c_device_id pm860x_id_table[] = {
+ { "88PM860x", 0 },
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, pm860x_id_table);
+
+static int verify_addr(struct i2c_client *i2c)
+{
+ unsigned short addr_8607[] = {0x30, 0x34};
+ unsigned short addr_8606[] = {0x10, 0x11};
+ int size, i;
+
+ if (i2c == NULL)
+ return 0;
+ size = ARRAY_SIZE(addr_8606);
+ for (i = 0; i < size; i++) {
+ if (i2c->addr == *(addr_8606 + i))
+ return CHIP_PM8606;
+ }
+ size = ARRAY_SIZE(addr_8607);
+ for (i = 0; i < size; i++) {
+ if (i2c->addr == *(addr_8607 + i))
+ return CHIP_PM8607;
+ }
+ return 0;
+}
+
+static int __devinit pm860x_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct pm860x_platform_data *pdata = client->dev.platform_data;
+ struct pm860x_chip *chip;
+
+ if (!pdata) {
+ pr_info("No platform data in %s!\n", __func__);
+ return -EINVAL;
+ }
+
+ chip = kzalloc(sizeof(struct pm860x_chip), GFP_KERNEL);
+ if (chip == NULL)
+ return -ENOMEM;
+
+ chip->id = verify_addr(client);
+ chip->client = client;
+ i2c_set_clientdata(client, chip);
+ chip->dev = &client->dev;
+ mutex_init(&chip->io_lock);
+ dev_set_drvdata(chip->dev, chip);
+
+ /*
+ * Both client and companion client shares same platform driver.
+ * Driver distinguishes them by pdata->companion_addr.
+ * pdata->companion_addr is only assigned if companion chip exists.
+ * At the same time, the companion_addr shouldn't equal to client
+ * address.
+ */
+ if (pdata->companion_addr && (pdata->companion_addr != client->addr)) {
+ chip->companion_addr = pdata->companion_addr;
+ chip->companion = i2c_new_dummy(chip->client->adapter,
+ chip->companion_addr);
+ i2c_set_clientdata(chip->companion, chip);
+ }
+
+ pm860x_device_init(chip, pdata);
+ return 0;
+}
+
+static int __devexit pm860x_remove(struct i2c_client *client)
+{
+ struct pm860x_chip *chip = i2c_get_clientdata(client);
+
+ pm860x_device_exit(chip);
+ i2c_unregister_device(chip->companion);
+ i2c_set_clientdata(chip->companion, NULL);
+ i2c_set_clientdata(chip->client, NULL);
+ kfree(chip);
+ return 0;
+}
+
+static struct i2c_driver pm860x_driver = {
+ .driver = {
+ .name = "88PM860x",
+ .owner = THIS_MODULE,
+ },
+ .probe = pm860x_probe,
+ .remove = __devexit_p(pm860x_remove),
+ .id_table = pm860x_id_table,
+};
+
+static int __init pm860x_i2c_init(void)
+{
+ int ret;
+ ret = i2c_add_driver(&pm860x_driver);
+ if (ret != 0)
+ pr_err("Failed to register 88PM860x I2C driver: %d\n", ret);
+ return ret;
+}
+subsys_initcall(pm860x_i2c_init);
+
+static void __exit pm860x_i2c_exit(void)
+{
+ i2c_del_driver(&pm860x_driver);
+}
+module_exit(pm860x_i2c_exit);
+
+MODULE_DESCRIPTION("I2C Driver for Marvell 88PM860x");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index b670d10d5c9..951fa9b93fb 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -9,6 +9,16 @@ config MFD_CORE
tristate
default n
+config MFD_88PM860X
+ bool "Support Marvell 88PM8606/88PM8607"
+ depends on I2C=y
+ select MFD_CORE
+ help
+ This supports for Marvell 88PM8606/88PM8607 Power Management IC.
+ This includes the I2C driver and the core APIs _only_, you have to
+ select individual components like voltage regulators, RTC and
+ battery-charger under the corresponding menus.
+
config MFD_SM501
tristate "Support for Silicon Motion SM501"
---help---
@@ -37,7 +47,7 @@ config MFD_ASIC3
config MFD_SH_MOBILE_SDHI
bool "Support for SuperH Mobile SDHI"
- depends on SUPERH
+ depends on SUPERH || ARCH_SHMOBILE
select MFD_CORE
---help---
This driver supports the SDHI hardware block found in many
@@ -68,6 +78,15 @@ config HTC_PASIC3
HTC Magician devices, respectively. Actual functionality is
handled by the leds-pasic3 and ds1wm drivers.
+config HTC_I2CPLD
+ bool "HTC I2C PLD chip support"
+ depends on I2C=y && GPIOLIB
+ help
+ If you say yes here you get support for the supposed CPLD
+ found on omap850 HTC devices like the HTC Wizard and HTC Herald.
+ This device provides input and output GPIOs through an I2C
+ interface to one or more sub-chips.
+
config UCB1400_CORE
tristate "Philips UCB1400 Core driver"
depends on AC97_BUS
@@ -184,6 +203,16 @@ config PMIC_ADP5520
individual components like LCD backlight, LEDs, GPIOs and Kepad
under the corresponding menus.
+config MFD_MAX8925
+ bool "Maxim Semiconductor MAX8925 PMIC Support"
+ depends on I2C=y
+ select MFD_CORE
+ help
+ Say yes here to support for Maxim Semiconductor MAX8925. This is
+ a Power Management IC. This driver provies common support for
+ accessing the device, additional drivers must be enabled in order
+ to use the functionality of the device.
+
config MFD_WM8400
tristate "Support Wolfson Microelectronics WM8400"
select MFD_CORE
@@ -205,7 +234,7 @@ config MFD_WM831X
functionality of the device.
config MFD_WM8350
- tristate
+ bool
config MFD_WM8350_CONFIG_MODE_0
bool
@@ -256,9 +285,9 @@ config MFD_WM8352_CONFIG_MODE_3
depends on MFD_WM8350
config MFD_WM8350_I2C
- tristate "Support Wolfson Microelectronics WM8350 with I2C"
+ bool "Support Wolfson Microelectronics WM8350 with I2C"
select MFD_WM8350
- depends on I2C
+ depends on I2C=y
help
The WM8350 is an integrated audio and power management
subsystem with watchdog and RTC functionality for embedded
@@ -266,6 +295,18 @@ config MFD_WM8350_I2C
I2C as the control interface. Additional options must be
selected to enable support for the functionality of the chip.
+config MFD_WM8994
+ tristate "Support Wolfson Microelectronics WM8994"
+ select MFD_CORE
+ depends on I2C
+ help
+ The WM8994 is a highly integrated hi-fi CODEC designed for
+ smartphone applicatiosn. As well as audio functionality it
+ has on board GPIO and regulator functionality which is
+ supported via the relevant subsystems. This driver provides
+ core support for the WM8994, in order to use the actual
+ functionaltiy of the device other drivers must be enabled.
+
config MFD_PCF50633
tristate "Support for NXP PCF50633"
depends on I2C
@@ -300,8 +341,8 @@ config PCF50633_GPIO
the PCF50633 chip.
config AB3100_CORE
- tristate "ST-Ericsson AB3100 Mixed Signal Circuit core functions"
- depends on I2C
+ bool "ST-Ericsson AB3100 Mixed Signal Circuit core functions"
+ depends on I2C=y
default y if ARCH_U300
help
Select this to enable the AB3100 Mixed Signal IC core
@@ -329,16 +370,6 @@ config EZX_PCAP
This enables the PCAP ASIC present on EZX Phones. This is
needed for MMC, TouchScreen, Sound, USB, etc..
-config MFD_88PM8607
- bool "Support Marvell 88PM8607"
- depends on I2C=y
- select MFD_CORE
- help
- This supports for Marvell 88PM8607 Power Management IC. This includes
- the I2C driver and the core APIs _only_, you have to select
- individual components like voltage regulators, RTC and
- battery-charger under the corresponding menus.
-
config AB4500_CORE
tristate "ST-Ericsson's AB4500 Mixed Signal Power management chip"
depends on SPI
@@ -358,6 +389,15 @@ config MFD_TIMBERDALE
The timberdale FPGA can be found on the Intel Atom development board
for in-vehicle infontainment, called Russellville.
+
+config LPC_SCH
+ tristate "Intel SCH LPC"
+ depends on PCI
+ select MFD_CORE
+ help
+ LPC bridge function of the Intel SCH provides support for
+ System Management Bus and General Purpose I/O.
+
endmenu
menu "Multimedia Capabilities Port drivers"
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 78295d6a75f..22715add99a 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -2,12 +2,15 @@
# Makefile for multifunction miscellaneous devices
#
+88pm860x-objs := 88pm860x-core.o 88pm860x-i2c.o
+obj-$(CONFIG_MFD_88PM860X) += 88pm860x.o
obj-$(CONFIG_MFD_SM501) += sm501.o
obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o
obj-$(CONFIG_MFD_SH_MOBILE_SDHI) += sh_mobile_sdhi.o
obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
+obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o
obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
@@ -22,6 +25,7 @@ wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
wm8350-objs += wm8350-irq.o
obj-$(CONFIG_MFD_WM8350) += wm8350.o
obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o
+obj-$(CONFIG_MFD_WM8994) += wm8994-core.o
obj-$(CONFIG_TPS65010) += tps65010.o
obj-$(CONFIG_MENELAUS) += menelaus.o
@@ -47,6 +51,8 @@ endif
obj-$(CONFIG_UCB1400_CORE) += ucb1400_core.o
obj-$(CONFIG_PMIC_DA903X) += da903x.o
+max8925-objs := max8925-core.o max8925-i2c.o
+obj-$(CONFIG_MFD_MAX8925) += max8925.o
obj-$(CONFIG_MFD_PCF50633) += pcf50633-core.o
obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o
@@ -55,5 +61,5 @@ obj-$(CONFIG_AB3100_CORE) += ab3100-core.o
obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o
obj-$(CONFIG_AB4500_CORE) += ab4500-core.o
obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o
-obj-$(CONFIG_MFD_88PM8607) += 88pm8607.o
obj-$(CONFIG_PMIC_ADP5520) += adp5520.o
+obj-$(CONFIG_LPC_SCH) += lpc_sch.o \ No newline at end of file
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
index fd42a80e7bf..a2ce3b6af4a 100644
--- a/drivers/mfd/ab3100-core.c
+++ b/drivers/mfd/ab3100-core.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007-2009 ST-Ericsson
+ * Copyright (C) 2007-2010 ST-Ericsson
* License terms: GNU General Public License (GPL) version 2
* Low-level core for exclusive access to the AB3100 IC on the I2C bus
* and some basic chip-configuration.
@@ -14,6 +14,7 @@
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/interrupt.h>
+#include <linux/random.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/uaccess.h>
@@ -365,18 +366,23 @@ int ab3100_event_registers_startup_state_get(struct ab3100 *ab3100,
}
EXPORT_SYMBOL(ab3100_event_registers_startup_state_get);
-/* Interrupt handling worker */
-static void ab3100_work(struct work_struct *work)
+/*
+ * This is a threaded interrupt handler so we can make some
+ * I2C calls etc.
+ */
+static irqreturn_t ab3100_irq_handler(int irq, void *data)
{
- struct ab3100 *ab3100 = container_of(work, struct ab3100, work);
+ struct ab3100 *ab3100 = data;
u8 event_regs[3];
u32 fatevent;
int err;
+ add_interrupt_randomness(irq);
+
err = ab3100_get_register_page_interruptible(ab3100, AB3100_EVENTA1,
event_regs, 3);
if (err)
- goto err_event_wq;
+ goto err_event;
fatevent = (event_regs[0] << 16) |
(event_regs[1] << 8) |
@@ -398,29 +404,11 @@ static void ab3100_work(struct work_struct *work)
dev_dbg(ab3100->dev,
"IRQ Event: 0x%08x\n", fatevent);
- /* By now the IRQ should be acked and deasserted so enable it again */
- enable_irq(ab3100->i2c_client->irq);
- return;
+ return IRQ_HANDLED;
- err_event_wq:
+ err_event:
dev_dbg(ab3100->dev,
- "error in event workqueue\n");
- /* Enable the IRQ anyway, what choice do we have? */
- enable_irq(ab3100->i2c_client->irq);
- return;
-}
-
-static irqreturn_t ab3100_irq_handler(int irq, void *data)
-{
- struct ab3100 *ab3100 = data;
- /*
- * Disable the IRQ and dispatch a worker to handle the
- * event. Since the chip resides on I2C this is slow
- * stuff and we will re-enable the interrupts once th
- * worker has finished.
- */
- disable_irq_nosync(irq);
- schedule_work(&ab3100->work);
+ "error reading event status\n");
return IRQ_HANDLED;
}
@@ -735,10 +723,7 @@ static struct platform_device ab3100_##devname##_device = { \
.id = -1, \
}
-/*
- * This lists all the subdevices and corresponding register
- * ranges.
- */
+/* This lists all the subdevices */
AB3100_DEVICE(dac, "ab3100-dac");
AB3100_DEVICE(leds, "ab3100-leds");
AB3100_DEVICE(power, "ab3100-power");
@@ -904,12 +889,11 @@ static int __init ab3100_probe(struct i2c_client *client,
if (err)
goto exit_no_setup;
- INIT_WORK(&ab3100->work, ab3100_work);
-
+ err = request_threaded_irq(client->irq, NULL, ab3100_irq_handler,
+ IRQF_ONESHOT, "ab3100-core", ab3100);
/* This real unpredictable IRQ is of course sampled for entropy */
- err = request_irq(client->irq, ab3100_irq_handler,
- IRQF_DISABLED | IRQF_SAMPLE_RANDOM,
- "AB3100 IRQ", ab3100);
+ rand_initialize_irq(client->irq);
+
if (err)
goto exit_no_irq;
diff --git a/drivers/mfd/ab3100-otp.c b/drivers/mfd/ab3100-otp.c
index 0499b2031a2..b603469dff6 100644
--- a/drivers/mfd/ab3100-otp.c
+++ b/drivers/mfd/ab3100-otp.c
@@ -13,6 +13,7 @@
#include <linux/platform_device.h>
#include <linux/mfd/ab3100.h>
#include <linux/debugfs.h>
+#include <linux/seq_file.h>
/* The OTP registers */
#define AB3100_OTP0 0xb0
@@ -95,11 +96,10 @@ static int __init ab3100_otp_read(struct ab3100_otp *otp)
* This is a simple debugfs human-readable file that dumps out
* the contents of the OTP.
*/
-#ifdef CONFIG_DEBUGFS
-static int show_otp(struct seq_file *s, void *v)
+#ifdef CONFIG_DEBUG_FS
+static int ab3100_show_otp(struct seq_file *s, void *v)
{
struct ab3100_otp *otp = s->private;
- int err;
seq_printf(s, "OTP is %s\n", otp->locked ? "LOCKED" : "UNLOCKED");
seq_printf(s, "OTP clock switch startup is %uHz\n", otp->freq);
@@ -113,7 +113,7 @@ static int show_otp(struct seq_file *s, void *v)
static int ab3100_otp_open(struct inode *inode, struct file *file)
{
- return single_open(file, ab3100_otp_show, inode->i_private);
+ return single_open(file, ab3100_show_otp, inode->i_private);
}
static const struct file_operations ab3100_otp_operations = {
@@ -131,13 +131,14 @@ static int __init ab3100_otp_init_debugfs(struct device *dev,
&ab3100_otp_operations);
if (!otp->debugfs) {
dev_err(dev, "AB3100 debugfs OTP file registration failed!\n");
- return err;
+ return -ENOENT;
}
+ return 0;
}
static void __exit ab3100_otp_exit_debugfs(struct ab3100_otp *otp)
{
- debugfs_remove_file(otp->debugfs);
+ debugfs_remove(otp->debugfs);
}
#else
/* Compile this out if debugfs not selected */
diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c
index aa266e1f69b..addb846c1e3 100644
--- a/drivers/mfd/htc-egpio.c
+++ b/drivers/mfd/htc-egpio.c
@@ -108,7 +108,7 @@ static void egpio_handler(unsigned int irq, struct irq_desc *desc)
ack_irqs(ei);
/* Process all set pins. */
readval &= ei->irqs_enabled;
- for_each_bit(irqpin, &readval, ei->nirqs) {
+ for_each_set_bit(irqpin, &readval, ei->nirqs) {
/* Run irq handler */
pr_debug("got IRQ %d\n", irqpin);
irq = ei->irq_start + irqpin;
diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c
new file mode 100644
index 00000000000..37b9fdab4f3
--- /dev/null
+++ b/drivers/mfd/htc-i2cpld.c
@@ -0,0 +1,710 @@
+/*
+ * htc-i2cpld.c
+ * Chip driver for an unknown CPLD chip found on omap850 HTC devices like
+ * the HTC Wizard and HTC Herald.
+ * The cpld is located on the i2c bus and acts as an input/output GPIO
+ * extender.
+ *
+ * Copyright (C) 2009 Cory Maccarrone <darkstar6262@gmail.com>
+ *
+ * Based on work done in the linwizard project
+ * Copyright (C) 2008-2009 Angelo Arrifano <miknix@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/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/spinlock.h>
+#include <linux/htcpld.h>
+#include <linux/gpio.h>
+
+struct htcpld_chip {
+ spinlock_t lock;
+
+ /* chip info */
+ u8 reset;
+ u8 addr;
+ struct device *dev;
+ struct i2c_client *client;
+
+ /* Output details */
+ u8 cache_out;
+ struct gpio_chip chip_out;
+
+ /* Input details */
+ u8 cache_in;
+ struct gpio_chip chip_in;
+
+ u16 irqs_enabled;
+ uint irq_start;
+ int nirqs;
+
+ /*
+ * Work structure to allow for setting values outside of any
+ * possible interrupt context
+ */
+ struct work_struct set_val_work;
+};
+
+struct htcpld_data {
+ /* irq info */
+ u16 irqs_enabled;
+ uint irq_start;
+ int nirqs;
+ uint chained_irq;
+ unsigned int int_reset_gpio_hi;
+ unsigned int int_reset_gpio_lo;
+
+ /* htcpld info */
+ struct htcpld_chip *chip;
+ unsigned int nchips;
+};
+
+/* There does not appear to be a way to proactively mask interrupts
+ * on the htcpld chip itself. So, we simply ignore interrupts that
+ * aren't desired. */
+static void htcpld_mask(unsigned int irq)
+{
+ struct htcpld_chip *chip = get_irq_chip_data(irq);
+ chip->irqs_enabled &= ~(1 << (irq - chip->irq_start));
+ pr_debug("HTCPLD mask %d %04x\n", irq, chip->irqs_enabled);
+}
+static void htcpld_unmask(unsigned int irq)
+{
+ struct htcpld_chip *chip = get_irq_chip_data(irq);
+ chip->irqs_enabled |= 1 << (irq - chip->irq_start);
+ pr_debug("HTCPLD unmask %d %04x\n", irq, chip->irqs_enabled);
+}
+
+static int htcpld_set_type(unsigned int irq, unsigned int flags)
+{
+ struct irq_desc *d = irq_to_desc(irq);
+
+ if (!d) {
+ pr_err("HTCPLD invalid IRQ: %d\n", irq);
+ return -EINVAL;
+ }
+
+ if (flags & ~IRQ_TYPE_SENSE_MASK)
+ return -EINVAL;
+
+ /* We only allow edge triggering */
+ if (flags & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH))
+ return -EINVAL;
+
+ d->status &= ~IRQ_TYPE_SENSE_MASK;
+ d->status |= flags;
+
+ return 0;
+}
+
+static struct irq_chip htcpld_muxed_chip = {
+ .name = "htcpld",
+ .mask = htcpld_mask,
+ .unmask = htcpld_unmask,
+ .set_type = htcpld_set_type,
+};
+
+/* To properly dispatch IRQ events, we need to read from the
+ * chip. This is an I2C action that could possibly sleep
+ * (which is bad in interrupt context) -- so we use a threaded
+ * interrupt handler to get around that.
+ */
+static irqreturn_t htcpld_handler(int irq, void *dev)
+{
+ struct htcpld_data *htcpld = dev;
+ unsigned int i;
+ unsigned long flags;
+ int irqpin;
+ struct irq_desc *desc;
+
+ if (!htcpld) {
+ pr_debug("htcpld is null in ISR\n");
+ return IRQ_HANDLED;
+ }
+
+ /*
+ * For each chip, do a read of the chip and trigger any interrupts
+ * desired. The interrupts will be triggered from LSB to MSB (i.e.
+ * bit 0 first, then bit 1, etc.)
+ *
+ * For chips that have no interrupt range specified, just skip 'em.
+ */
+ for (i = 0; i < htcpld->nchips; i++) {
+ struct htcpld_chip *chip = &htcpld->chip[i];
+ struct i2c_client *client;
+ int val;
+ unsigned long uval, old_val;
+
+ if (!chip) {
+ pr_debug("chip %d is null in ISR\n", i);
+ continue;
+ }
+
+ if (chip->nirqs == 0)
+ continue;
+
+ client = chip->client;
+ if (!client) {
+ pr_debug("client %d is null in ISR\n", i);
+ continue;
+ }
+
+ /* Scan the chip */
+ val = i2c_smbus_read_byte_data(client, chip->cache_out);
+ if (val < 0) {
+ /* Throw a warning and skip this chip */
+ dev_warn(chip->dev, "Unable to read from chip: %d\n",
+ val);
+ continue;
+ }
+
+ uval = (unsigned long)val;
+
+ spin_lock_irqsave(&chip->lock, flags);
+
+ /* Save away the old value so we can compare it */
+ old_val = chip->cache_in;
+
+ /* Write the new value */
+ chip->cache_in = uval;
+
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ /*
+ * For each bit in the data (starting at bit 0), trigger
+ * associated interrupts.
+ */
+ for (irqpin = 0; irqpin < chip->nirqs; irqpin++) {
+ unsigned oldb, newb;
+ int flags;
+
+ irq = chip->irq_start + irqpin;
+ desc = irq_to_desc(irq);
+ flags = desc->status;
+
+ /* Run the IRQ handler, but only if the bit value
+ * changed, and the proper flags are set */
+ oldb = (old_val >> irqpin) & 1;
+ newb = (uval >> irqpin) & 1;
+
+ if ((!oldb && newb && (flags & IRQ_TYPE_EDGE_RISING)) ||
+ (oldb && !newb &&
+ (flags & IRQ_TYPE_EDGE_FALLING))) {
+ pr_debug("fire IRQ %d\n", irqpin);
+ desc->handle_irq(irq, desc);
+ }
+ }
+ }
+
+ /*
+ * In order to continue receiving interrupts, the int_reset_gpio must
+ * be asserted.
+ */
+ if (htcpld->int_reset_gpio_hi)
+ gpio_set_value(htcpld->int_reset_gpio_hi, 1);
+ if (htcpld->int_reset_gpio_lo)
+ gpio_set_value(htcpld->int_reset_gpio_lo, 0);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * The GPIO set routines can be called from interrupt context, especially if,
+ * for example they're attached to the led-gpio framework and a trigger is
+ * enabled. As such, we declared work above in the htcpld_chip structure,
+ * and that work is scheduled in the set routine. The kernel can then run
+ * the I2C functions, which will sleep, in process context.
+ */
+void htcpld_chip_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+ struct i2c_client *client;
+ struct htcpld_chip *chip_data;
+ unsigned long flags;
+
+ chip_data = container_of(chip, struct htcpld_chip, chip_out);
+ if (!chip_data)
+ return;
+
+ client = chip_data->client;
+ if (client == NULL)
+ return;
+
+ spin_lock_irqsave(&chip_data->lock, flags);
+ if (val)
+ chip_data->cache_out |= (1 << offset);
+ else
+ chip_data->cache_out &= ~(1 << offset);
+ spin_unlock_irqrestore(&chip_data->lock, flags);
+
+ schedule_work(&(chip_data->set_val_work));
+}
+
+void htcpld_chip_set_ni(struct work_struct *work)
+{
+ struct htcpld_chip *chip_data;
+ struct i2c_client *client;
+
+ chip_data = container_of(work, struct htcpld_chip, set_val_work);
+ client = chip_data->client;
+ i2c_smbus_read_byte_data(client, chip_data->cache_out);
+}
+
+int htcpld_chip_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct htcpld_chip *chip_data;
+ int val = 0;
+ int is_input = 0;
+
+ /* Try out first */
+ chip_data = container_of(chip, struct htcpld_chip, chip_out);
+ if (!chip_data) {
+ /* Try in */
+ is_input = 1;
+ chip_data = container_of(chip, struct htcpld_chip, chip_in);
+ if (!chip_data)
+ return -EINVAL;
+ }
+
+ /* Determine if this is an input or output GPIO */
+ if (!is_input)
+ /* Use the output cache */
+ val = (chip_data->cache_out >> offset) & 1;
+ else
+ /* Use the input cache */
+ val = (chip_data->cache_in >> offset) & 1;
+
+ if (val)
+ return 1;
+ else
+ return 0;
+}
+
+static int htcpld_direction_output(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ htcpld_chip_set(chip, offset, value);
+ return 0;
+}
+
+static int htcpld_direction_input(struct gpio_chip *chip,
+ unsigned offset)
+{
+ /*
+ * No-op: this function can only be called on the input chip.
+ * We do however make sure the offset is within range.
+ */
+ return (offset < chip->ngpio) ? 0 : -EINVAL;
+}
+
+int htcpld_chip_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+ struct htcpld_chip *chip_data;
+
+ chip_data = container_of(chip, struct htcpld_chip, chip_in);
+
+ if (offset < chip_data->nirqs)
+ return chip_data->irq_start + offset;
+ else
+ return -EINVAL;
+}
+
+void htcpld_chip_reset(struct i2c_client *client)
+{
+ struct htcpld_chip *chip_data = i2c_get_clientdata(client);
+ if (!chip_data)
+ return;
+
+ i2c_smbus_read_byte_data(
+ client, (chip_data->cache_out = chip_data->reset));
+}
+
+static int __devinit htcpld_setup_chip_irq(
+ struct platform_device *pdev,
+ int chip_index)
+{
+ struct htcpld_data *htcpld;
+ struct device *dev = &pdev->dev;
+ struct htcpld_core_platform_data *pdata;
+ struct htcpld_chip *chip;
+ struct htcpld_chip_platform_data *plat_chip_data;
+ unsigned int irq, irq_end;
+ int ret = 0;
+
+ /* Get the platform and driver data */
+ pdata = dev->platform_data;
+ htcpld = platform_get_drvdata(pdev);
+ chip = &htcpld->chip[chip_index];
+ plat_chip_data = &pdata->chip[chip_index];
+
+ /* Setup irq handlers */
+ irq_end = chip->irq_start + chip->nirqs;
+ for (irq = chip->irq_start; irq < irq_end; irq++) {
+ set_irq_chip(irq, &htcpld_muxed_chip);
+ set_irq_chip_data(irq, chip);
+ set_irq_handler(irq, handle_simple_irq);
+#ifdef CONFIG_ARM
+ set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+#else
+ set_irq_probe(irq);
+#endif
+ }
+
+ return ret;
+}
+
+static int __devinit htcpld_register_chip_i2c(
+ struct platform_device *pdev,
+ int chip_index)
+{
+ struct htcpld_data *htcpld;
+ struct device *dev = &pdev->dev;
+ struct htcpld_core_platform_data *pdata;
+ struct htcpld_chip *chip;
+ struct htcpld_chip_platform_data *plat_chip_data;
+ struct i2c_adapter *adapter;
+ struct i2c_client *client;
+ struct i2c_board_info info;
+
+ /* Get the platform and driver data */
+ pdata = dev->platform_data;
+ htcpld = platform_get_drvdata(pdev);
+ chip = &htcpld->chip[chip_index];
+ plat_chip_data = &pdata->chip[chip_index];
+
+ adapter = i2c_get_adapter(pdata->i2c_adapter_id);
+ if (adapter == NULL) {
+ /* Eek, no such I2C adapter! Bail out. */
+ dev_warn(dev, "Chip at i2c address 0x%x: Invalid i2c adapter %d\n",
+ plat_chip_data->addr, pdata->i2c_adapter_id);
+ return -ENODEV;
+ }
+
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
+ dev_warn(dev, "i2c adapter %d non-functional\n",
+ pdata->i2c_adapter_id);
+ return -EINVAL;
+ }
+
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ info.addr = plat_chip_data->addr;
+ strlcpy(info.type, "htcpld-chip", I2C_NAME_SIZE);
+ info.platform_data = chip;
+
+ /* Add the I2C device. This calls the probe() function. */
+ client = i2c_new_device(adapter, &info);
+ if (!client) {
+ /* I2C device registration failed, contineu with the next */
+ dev_warn(dev, "Unable to add I2C device for 0x%x\n",
+ plat_chip_data->addr);
+ return -ENODEV;
+ }
+
+ i2c_set_clientdata(client, chip);
+ snprintf(client->name, I2C_NAME_SIZE, "Chip_0x%d", client->addr);
+ chip->client = client;
+
+ /* Reset the chip */
+ htcpld_chip_reset(client);
+ chip->cache_in = i2c_smbus_read_byte_data(client, chip->cache_out);
+
+ return 0;
+}
+
+static void __devinit htcpld_unregister_chip_i2c(
+ struct platform_device *pdev,
+ int chip_index)
+{
+ struct htcpld_data *htcpld;
+ struct htcpld_chip *chip;
+
+ /* Get the platform and driver data */
+ htcpld = platform_get_drvdata(pdev);
+ chip = &htcpld->chip[chip_index];
+
+ if (chip->client)
+ i2c_unregister_device(chip->client);
+}
+
+static int __devinit htcpld_register_chip_gpio(
+ struct platform_device *pdev,
+ int chip_index)
+{
+ struct htcpld_data *htcpld;
+ struct device *dev = &pdev->dev;
+ struct htcpld_core_platform_data *pdata;
+ struct htcpld_chip *chip;
+ struct htcpld_chip_platform_data *plat_chip_data;
+ struct gpio_chip *gpio_chip;
+ int ret = 0;
+
+ /* Get the platform and driver data */
+ pdata = dev->platform_data;
+ htcpld = platform_get_drvdata(pdev);
+ chip = &htcpld->chip[chip_index];
+ plat_chip_data = &pdata->chip[chip_index];
+
+ /* Setup the GPIO chips */
+ gpio_chip = &(chip->chip_out);
+ gpio_chip->label = "htcpld-out";
+ gpio_chip->dev = dev;
+ gpio_chip->owner = THIS_MODULE;
+ gpio_chip->get = htcpld_chip_get;
+ gpio_chip->set = htcpld_chip_set;
+ gpio_chip->direction_input = NULL;
+ gpio_chip->direction_output = htcpld_direction_output;
+ gpio_chip->base = plat_chip_data->gpio_out_base;
+ gpio_chip->ngpio = plat_chip_data->num_gpios;
+
+ gpio_chip = &(chip->chip_in);
+ gpio_chip->label = "htcpld-in";
+ gpio_chip->dev = dev;
+ gpio_chip->owner = THIS_MODULE;
+ gpio_chip->get = htcpld_chip_get;
+ gpio_chip->set = NULL;
+ gpio_chip->direction_input = htcpld_direction_input;
+ gpio_chip->direction_output = NULL;
+ gpio_chip->to_irq = htcpld_chip_to_irq;
+ gpio_chip->base = plat_chip_data->gpio_in_base;
+ gpio_chip->ngpio = plat_chip_data->num_gpios;
+
+ /* Add the GPIO chips */
+ ret = gpiochip_add(&(chip->chip_out));
+ if (ret) {
+ dev_warn(dev, "Unable to register output GPIOs for 0x%x: %d\n",
+ plat_chip_data->addr, ret);
+ return ret;
+ }
+
+ ret = gpiochip_add(&(chip->chip_in));
+ if (ret) {
+ int error;
+
+ dev_warn(dev, "Unable to register input GPIOs for 0x%x: %d\n",
+ plat_chip_data->addr, ret);
+
+ error = gpiochip_remove(&(chip->chip_out));
+ if (error)
+ dev_warn(dev, "Error while trying to unregister gpio chip: %d\n", error);
+
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __devinit htcpld_setup_chips(struct platform_device *pdev)
+{
+ struct htcpld_data *htcpld;
+ struct device *dev = &pdev->dev;
+ struct htcpld_core_platform_data *pdata;
+ int i;
+
+ /* Get the platform and driver data */
+ pdata = dev->platform_data;
+ htcpld = platform_get_drvdata(pdev);
+
+ /* Setup each chip's output GPIOs */
+ htcpld->nchips = pdata->num_chip;
+ htcpld->chip = kzalloc(sizeof(struct htcpld_chip) * htcpld->nchips,
+ GFP_KERNEL);
+ if (!htcpld->chip) {
+ dev_warn(dev, "Unable to allocate memory for chips\n");
+ return -ENOMEM;
+ }
+
+ /* Add the chips as best we can */
+ for (i = 0; i < htcpld->nchips; i++) {
+ int ret;
+
+ /* Setup the HTCPLD chips */
+ htcpld->chip[i].reset = pdata->chip[i].reset;
+ htcpld->chip[i].cache_out = pdata->chip[i].reset;
+ htcpld->chip[i].cache_in = 0;
+ htcpld->chip[i].dev = dev;
+ htcpld->chip[i].irq_start = pdata->chip[i].irq_base;
+ htcpld->chip[i].nirqs = pdata->chip[i].num_irqs;
+
+ INIT_WORK(&(htcpld->chip[i].set_val_work), &htcpld_chip_set_ni);
+ spin_lock_init(&(htcpld->chip[i].lock));
+
+ /* Setup the interrupts for the chip */
+ if (htcpld->chained_irq) {
+ ret = htcpld_setup_chip_irq(pdev, i);
+ if (ret)
+ continue;
+ }
+
+ /* Register the chip with I2C */
+ ret = htcpld_register_chip_i2c(pdev, i);
+ if (ret)
+ continue;
+
+
+ /* Register the chips with the GPIO subsystem */
+ ret = htcpld_register_chip_gpio(pdev, i);
+ if (ret) {
+ /* Unregister the chip from i2c and continue */
+ htcpld_unregister_chip_i2c(pdev, i);
+ continue;
+ }
+
+ dev_info(dev, "Registered chip at 0x%x\n", pdata->chip[i].addr);
+ }
+
+ return 0;
+}
+
+static int __devinit htcpld_core_probe(struct platform_device *pdev)
+{
+ struct htcpld_data *htcpld;
+ struct device *dev = &pdev->dev;
+ struct htcpld_core_platform_data *pdata;
+ struct resource *res;
+ int ret = 0;
+
+ if (!dev)
+ return -ENODEV;
+
+ pdata = dev->platform_data;
+ if (!pdata) {
+ dev_warn(dev, "Platform data not found for htcpld core!\n");
+ return -ENXIO;
+ }
+
+ htcpld = kzalloc(sizeof(struct htcpld_data), GFP_KERNEL);
+ if (!htcpld)
+ return -ENOMEM;
+
+ /* Find chained irq */
+ ret = -EINVAL;
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (res) {
+ int flags;
+ htcpld->chained_irq = res->start;
+
+ /* Setup the chained interrupt handler */
+ flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING;
+ ret = request_threaded_irq(htcpld->chained_irq,
+ NULL, htcpld_handler,
+ flags, pdev->name, htcpld);
+ if (ret) {
+ dev_warn(dev, "Unable to setup chained irq handler: %d\n", ret);
+ goto fail;
+ } else
+ device_init_wakeup(dev, 0);
+ }
+
+ /* Set the driver data */
+ platform_set_drvdata(pdev, htcpld);
+
+ /* Setup the htcpld chips */
+ ret = htcpld_setup_chips(pdev);
+ if (ret)
+ goto fail;
+
+ /* Request the GPIO(s) for the int reset and set them up */
+ if (pdata->int_reset_gpio_hi) {
+ ret = gpio_request(pdata->int_reset_gpio_hi, "htcpld-core");
+ if (ret) {
+ /*
+ * If it failed, that sucks, but we can probably
+ * continue on without it.
+ */
+ dev_warn(dev, "Unable to request int_reset_gpio_hi -- interrupts may not work\n");
+ htcpld->int_reset_gpio_hi = 0;
+ } else {
+ htcpld->int_reset_gpio_hi = pdata->int_reset_gpio_hi;
+ gpio_set_value(htcpld->int_reset_gpio_hi, 1);
+ }
+ }
+
+ if (pdata->int_reset_gpio_lo) {
+ ret = gpio_request(pdata->int_reset_gpio_lo, "htcpld-core");
+ if (ret) {
+ /*
+ * If it failed, that sucks, but we can probably
+ * continue on without it.
+ */
+ dev_warn(dev, "Unable to request int_reset_gpio_lo -- interrupts may not work\n");
+ htcpld->int_reset_gpio_lo = 0;
+ } else {
+ htcpld->int_reset_gpio_lo = pdata->int_reset_gpio_lo;
+ gpio_set_value(htcpld->int_reset_gpio_lo, 0);
+ }
+ }
+
+ dev_info(dev, "Initialized successfully\n");
+ return 0;
+
+fail:
+ kfree(htcpld);
+ return ret;
+}
+
+/* The I2C Driver -- used internally */
+static const struct i2c_device_id htcpld_chip_id[] = {
+ { "htcpld-chip", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, htcpld_chip_id);
+
+
+static struct i2c_driver htcpld_chip_driver = {
+ .driver = {
+ .name = "htcpld-chip",
+ },
+ .id_table = htcpld_chip_id,
+};
+
+/* The Core Driver */
+static struct platform_driver htcpld_core_driver = {
+ .driver = {
+ .name = "i2c-htcpld",
+ },
+};
+
+static int __init htcpld_core_init(void)
+{
+ int ret;
+
+ /* Register the I2C Chip driver */
+ ret = i2c_add_driver(&htcpld_chip_driver);
+ if (ret)
+ return ret;
+
+ /* Probe for our chips */
+ return platform_driver_probe(&htcpld_core_driver, htcpld_core_probe);
+}
+
+static void __exit htcpld_core_exit(void)
+{
+ i2c_del_driver(&htcpld_chip_driver);
+ platform_driver_unregister(&htcpld_core_driver);
+}
+
+module_init(htcpld_core_init);
+module_exit(htcpld_core_exit);
+
+MODULE_AUTHOR("Cory Maccarrone <darkstar6262@gmail.com>");
+MODULE_DESCRIPTION("I2C HTC PLD Driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/mfd/lpc_sch.c b/drivers/mfd/lpc_sch.c
new file mode 100644
index 00000000000..51b2f6065a0
--- /dev/null
+++ b/drivers/mfd/lpc_sch.c
@@ -0,0 +1,133 @@
+/*
+ * lpc_sch.c - LPC interface for Intel Poulsbo SCH
+ *
+ * LPC bridge function of the Intel SCH contains many other
+ * functional units, such as Interrupt controllers, Timers,
+ * Power Management, System Management, GPIO, RTC, and LPC
+ * Configuration Registers.
+ *
+ * Copyright (c) 2010 CompuLab Ltd
+ * Author: Denis Turischev <denis@compulab.co.il>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/acpi.h>
+#include <linux/pci.h>
+#include <linux/mfd/core.h>
+
+#define SMBASE 0x40
+#define SMBUS_IO_SIZE 64
+
+#define GPIOBASE 0x44
+#define GPIO_IO_SIZE 64
+
+static struct resource smbus_sch_resource = {
+ .flags = IORESOURCE_IO,
+};
+
+
+static struct resource gpio_sch_resource = {
+ .flags = IORESOURCE_IO,
+};
+
+static struct mfd_cell lpc_sch_cells[] = {
+ {
+ .name = "isch_smbus",
+ .num_resources = 1,
+ .resources = &smbus_sch_resource,
+ },
+ {
+ .name = "sch_gpio",
+ .num_resources = 1,
+ .resources = &gpio_sch_resource,
+ },
+};
+
+static struct pci_device_id lpc_sch_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) },
+ { 0, }
+};
+MODULE_DEVICE_TABLE(pci, lpc_sch_ids);
+
+static int __devinit lpc_sch_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
+ unsigned int base_addr_cfg;
+ unsigned short base_addr;
+
+ pci_read_config_dword(dev, SMBASE, &base_addr_cfg);
+ if (!(base_addr_cfg & (1 << 31))) {
+ dev_err(&dev->dev, "Decode of the SMBus I/O range disabled\n");
+ return -ENODEV;
+ }
+ base_addr = (unsigned short)base_addr_cfg;
+ if (base_addr == 0) {
+ dev_err(&dev->dev, "I/O space for SMBus uninitialized\n");
+ return -ENODEV;
+ }
+
+ smbus_sch_resource.start = base_addr;
+ smbus_sch_resource.end = base_addr + SMBUS_IO_SIZE - 1;
+
+ pci_read_config_dword(dev, GPIOBASE, &base_addr_cfg);
+ if (!(base_addr_cfg & (1 << 31))) {
+ dev_err(&dev->dev, "Decode of the GPIO I/O range disabled\n");
+ return -ENODEV;
+ }
+ base_addr = (unsigned short)base_addr_cfg;
+ if (base_addr == 0) {
+ dev_err(&dev->dev, "I/O space for GPIO uninitialized\n");
+ return -ENODEV;
+ }
+
+ gpio_sch_resource.start = base_addr;
+ gpio_sch_resource.end = base_addr + GPIO_IO_SIZE - 1;
+
+ return mfd_add_devices(&dev->dev, -1,
+ lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, 0);
+}
+
+static void __devexit lpc_sch_remove(struct pci_dev *dev)
+{
+ mfd_remove_devices(&dev->dev);
+}
+
+static struct pci_driver lpc_sch_driver = {
+ .name = "lpc_sch",
+ .id_table = lpc_sch_ids,
+ .probe = lpc_sch_probe,
+ .remove = __devexit_p(lpc_sch_remove),
+};
+
+static int __init lpc_sch_init(void)
+{
+ return pci_register_driver(&lpc_sch_driver);
+}
+
+static void __exit lpc_sch_exit(void)
+{
+ pci_unregister_driver(&lpc_sch_driver);
+}
+
+module_init(lpc_sch_init);
+module_exit(lpc_sch_exit);
+
+MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
+MODULE_DESCRIPTION("LPC interface for Intel Poulsbo SCH");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
new file mode 100644
index 00000000000..85d63c04749
--- /dev/null
+++ b/drivers/mfd/max8925-core.c
@@ -0,0 +1,656 @@
+/*
+ * Base driver for Maxim MAX8925
+ *
+ * Copyright (C) 2009-2010 Marvell International Ltd.
+ * Haojian Zhuang <haojian.zhuang@marvell.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/i2c.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/max8925.h>
+
+static struct resource backlight_resources[] = {
+ {
+ .name = "max8925-backlight",
+ .start = MAX8925_WLED_MODE_CNTL,
+ .end = MAX8925_WLED_CNTL,
+ .flags = IORESOURCE_IO,
+ },
+};
+
+static struct mfd_cell backlight_devs[] = {
+ {
+ .name = "max8925-backlight",
+ .num_resources = 1,
+ .resources = &backlight_resources[0],
+ .id = -1,
+ },
+};
+
+static struct resource touch_resources[] = {
+ {
+ .name = "max8925-tsc",
+ .start = MAX8925_TSC_IRQ,
+ .end = MAX8925_ADC_RES_END,
+ .flags = IORESOURCE_IO,
+ },
+};
+
+static struct mfd_cell touch_devs[] = {
+ {
+ .name = "max8925-touch",
+ .num_resources = 1,
+ .resources = &touch_resources[0],
+ .id = -1,
+ },
+};
+
+static struct resource power_supply_resources[] = {
+ {
+ .name = "max8925-power",
+ .start = MAX8925_CHG_IRQ1,
+ .end = MAX8925_CHG_IRQ1_MASK,
+ .flags = IORESOURCE_IO,
+ },
+};
+
+static struct mfd_cell power_devs[] = {
+ {
+ .name = "max8925-power",
+ .num_resources = 1,
+ .resources = &power_supply_resources[0],
+ .id = -1,
+ },
+};
+
+static struct resource rtc_resources[] = {
+ {
+ .name = "max8925-rtc",
+ .start = MAX8925_RTC_IRQ,
+ .end = MAX8925_RTC_IRQ_MASK,
+ .flags = IORESOURCE_IO,
+ },
+};
+
+static struct mfd_cell rtc_devs[] = {
+ {
+ .name = "max8925-rtc",
+ .num_resources = 1,
+ .resources = &rtc_resources[0],
+ .id = -1,
+ },
+};
+
+#define MAX8925_REG_RESOURCE(_start, _end) \
+{ \
+ .start = MAX8925_##_start, \
+ .end = MAX8925_##_end, \
+ .flags = IORESOURCE_IO, \
+}
+
+static struct resource regulator_resources[] = {
+ MAX8925_REG_RESOURCE(SDCTL1, SDCTL1),
+ MAX8925_REG_RESOURCE(SDCTL2, SDCTL2),
+ MAX8925_REG_RESOURCE(SDCTL3, SDCTL3),
+ MAX8925_REG_RESOURCE(LDOCTL1, LDOCTL1),
+ MAX8925_REG_RESOURCE(LDOCTL2, LDOCTL2),
+ MAX8925_REG_RESOURCE(LDOCTL3, LDOCTL3),
+ MAX8925_REG_RESOURCE(LDOCTL4, LDOCTL4),
+ MAX8925_REG_RESOURCE(LDOCTL5, LDOCTL5),
+ MAX8925_REG_RESOURCE(LDOCTL6, LDOCTL6),
+ MAX8925_REG_RESOURCE(LDOCTL7, LDOCTL7),
+ MAX8925_REG_RESOURCE(LDOCTL8, LDOCTL8),
+ MAX8925_REG_RESOURCE(LDOCTL9, LDOCTL9),
+ MAX8925_REG_RESOURCE(LDOCTL10, LDOCTL10),
+ MAX8925_REG_RESOURCE(LDOCTL11, LDOCTL11),
+ MAX8925_REG_RESOURCE(LDOCTL12, LDOCTL12),
+ MAX8925_REG_RESOURCE(LDOCTL13, LDOCTL13),
+ MAX8925_REG_RESOURCE(LDOCTL14, LDOCTL14),
+ MAX8925_REG_RESOURCE(LDOCTL15, LDOCTL15),
+ MAX8925_REG_RESOURCE(LDOCTL16, LDOCTL16),
+ MAX8925_REG_RESOURCE(LDOCTL17, LDOCTL17),
+ MAX8925_REG_RESOURCE(LDOCTL18, LDOCTL18),
+ MAX8925_REG_RESOURCE(LDOCTL19, LDOCTL19),
+ MAX8925_REG_RESOURCE(LDOCTL20, LDOCTL20),
+};
+
+#define MAX8925_REG_DEVS(_id) \
+{ \
+ .name = "max8925-regulator", \
+ .num_resources = 1, \
+ .resources = &regulator_resources[MAX8925_ID_##_id], \
+ .id = MAX8925_ID_##_id, \
+}
+
+static struct mfd_cell regulator_devs[] = {
+ MAX8925_REG_DEVS(SD1),
+ MAX8925_REG_DEVS(SD2),
+ MAX8925_REG_DEVS(SD3),
+ MAX8925_REG_DEVS(LDO1),
+ MAX8925_REG_DEVS(LDO2),
+ MAX8925_REG_DEVS(LDO3),
+ MAX8925_REG_DEVS(LDO4),
+ MAX8925_REG_DEVS(LDO5),
+ MAX8925_REG_DEVS(LDO6),
+ MAX8925_REG_DEVS(LDO7),
+ MAX8925_REG_DEVS(LDO8),
+ MAX8925_REG_DEVS(LDO9),
+ MAX8925_REG_DEVS(LDO10),
+ MAX8925_REG_DEVS(LDO11),
+ MAX8925_REG_DEVS(LDO12),
+ MAX8925_REG_DEVS(LDO13),
+ MAX8925_REG_DEVS(LDO14),
+ MAX8925_REG_DEVS(LDO15),
+ MAX8925_REG_DEVS(LDO16),
+ MAX8925_REG_DEVS(LDO17),
+ MAX8925_REG_DEVS(LDO18),
+ MAX8925_REG_DEVS(LDO19),
+ MAX8925_REG_DEVS(LDO20),
+};
+
+enum {
+ FLAGS_ADC = 1, /* register in ADC component */
+ FLAGS_RTC, /* register in RTC component */
+};
+
+struct max8925_irq_data {
+ int reg;
+ int mask_reg;
+ int enable; /* enable or not */
+ int offs; /* bit offset in mask register */
+ int flags;
+ int tsc_irq;
+};
+
+static struct max8925_irq_data max8925_irqs[] = {
+ [MAX8925_IRQ_VCHG_DC_OVP] = {
+ .reg = MAX8925_CHG_IRQ1,
+ .mask_reg = MAX8925_CHG_IRQ1_MASK,
+ .offs = 1 << 0,
+ },
+ [MAX8925_IRQ_VCHG_DC_F] = {
+ .reg = MAX8925_CHG_IRQ1,
+ .mask_reg = MAX8925_CHG_IRQ1_MASK,
+ .offs = 1 << 1,
+ },
+ [MAX8925_IRQ_VCHG_DC_R] = {
+ .reg = MAX8925_CHG_IRQ1,
+ .mask_reg = MAX8925_CHG_IRQ1_MASK,
+ .offs = 1 << 2,
+ },
+ [MAX8925_IRQ_VCHG_USB_OVP] = {
+ .reg = MAX8925_CHG_IRQ1,
+ .mask_reg = MAX8925_CHG_IRQ1_MASK,
+ .offs = 1 << 3,
+ },
+ [MAX8925_IRQ_VCHG_USB_F] = {
+ .reg = MAX8925_CHG_IRQ1,
+ .mask_reg = MAX8925_CHG_IRQ1_MASK,
+ .offs = 1 << 4,
+ },
+ [MAX8925_IRQ_VCHG_USB_R] = {
+ .reg = MAX8925_CHG_IRQ1,
+ .mask_reg = MAX8925_CHG_IRQ1_MASK,
+ .offs = 1 << 5,
+ },
+ [MAX8925_IRQ_VCHG_THM_OK_R] = {
+ .reg = MAX8925_CHG_IRQ2,
+ .mask_reg = MAX8925_CHG_IRQ2_MASK,
+ .offs = 1 << 0,
+ },
+ [MAX8925_IRQ_VCHG_THM_OK_F] = {
+ .reg = MAX8925_CHG_IRQ2,
+ .mask_reg = MAX8925_CHG_IRQ2_MASK,
+ .offs = 1 << 1,
+ },
+ [MAX8925_IRQ_VCHG_SYSLOW_F] = {
+ .reg = MAX8925_CHG_IRQ2,
+ .mask_reg = MAX8925_CHG_IRQ2_MASK,
+ .offs = 1 << 2,
+ },
+ [MAX8925_IRQ_VCHG_SYSLOW_R] = {
+ .reg = MAX8925_CHG_IRQ2,
+ .mask_reg = MAX8925_CHG_IRQ2_MASK,
+ .offs = 1 << 3,
+ },
+ [MAX8925_IRQ_VCHG_RST] = {
+ .reg = MAX8925_CHG_IRQ2,
+ .mask_reg = MAX8925_CHG_IRQ2_MASK,
+ .offs = 1 << 4,
+ },
+ [MAX8925_IRQ_VCHG_DONE] = {
+ .reg = MAX8925_CHG_IRQ2,
+ .mask_reg = MAX8925_CHG_IRQ2_MASK,
+ .offs = 1 << 5,
+ },
+ [MAX8925_IRQ_VCHG_TOPOFF] = {
+ .reg = MAX8925_CHG_IRQ2,
+ .mask_reg = MAX8925_CHG_IRQ2_MASK,
+ .offs = 1 << 6,
+ },
+ [MAX8925_IRQ_VCHG_TMR_FAULT] = {
+ .reg = MAX8925_CHG_IRQ2,
+ .mask_reg = MAX8925_CHG_IRQ2_MASK,
+ .offs = 1 << 7,
+ },
+ [MAX8925_IRQ_GPM_RSTIN] = {
+ .reg = MAX8925_ON_OFF_IRQ1,
+ .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
+ .offs = 1 << 0,
+ },
+ [MAX8925_IRQ_GPM_MPL] = {
+ .reg = MAX8925_ON_OFF_IRQ1,
+ .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
+ .offs = 1 << 1,
+ },
+ [MAX8925_IRQ_GPM_SW_3SEC] = {
+ .reg = MAX8925_ON_OFF_IRQ1,
+ .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
+ .offs = 1 << 2,
+ },
+ [MAX8925_IRQ_GPM_EXTON_F] = {
+ .reg = MAX8925_ON_OFF_IRQ1,
+ .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
+ .offs = 1 << 3,
+ },
+ [MAX8925_IRQ_GPM_EXTON_R] = {
+ .reg = MAX8925_ON_OFF_IRQ1,
+ .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
+ .offs = 1 << 4,
+ },
+ [MAX8925_IRQ_GPM_SW_1SEC] = {
+ .reg = MAX8925_ON_OFF_IRQ1,
+ .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
+ .offs = 1 << 5,
+ },
+ [MAX8925_IRQ_GPM_SW_F] = {
+ .reg = MAX8925_ON_OFF_IRQ1,
+ .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
+ .offs = 1 << 6,
+ },
+ [MAX8925_IRQ_GPM_SW_R] = {
+ .reg = MAX8925_ON_OFF_IRQ1,
+ .mask_reg = MAX8925_ON_OFF_IRQ1_MASK,
+ .offs = 1 << 7,
+ },
+ [MAX8925_IRQ_GPM_SYSCKEN_F] = {
+ .reg = MAX8925_ON_OFF_IRQ2,
+ .mask_reg = MAX8925_ON_OFF_IRQ2_MASK,
+ .offs = 1 << 0,
+ },
+ [MAX8925_IRQ_GPM_SYSCKEN_R] = {
+ .reg = MAX8925_ON_OFF_IRQ2,
+ .mask_reg = MAX8925_ON_OFF_IRQ2_MASK,
+ .offs = 1 << 1,
+ },
+ [MAX8925_IRQ_RTC_ALARM1] = {
+ .reg = MAX8925_RTC_IRQ,
+ .mask_reg = MAX8925_RTC_IRQ_MASK,
+ .offs = 1 << 2,
+ .flags = FLAGS_RTC,
+ },
+ [MAX8925_IRQ_RTC_ALARM0] = {
+ .reg = MAX8925_RTC_IRQ,
+ .mask_reg = MAX8925_RTC_IRQ_MASK,
+ .offs = 1 << 3,
+ .flags = FLAGS_RTC,
+ },
+ [MAX8925_IRQ_TSC_STICK] = {
+ .reg = MAX8925_TSC_IRQ,
+ .mask_reg = MAX8925_TSC_IRQ_MASK,
+ .offs = 1 << 0,
+ .flags = FLAGS_ADC,
+ .tsc_irq = 1,
+ },
+ [MAX8925_IRQ_TSC_NSTICK] = {
+ .reg = MAX8925_TSC_IRQ,
+ .mask_reg = MAX8925_TSC_IRQ_MASK,
+ .offs = 1 << 1,
+ .flags = FLAGS_ADC,
+ .tsc_irq = 1,
+ },
+};
+
+static inline struct max8925_irq_data *irq_to_max8925(struct max8925_chip *chip,
+ int irq)
+{
+ return &max8925_irqs[irq - chip->irq_base];
+}
+
+static irqreturn_t max8925_irq(int irq, void *data)
+{
+ struct max8925_chip *chip = data;
+ struct max8925_irq_data *irq_data;
+ struct i2c_client *i2c;
+ int read_reg = -1, value = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
+ irq_data = &max8925_irqs[i];
+ /* TSC IRQ should be serviced in max8925_tsc_irq() */
+ if (irq_data->tsc_irq)
+ continue;
+ if (irq_data->flags == FLAGS_RTC)
+ i2c = chip->rtc;
+ else if (irq_data->flags == FLAGS_ADC)
+ i2c = chip->adc;
+ else
+ i2c = chip->i2c;
+ if (read_reg != irq_data->reg) {
+ read_reg = irq_data->reg;
+ value = max8925_reg_read(i2c, irq_data->reg);
+ }
+ if (value & irq_data->enable)
+ handle_nested_irq(chip->irq_base + i);
+ }
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t max8925_tsc_irq(int irq, void *data)
+{
+ struct max8925_chip *chip = data;
+ struct max8925_irq_data *irq_data;
+ struct i2c_client *i2c;
+ int read_reg = -1, value = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
+ irq_data = &max8925_irqs[i];
+ /* non TSC IRQ should be serviced in max8925_irq() */
+ if (!irq_data->tsc_irq)
+ continue;
+ if (irq_data->flags == FLAGS_RTC)
+ i2c = chip->rtc;
+ else if (irq_data->flags == FLAGS_ADC)
+ i2c = chip->adc;
+ else
+ i2c = chip->i2c;
+ if (read_reg != irq_data->reg) {
+ read_reg = irq_data->reg;
+ value = max8925_reg_read(i2c, irq_data->reg);
+ }
+ if (value & irq_data->enable)
+ handle_nested_irq(chip->irq_base + i);
+ }
+ return IRQ_HANDLED;
+}
+
+static void max8925_irq_lock(unsigned int irq)
+{
+ struct max8925_chip *chip = get_irq_chip_data(irq);
+
+ mutex_lock(&chip->irq_lock);
+}
+
+static void max8925_irq_sync_unlock(unsigned int irq)
+{
+ struct max8925_chip *chip = get_irq_chip_data(irq);
+ struct max8925_irq_data *irq_data;
+ static unsigned char cache_chg[2] = {0xff, 0xff};
+ static unsigned char cache_on[2] = {0xff, 0xff};
+ static unsigned char cache_rtc = 0xff, cache_tsc = 0xff;
+ unsigned char irq_chg[2], irq_on[2];
+ unsigned char irq_rtc, irq_tsc;
+ int i;
+
+ /* Load cached value. In initial, all IRQs are masked */
+ irq_chg[0] = cache_chg[0];
+ irq_chg[1] = cache_chg[1];
+ irq_on[0] = cache_on[0];
+ irq_on[1] = cache_on[1];
+ irq_rtc = cache_rtc;
+ irq_tsc = cache_tsc;
+ for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
+ irq_data = &max8925_irqs[i];
+ switch (irq_data->mask_reg) {
+ case MAX8925_CHG_IRQ1_MASK:
+ irq_chg[0] &= irq_data->enable;
+ break;
+ case MAX8925_CHG_IRQ2_MASK:
+ irq_chg[1] &= irq_data->enable;
+ break;
+ case MAX8925_ON_OFF_IRQ1_MASK:
+ irq_on[0] &= irq_data->enable;
+ break;
+ case MAX8925_ON_OFF_IRQ2_MASK:
+ irq_on[1] &= irq_data->enable;
+ break;
+ case MAX8925_RTC_IRQ_MASK:
+ irq_rtc &= irq_data->enable;
+ break;
+ case MAX8925_TSC_IRQ_MASK:
+ irq_tsc &= irq_data->enable;
+ break;
+ default:
+ dev_err(chip->dev, "wrong IRQ\n");
+ break;
+ }
+ }
+ /* update mask into registers */
+ if (cache_chg[0] != irq_chg[0]) {
+ cache_chg[0] = irq_chg[0];
+ max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ1_MASK,
+ irq_chg[0]);
+ }
+ if (cache_chg[1] != irq_chg[1]) {
+ cache_chg[1] = irq_chg[1];
+ max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ2_MASK,
+ irq_chg[1]);
+ }
+ if (cache_on[0] != irq_on[0]) {
+ cache_on[0] = irq_on[0];
+ max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ1_MASK,
+ irq_on[0]);
+ }
+ if (cache_on[1] != irq_on[1]) {
+ cache_on[1] = irq_on[1];
+ max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ2_MASK,
+ irq_on[1]);
+ }
+ if (cache_rtc != irq_rtc) {
+ cache_rtc = irq_rtc;
+ max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, irq_rtc);
+ }
+ if (cache_tsc != irq_tsc) {
+ cache_tsc = irq_tsc;
+ max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, irq_tsc);
+ }
+
+ mutex_unlock(&chip->irq_lock);
+}
+
+static void max8925_irq_enable(unsigned int irq)
+{
+ struct max8925_chip *chip = get_irq_chip_data(irq);
+ max8925_irqs[irq - chip->irq_base].enable
+ = max8925_irqs[irq - chip->irq_base].offs;
+}
+
+static void max8925_irq_disable(unsigned int irq)
+{
+ struct max8925_chip *chip = get_irq_chip_data(irq);
+ max8925_irqs[irq - chip->irq_base].enable = 0;
+}
+
+static struct irq_chip max8925_irq_chip = {
+ .name = "max8925",
+ .bus_lock = max8925_irq_lock,
+ .bus_sync_unlock = max8925_irq_sync_unlock,
+ .enable = max8925_irq_enable,
+ .disable = max8925_irq_disable,
+};
+
+static int max8925_irq_init(struct max8925_chip *chip, int irq,
+ struct max8925_platform_data *pdata)
+{
+ unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
+ struct irq_desc *desc;
+ int i, ret;
+ int __irq;
+
+ if (!pdata || !pdata->irq_base) {
+ dev_warn(chip->dev, "No interrupt support on IRQ base\n");
+ return -EINVAL;
+ }
+ /* clear all interrupts */
+ max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ1);
+ max8925_reg_read(chip->i2c, MAX8925_CHG_IRQ2);
+ max8925_reg_read(chip->i2c, MAX8925_ON_OFF_IRQ1);
+ max8925_reg_read(chip->i2c, MAX8925_ON_OFF_IRQ2);
+ max8925_reg_read(chip->rtc, MAX8925_RTC_IRQ);
+ max8925_reg_read(chip->adc, MAX8925_TSC_IRQ);
+ /* mask all interrupts */
+ max8925_reg_write(chip->rtc, MAX8925_ALARM0_CNTL, 0);
+ max8925_reg_write(chip->rtc, MAX8925_ALARM1_CNTL, 0);
+ max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ1_MASK, 0xff);
+ max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ2_MASK, 0xff);
+ max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ1_MASK, 0xff);
+ max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ2_MASK, 0xff);
+ max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, 0xff);
+ max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, 0xff);
+
+ mutex_init(&chip->irq_lock);
+ chip->core_irq = irq;
+ chip->irq_base = pdata->irq_base;
+ desc = irq_to_desc(chip->core_irq);
+
+ /* register with genirq */
+ for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
+ __irq = i + chip->irq_base;
+ set_irq_chip_data(__irq, chip);
+ set_irq_chip_and_handler(__irq, &max8925_irq_chip,
+ handle_edge_irq);
+ set_irq_nested_thread(__irq, 1);
+#ifdef CONFIG_ARM
+ set_irq_flags(__irq, IRQF_VALID);
+#else
+ set_irq_noprobe(__irq);
+#endif
+ }
+ if (!irq) {
+ dev_warn(chip->dev, "No interrupt support on core IRQ\n");
+ goto tsc_irq;
+ }
+
+ ret = request_threaded_irq(irq, NULL, max8925_irq, flags,
+ "max8925", chip);
+ if (ret) {
+ dev_err(chip->dev, "Failed to request core IRQ: %d\n", ret);
+ chip->core_irq = 0;
+ }
+tsc_irq:
+ if (!pdata->tsc_irq) {
+ dev_warn(chip->dev, "No interrupt support on TSC IRQ\n");
+ return 0;
+ }
+ chip->tsc_irq = pdata->tsc_irq;
+
+ ret = request_threaded_irq(chip->tsc_irq, NULL, max8925_tsc_irq,
+ flags, "max8925-tsc", chip);
+ if (ret) {
+ dev_err(chip->dev, "Failed to request TSC IRQ: %d\n", ret);
+ chip->tsc_irq = 0;
+ }
+ return 0;
+}
+
+int __devinit max8925_device_init(struct max8925_chip *chip,
+ struct max8925_platform_data *pdata)
+{
+ int ret;
+
+ max8925_irq_init(chip, chip->i2c->irq, pdata);
+
+ if (pdata && (pdata->power || pdata->touch)) {
+ /* enable ADC to control internal reference */
+ max8925_set_bits(chip->i2c, MAX8925_RESET_CNFG, 1, 1);
+ /* enable internal reference for ADC */
+ max8925_set_bits(chip->adc, MAX8925_TSC_CNFG1, 3, 2);
+ /* check for internal reference IRQ */
+ do {
+ ret = max8925_reg_read(chip->adc, MAX8925_TSC_IRQ);
+ } while (ret & MAX8925_NREF_OK);
+ /* enaable ADC scheduler, interval is 1 second */
+ max8925_set_bits(chip->adc, MAX8925_ADC_SCHED, 3, 2);
+ }
+
+ /* enable Momentary Power Loss */
+ max8925_set_bits(chip->rtc, MAX8925_MPL_CNTL, 1 << 4, 1 << 4);
+
+ ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
+ ARRAY_SIZE(rtc_devs),
+ &rtc_resources[0], 0);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to add rtc subdev\n");
+ goto out;
+ }
+ if (pdata && pdata->regulator[0]) {
+ ret = mfd_add_devices(chip->dev, 0, &regulator_devs[0],
+ ARRAY_SIZE(regulator_devs),
+ &regulator_resources[0], 0);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to add regulator subdev\n");
+ goto out_dev;
+ }
+ }
+
+ if (pdata && pdata->backlight) {
+ ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0],
+ ARRAY_SIZE(backlight_devs),
+ &backlight_resources[0], 0);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to add backlight subdev\n");
+ goto out_dev;
+ }
+ }
+
+ if (pdata && pdata->power) {
+ ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
+ ARRAY_SIZE(power_devs),
+ &power_supply_resources[0], 0);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to add power supply "
+ "subdev\n");
+ goto out_dev;
+ }
+ }
+
+ if (pdata && pdata->touch) {
+ ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
+ ARRAY_SIZE(touch_devs),
+ &touch_resources[0], 0);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to add touch subdev\n");
+ goto out_dev;
+ }
+ }
+
+ return 0;
+out_dev:
+ mfd_remove_devices(chip->dev);
+out:
+ return ret;
+}
+
+void __devexit max8925_device_exit(struct max8925_chip *chip)
+{
+ if (chip->core_irq)
+ free_irq(chip->core_irq, chip);
+ if (chip->tsc_irq)
+ free_irq(chip->tsc_irq, chip);
+ mfd_remove_devices(chip->dev);
+}
+
+
+MODULE_DESCRIPTION("PMIC Driver for Maxim MAX8925");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c
new file mode 100644
index 00000000000..c0b883c14f4
--- /dev/null
+++ b/drivers/mfd/max8925-i2c.c
@@ -0,0 +1,211 @@
+/*
+ * I2C driver for Maxim MAX8925
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ * Haojian Zhuang <haojian.zhuang@marvell.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/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/mfd/max8925.h>
+
+#define RTC_I2C_ADDR 0x68
+#define ADC_I2C_ADDR 0x47
+
+static inline int max8925_read_device(struct i2c_client *i2c,
+ int reg, int bytes, void *dest)
+{
+ int ret;
+
+ if (bytes > 1)
+ ret = i2c_smbus_read_i2c_block_data(i2c, reg, bytes, dest);
+ else {
+ ret = i2c_smbus_read_byte_data(i2c, reg);
+ if (ret < 0)
+ return ret;
+ *(unsigned char *)dest = (unsigned char)ret;
+ }
+ return ret;
+}
+
+static inline int max8925_write_device(struct i2c_client *i2c,
+ int reg, int bytes, void *src)
+{
+ unsigned char buf[bytes + 1];
+ int ret;
+
+ buf[0] = (unsigned char)reg;
+ memcpy(&buf[1], src, bytes);
+
+ ret = i2c_master_send(i2c, buf, bytes + 1);
+ if (ret < 0)
+ return ret;
+ return 0;
+}
+
+int max8925_reg_read(struct i2c_client *i2c, int reg)
+{
+ struct max8925_chip *chip = i2c_get_clientdata(i2c);
+ unsigned char data = 0;
+ int ret;
+
+ mutex_lock(&chip->io_lock);
+ ret = max8925_read_device(i2c, reg, 1, &data);
+ mutex_unlock(&chip->io_lock);
+
+ if (ret < 0)
+ return ret;
+ else
+ return (int)data;
+}
+EXPORT_SYMBOL(max8925_reg_read);
+
+int max8925_reg_write(struct i2c_client *i2c, int reg,
+ unsigned char data)
+{
+ struct max8925_chip *chip = i2c_get_clientdata(i2c);
+ int ret;
+
+ mutex_lock(&chip->io_lock);
+ ret = max8925_write_device(i2c, reg, 1, &data);
+ mutex_unlock(&chip->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(max8925_reg_write);
+
+int max8925_bulk_read(struct i2c_client *i2c, int reg,
+ int count, unsigned char *buf)
+{
+ struct max8925_chip *chip = i2c_get_clientdata(i2c);
+ int ret;
+
+ mutex_lock(&chip->io_lock);
+ ret = max8925_read_device(i2c, reg, count, buf);
+ mutex_unlock(&chip->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(max8925_bulk_read);
+
+int max8925_bulk_write(struct i2c_client *i2c, int reg,
+ int count, unsigned char *buf)
+{
+ struct max8925_chip *chip = i2c_get_clientdata(i2c);
+ int ret;
+
+ mutex_lock(&chip->io_lock);
+ ret = max8925_write_device(i2c, reg, count, buf);
+ mutex_unlock(&chip->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(max8925_bulk_write);
+
+int max8925_set_bits(struct i2c_client *i2c, int reg,
+ unsigned char mask, unsigned char data)
+{
+ struct max8925_chip *chip = i2c_get_clientdata(i2c);
+ unsigned char value;
+ int ret;
+
+ mutex_lock(&chip->io_lock);
+ ret = max8925_read_device(i2c, reg, 1, &value);
+ if (ret < 0)
+ goto out;
+ value &= ~mask;
+ value |= data;
+ ret = max8925_write_device(i2c, reg, 1, &value);
+out:
+ mutex_unlock(&chip->io_lock);
+ return ret;
+}
+EXPORT_SYMBOL(max8925_set_bits);
+
+
+static const struct i2c_device_id max8925_id_table[] = {
+ { "max8925", 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, max8925_id_table);
+
+static int __devinit max8925_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct max8925_platform_data *pdata = client->dev.platform_data;
+ static struct max8925_chip *chip;
+
+ if (!pdata) {
+ pr_info("%s: platform data is missing\n", __func__);
+ return -EINVAL;
+ }
+
+ chip = kzalloc(sizeof(struct max8925_chip), GFP_KERNEL);
+ if (chip == NULL)
+ return -ENOMEM;
+ chip->i2c = client;
+ chip->dev = &client->dev;
+ i2c_set_clientdata(client, chip);
+ dev_set_drvdata(chip->dev, chip);
+ mutex_init(&chip->io_lock);
+
+ chip->rtc = i2c_new_dummy(chip->i2c->adapter, RTC_I2C_ADDR);
+ i2c_set_clientdata(chip->rtc, chip);
+
+ chip->adc = i2c_new_dummy(chip->i2c->adapter, ADC_I2C_ADDR);
+ i2c_set_clientdata(chip->adc, chip);
+
+ max8925_device_init(chip, pdata);
+
+ return 0;
+}
+
+static int __devexit max8925_remove(struct i2c_client *client)
+{
+ struct max8925_chip *chip = i2c_get_clientdata(client);
+
+ max8925_device_exit(chip);
+ i2c_unregister_device(chip->adc);
+ i2c_unregister_device(chip->rtc);
+ i2c_set_clientdata(chip->adc, NULL);
+ i2c_set_clientdata(chip->rtc, NULL);
+ i2c_set_clientdata(chip->i2c, NULL);
+ kfree(chip);
+ return 0;
+}
+
+static struct i2c_driver max8925_driver = {
+ .driver = {
+ .name = "max8925",
+ .owner = THIS_MODULE,
+ },
+ .probe = max8925_probe,
+ .remove = __devexit_p(max8925_remove),
+ .id_table = max8925_id_table,
+};
+
+static int __init max8925_i2c_init(void)
+{
+ int ret;
+
+ ret = i2c_add_driver(&max8925_driver);
+ if (ret != 0)
+ pr_err("Failed to register MAX8925 I2C driver: %d\n", ret);
+ return ret;
+}
+subsys_initcall(max8925_i2c_init);
+
+static void __exit max8925_i2c_exit(void)
+{
+ i2c_del_driver(&max8925_driver);
+}
+module_exit(max8925_i2c_exit);
+
+MODULE_DESCRIPTION("I2C Driver for Maxim 8925");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/mc13783-core.c b/drivers/mfd/mc13783-core.c
index 735c8a4d164..62a847e4c2d 100644
--- a/drivers/mfd/mc13783-core.c
+++ b/drivers/mfd/mc13783-core.c
@@ -225,7 +225,7 @@ int mc13783_reg_rmw(struct mc13783 *mc13783, unsigned int offset,
}
EXPORT_SYMBOL(mc13783_reg_rmw);
-int mc13783_mask(struct mc13783 *mc13783, int irq)
+int mc13783_irq_mask(struct mc13783 *mc13783, int irq)
{
int ret;
unsigned int offmask = irq < 24 ? MC13783_IRQMASK0 : MC13783_IRQMASK1;
@@ -245,9 +245,9 @@ int mc13783_mask(struct mc13783 *mc13783, int irq)
return mc13783_reg_write(mc13783, offmask, mask | irqbit);
}
-EXPORT_SYMBOL(mc13783_mask);
+EXPORT_SYMBOL(mc13783_irq_mask);
-int mc13783_unmask(struct mc13783 *mc13783, int irq)
+int mc13783_irq_unmask(struct mc13783 *mc13783, int irq)
{
int ret;
unsigned int offmask = irq < 24 ? MC13783_IRQMASK0 : MC13783_IRQMASK1;
@@ -267,7 +267,53 @@ int mc13783_unmask(struct mc13783 *mc13783, int irq)
return mc13783_reg_write(mc13783, offmask, mask & ~irqbit);
}
-EXPORT_SYMBOL(mc13783_unmask);
+EXPORT_SYMBOL(mc13783_irq_unmask);
+
+int mc13783_irq_status(struct mc13783 *mc13783, int irq,
+ int *enabled, int *pending)
+{
+ int ret;
+ unsigned int offmask = irq < 24 ? MC13783_IRQMASK0 : MC13783_IRQMASK1;
+ unsigned int offstat = irq < 24 ? MC13783_IRQSTAT0 : MC13783_IRQSTAT1;
+ u32 irqbit = 1 << (irq < 24 ? irq : irq - 24);
+
+ if (irq < 0 || irq >= MC13783_NUM_IRQ)
+ return -EINVAL;
+
+ if (enabled) {
+ u32 mask;
+
+ ret = mc13783_reg_read(mc13783, offmask, &mask);
+ if (ret)
+ return ret;
+
+ *enabled = mask & irqbit;
+ }
+
+ if (pending) {
+ u32 stat;
+
+ ret = mc13783_reg_read(mc13783, offstat, &stat);
+ if (ret)
+ return ret;
+
+ *pending = stat & irqbit;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(mc13783_irq_status);
+
+int mc13783_irq_ack(struct mc13783 *mc13783, int irq)
+{
+ unsigned int offstat = irq < 24 ? MC13783_IRQSTAT0 : MC13783_IRQSTAT1;
+ unsigned int val = 1 << (irq < 24 ? irq : irq - 24);
+
+ BUG_ON(irq < 0 || irq >= MC13783_NUM_IRQ);
+
+ return mc13783_reg_write(mc13783, offstat, val);
+}
+EXPORT_SYMBOL(mc13783_irq_ack);
int mc13783_irq_request_nounmask(struct mc13783 *mc13783, int irq,
irq_handler_t handler, const char *name, void *dev)
@@ -297,7 +343,7 @@ int mc13783_irq_request(struct mc13783 *mc13783, int irq,
if (ret)
return ret;
- ret = mc13783_unmask(mc13783, irq);
+ ret = mc13783_irq_unmask(mc13783, irq);
if (ret) {
mc13783->irqhandler[irq] = NULL;
mc13783->irqdata[irq] = NULL;
@@ -317,7 +363,7 @@ int mc13783_irq_free(struct mc13783 *mc13783, int irq, void *dev)
mc13783->irqdata[irq] != dev)
return -EINVAL;
- ret = mc13783_mask(mc13783, irq);
+ ret = mc13783_irq_mask(mc13783, irq);
if (ret)
return ret;
@@ -333,17 +379,6 @@ static inline irqreturn_t mc13783_irqhandler(struct mc13783 *mc13783, int irq)
return mc13783->irqhandler[irq](irq, mc13783->irqdata[irq]);
}
-int mc13783_ackirq(struct mc13783 *mc13783, int irq)
-{
- unsigned int offstat = irq < 24 ? MC13783_IRQSTAT0 : MC13783_IRQSTAT1;
- unsigned int val = 1 << (irq < 24 ? irq : irq - 24);
-
- BUG_ON(irq < 0 || irq >= MC13783_NUM_IRQ);
-
- return mc13783_reg_write(mc13783, offstat, val);
-}
-EXPORT_SYMBOL(mc13783_ackirq);
-
/*
* returns: number of handled irqs or negative error
* locking: holds mc13783->lock
@@ -422,7 +457,7 @@ static irqreturn_t mc13783_handler_adcdone(int irq, void *data)
{
struct mc13783_adcdone_data *adcdone_data = data;
- mc13783_ackirq(adcdone_data->mc13783, irq);
+ mc13783_irq_ack(adcdone_data->mc13783, irq);
complete_all(&adcdone_data->done);
@@ -486,7 +521,7 @@ int mc13783_adc_do_conversion(struct mc13783 *mc13783, unsigned int mode,
dev_dbg(&mc13783->spidev->dev, "%s: request irq\n", __func__);
mc13783_irq_request(mc13783, MC13783_IRQ_ADCDONE,
mc13783_handler_adcdone, __func__, &adcdone_data);
- mc13783_ackirq(mc13783, MC13783_IRQ_ADCDONE);
+ mc13783_irq_ack(mc13783, MC13783_IRQ_ADCDONE);
mc13783_reg_write(mc13783, MC13783_REG_ADC_0, adc0);
mc13783_reg_write(mc13783, MC13783_REG_ADC_1, adc1);
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index ae15e495e20..aa17f4bddc5 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -13,6 +13,7 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
+#include <linux/acpi.h>
#include <linux/mfd/core.h>
static int mfd_add_device(struct device *parent, int id,
@@ -62,6 +63,10 @@ static int mfd_add_device(struct device *parent, int id,
res[r].start = cell->resources[r].start;
res[r].end = cell->resources[r].end;
}
+
+ ret = acpi_check_resource_conflict(res);
+ if (ret)
+ goto fail_res;
}
platform_device_add_resources(pdev, res, cell->num_resources);
diff --git a/drivers/mfd/sh_mobile_sdhi.c b/drivers/mfd/sh_mobile_sdhi.c
index 03efae8041a..468fd366d4d 100644
--- a/drivers/mfd/sh_mobile_sdhi.c
+++ b/drivers/mfd/sh_mobile_sdhi.c
@@ -21,7 +21,7 @@
#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
-
+#include <linux/mmc/host.h>
#include <linux/mfd/core.h>
#include <linux/mfd/tmio.h>
#include <linux/mfd/sh_mobile_sdhi.h>
@@ -95,9 +95,9 @@ static int __init sh_mobile_sdhi_probe(struct platform_device *pdev)
clk_enable(priv->clk);
- /* FIXME: silly const unsigned int hclk */
- *(unsigned int *)&priv->mmc_data.hclk = clk_get_rate(priv->clk);
+ priv->mmc_data.hclk = clk_get_rate(priv->clk);
priv->mmc_data.set_pwr = sh_mobile_sdhi_set_pwr;
+ priv->mmc_data.capabilities = MMC_CAP_MMC_HIGHSPEED;
memcpy(&priv->cell_mmc, &sh_mobile_sdhi_cell, sizeof(priv->cell_mmc));
priv->cell_mmc.driver_data = &priv->mmc_data;
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 0cc5eeff5ee..dc9ea95c056 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -1430,7 +1430,7 @@ static int __devinit sm501_plat_probe(struct platform_device *dev)
}
sm->regs_claim = request_mem_region(sm->io_res->start,
- 0x100, "sm501");
+ resource_size(sm->io_res), "sm501");
if (sm->regs_claim == NULL) {
dev_err(&dev->dev, "cannot claim registers\n");
@@ -1440,8 +1440,7 @@ static int __devinit sm501_plat_probe(struct platform_device *dev)
platform_set_drvdata(dev, sm);
- sm->regs = ioremap(sm->io_res->start,
- (sm->io_res->end - sm->io_res->start) - 1);
+ sm->regs = ioremap(sm->io_res->start, resource_size(sm->io_res));
if (sm->regs == NULL) {
dev_err(&dev->dev, "cannot remap registers\n");
@@ -1645,7 +1644,7 @@ static int __devinit sm501_pci_probe(struct pci_dev *dev,
sm->mem_res = &dev->resource[0];
sm->regs_claim = request_mem_region(sm->io_res->start,
- 0x100, "sm501");
+ resource_size(sm->io_res), "sm501");
if (sm->regs_claim == NULL) {
dev_err(&dev->dev, "cannot claim registers\n");
err= -EBUSY;
diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c
index bcf4687d4af..26d9176fca9 100644
--- a/drivers/mfd/t7l66xb.c
+++ b/drivers/mfd/t7l66xb.c
@@ -360,7 +360,7 @@ static int t7l66xb_probe(struct platform_device *dev)
if (ret)
goto err_request_scr;
- t7l66xb->scr = ioremap(rscr->start, rscr->end - rscr->start + 1);
+ t7l66xb->scr = ioremap(rscr->start, resource_size(rscr));
if (!t7l66xb->scr) {
ret = -ENOMEM;
goto err_ioremap;
@@ -403,12 +403,12 @@ static int t7l66xb_probe(struct platform_device *dev)
err_ioremap:
release_resource(&t7l66xb->rscr);
err_request_scr:
- kfree(t7l66xb);
clk_put(t7l66xb->clk48m);
err_clk48m_get:
clk_put(t7l66xb->clk32k);
err_clk32k_get:
err_noirq:
+ kfree(t7l66xb);
return ret;
}
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
index 4bc5a08a2b0..c59e5c5737d 100644
--- a/drivers/mfd/tc6393xb.c
+++ b/drivers/mfd/tc6393xb.c
@@ -647,7 +647,7 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
if (ret)
goto err_request_scr;
- tc6393xb->scr = ioremap(rscr->start, rscr->end - rscr->start + 1);
+ tc6393xb->scr = ioremap(rscr->start, resource_size(rscr));
if (!tc6393xb->scr) {
ret = -ENOMEM;
goto err_ioremap;
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 19a930d0624..562cd4935e1 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -58,13 +58,6 @@
#define DRIVER_NAME "twl"
-#if defined(CONFIG_TWL4030_BCI_BATTERY) || \
- defined(CONFIG_TWL4030_BCI_BATTERY_MODULE)
-#define twl_has_bci() true
-#else
-#define twl_has_bci() false
-#endif
-
#if defined(CONFIG_KEYBOARD_TWL4030) || defined(CONFIG_KEYBOARD_TWL4030_MODULE)
#define twl_has_keypad() true
#else
@@ -130,7 +123,7 @@
#define TWL_NUM_SLAVES 4
#if defined(CONFIG_INPUT_TWL4030_PWRBUTTON) \
- || defined(CONFIG_INPUT_TWL4030_PWBUTTON_MODULE)
+ || defined(CONFIG_INPUT_TWL4030_PWRBUTTON_MODULE)
#define twl_has_pwrbutton() true
#else
#define twl_has_pwrbutton() false
@@ -205,6 +198,7 @@
/* subchip/slave 3 0x4B - AUDIO */
#define TWL6030_BASEADD_AUDIO 0x0000
#define TWL6030_BASEADD_RSV 0x0000
+#define TWL6030_BASEADD_ZERO 0x0000
/* Few power values */
#define R_CFG_BOOT 0x05
@@ -320,9 +314,11 @@ static struct twl_mapping twl6030_map[] = {
{ SUB_CHIP_ID1, TWL6030_BASEADD_CHARGER },
{ SUB_CHIP_ID1, TWL6030_BASEADD_GASGAUGE },
{ SUB_CHIP_ID1, TWL6030_BASEADD_PWM },
- { SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
- { SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
+ { SUB_CHIP_ID0, TWL6030_BASEADD_ZERO },
+ { SUB_CHIP_ID1, TWL6030_BASEADD_ZERO },
+ { SUB_CHIP_ID2, TWL6030_BASEADD_ZERO },
+ { SUB_CHIP_ID2, TWL6030_BASEADD_ZERO },
{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
{ SUB_CHIP_ID2, TWL6030_BASEADD_RSV },
@@ -588,18 +584,6 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
struct device *child;
unsigned sub_chip_id;
- if (twl_has_bci() && pdata->bci &&
- !(features & (TPS_SUBSET | TWL5031))) {
- child = add_child(3, "twl4030_bci",
- pdata->bci, sizeof(*pdata->bci),
- false,
- /* irq0 = CHG_PRES, irq1 = BCI */
- pdata->irq_base + BCI_PRES_INTR_OFFSET,
- pdata->irq_base + BCI_INTR_OFFSET);
- if (IS_ERR(child))
- return PTR_ERR(child);
- }
-
if (twl_has_gpio() && pdata->gpio) {
child = add_child(SUB_CHIP_ID1, "twl4030_gpio",
pdata->gpio, sizeof(*pdata->gpio),
@@ -977,6 +961,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
int status;
unsigned i;
struct twl4030_platform_data *pdata = client->dev.platform_data;
+ u8 temp;
if (!pdata) {
dev_dbg(&client->dev, "no platform data?\n");
@@ -1044,6 +1029,18 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
goto fail;
}
+ /* Disable TWL4030/TWL5030 I2C Pull-up on I2C1 and I2C4(SR) interface.
+ * Program I2C_SCL_CTRL_PU(bit 0)=0, I2C_SDA_CTRL_PU (bit 2)=0,
+ * SR_I2C_SCL_CTRL_PU(bit 4)=0 and SR_I2C_SDA_CTRL_PU(bit 6)=0.
+ */
+
+ if (twl_class_is_4030()) {
+ twl_i2c_read_u8(TWL4030_MODULE_INTBR, &temp, REG_GPPUPDCTR1);
+ temp &= ~(SR_I2C_SDA_CTRL_PU | SR_I2C_SCL_CTRL_PU | \
+ I2C_SDA_CTRL_PU | I2C_SCL_CTRL_PU);
+ twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);
+ }
+
status = add_children(pdata, id->driver_data);
fail:
if (status < 0)
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
index 0815292fdaf..7efa8789a3a 100644
--- a/drivers/mfd/twl4030-power.c
+++ b/drivers/mfd/twl4030-power.c
@@ -405,7 +405,7 @@ static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig)
if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) {
remap &= ~SLEEP_STATE_MASK;
- remap |= rconfig->remap_off << SLEEP_STATE_SHIFT;
+ remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT;
}
err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
@@ -461,6 +461,56 @@ out:
return err;
}
+int twl4030_remove_script(u8 flags)
+{
+ int err = 0;
+
+ err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, R_KEY_1,
+ R_PROTECT_KEY);
+ if (err) {
+ pr_err("twl4030: unable to unlock PROTECT_KEY\n");
+ return err;
+ }
+
+ err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, R_KEY_2,
+ R_PROTECT_KEY);
+ if (err) {
+ pr_err("twl4030: unable to unlock PROTECT_KEY\n");
+ return err;
+ }
+
+ if (flags & TWL4030_WRST_SCRIPT) {
+ err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
+ R_SEQ_ADD_WARM);
+ if (err)
+ return err;
+ }
+ if (flags & TWL4030_WAKEUP12_SCRIPT) {
+ if (err)
+ err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
+ R_SEQ_ADD_S2A12);
+ return err;
+ }
+ if (flags & TWL4030_WAKEUP3_SCRIPT) {
+ err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
+ R_SEQ_ADD_S2A3);
+ if (err)
+ return err;
+ }
+ if (flags & TWL4030_SLEEP_SCRIPT) {
+ err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, END_OF_SCRIPT,
+ R_SEQ_ADD_A2S);
+ if (err)
+ return err;
+ }
+
+ err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, R_PROTECT_KEY);
+ if (err)
+ pr_err("TWL4030 Unable to relock registers\n");
+
+ return err;
+}
+
void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
{
int err = 0;
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c
index 252b74188ec..b281217334e 100644
--- a/drivers/mfd/ucb1x00-core.c
+++ b/drivers/mfd/ucb1x00-core.c
@@ -27,6 +27,7 @@
#include <linux/mutex.h>
#include <linux/mfd/ucb1x00.h>
#include <linux/gpio.h>
+#include <linux/semaphore.h>
#include <mach/dma.h>
#include <mach/hardware.h>
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index 4b2021af1d9..07101e9e1cb 100644
--- a/drivers/mfd/wm831x-core.c
+++ b/drivers/mfd/wm831x-core.c
@@ -321,7 +321,6 @@ EXPORT_SYMBOL_GPL(wm831x_set_bits);
*/
int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
{
- int tries = 10;
int ret, src;
mutex_lock(&wm831x->auxadc_lock);
@@ -349,13 +348,14 @@ int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input)
goto disable;
}
- do {
- msleep(1);
+ /* Ignore the result to allow us to soldier on without IRQ hookup */
+ wait_for_completion_timeout(&wm831x->auxadc_done, msecs_to_jiffies(5));
- ret = wm831x_reg_read(wm831x, WM831X_AUXADC_CONTROL);
- if (ret < 0)
- ret = WM831X_AUX_CVT_ENA;
- } while ((ret & WM831X_AUX_CVT_ENA) && --tries);
+ ret = wm831x_reg_read(wm831x, WM831X_AUXADC_CONTROL);
+ if (ret < 0) {
+ dev_err(wm831x->dev, "AUXADC status read failed: %d\n", ret);
+ goto disable;
+ }
if (ret & WM831X_AUX_CVT_ENA) {
dev_err(wm831x->dev, "Timed out reading AUXADC\n");
@@ -390,6 +390,15 @@ out:
}
EXPORT_SYMBOL_GPL(wm831x_auxadc_read);
+static irqreturn_t wm831x_auxadc_irq(int irq, void *irq_data)
+{
+ struct wm831x *wm831x = irq_data;
+
+ complete(&wm831x->auxadc_done);
+
+ return IRQ_HANDLED;
+}
+
/**
* wm831x_auxadc_read_uv: Read a voltage from the WM831x AUXADC
*
@@ -1411,6 +1420,7 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
mutex_init(&wm831x->io_lock);
mutex_init(&wm831x->key_lock);
mutex_init(&wm831x->auxadc_lock);
+ init_completion(&wm831x->auxadc_done);
dev_set_drvdata(wm831x->dev, wm831x);
ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID);
@@ -1449,18 +1459,33 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
case WM8310:
parent = WM8310;
wm831x->num_gpio = 16;
+ if (rev > 0) {
+ wm831x->has_gpio_ena = 1;
+ wm831x->has_cs_sts = 1;
+ }
+
dev_info(wm831x->dev, "WM8310 revision %c\n", 'A' + rev);
break;
case WM8311:
parent = WM8311;
wm831x->num_gpio = 16;
+ if (rev > 0) {
+ wm831x->has_gpio_ena = 1;
+ wm831x->has_cs_sts = 1;
+ }
+
dev_info(wm831x->dev, "WM8311 revision %c\n", 'A' + rev);
break;
case WM8312:
parent = WM8312;
wm831x->num_gpio = 16;
+ if (rev > 0) {
+ wm831x->has_gpio_ena = 1;
+ wm831x->has_cs_sts = 1;
+ }
+
dev_info(wm831x->dev, "WM8312 revision %c\n", 'A' + rev);
break;
@@ -1508,6 +1533,16 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
if (ret != 0)
goto err;
+ if (wm831x->irq_base) {
+ ret = request_threaded_irq(wm831x->irq_base +
+ WM831X_IRQ_AUXADC_DATA,
+ NULL, wm831x_auxadc_irq, 0,
+ "auxadc", wm831x);
+ if (ret < 0)
+ dev_err(wm831x->dev, "AUXADC IRQ request failed: %d\n",
+ ret);
+ }
+
/* The core device is up, instantiate the subdevices. */
switch (parent) {
case WM8310:
@@ -1578,6 +1613,8 @@ static void wm831x_device_exit(struct wm831x *wm831x)
{
wm831x_otp_exit(wm831x);
mfd_remove_devices(wm831x->dev);
+ if (wm831x->irq_base)
+ free_irq(wm831x->irq_base + WM831X_IRQ_AUXADC_DATA, wm831x);
wm831x_irq_exit(wm831x);
kfree(wm831x);
}
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c
index 9a970bd6877..bd75807d530 100644
--- a/drivers/mfd/wm8350-core.c
+++ b/drivers/mfd/wm8350-core.c
@@ -339,7 +339,6 @@ EXPORT_SYMBOL_GPL(wm8350_reg_unlock);
int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)
{
u16 reg, result = 0;
- int tries = 5;
if (channel < WM8350_AUXADC_AUX1 || channel > WM8350_AUXADC_TEMP)
return -EINVAL;
@@ -363,12 +362,13 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)
reg |= 1 << channel | WM8350_AUXADC_POLL;
wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg);
- do {
- schedule_timeout_interruptible(1);
- reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1);
- } while ((reg & WM8350_AUXADC_POLL) && --tries);
+ /* We ignore the result of the completion and just check for a
+ * conversion result, allowing us to soldier on if the IRQ
+ * infrastructure is not set up for the chip. */
+ wait_for_completion_timeout(&wm8350->auxadc_done, msecs_to_jiffies(5));
- if (!tries)
+ reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1);
+ if (reg & WM8350_AUXADC_POLL)
dev_err(wm8350->dev, "adc chn %d read timeout\n", channel);
else
result = wm8350_reg_read(wm8350,
@@ -385,6 +385,15 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)
}
EXPORT_SYMBOL_GPL(wm8350_read_auxadc);
+static irqreturn_t wm8350_auxadc_irq(int irq, void *irq_data)
+{
+ struct wm8350 *wm8350 = irq_data;
+
+ complete(&wm8350->auxadc_done);
+
+ return IRQ_HANDLED;
+}
+
/*
* Cache is always host endian.
*/
@@ -682,11 +691,22 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
}
mutex_init(&wm8350->auxadc_mutex);
+ init_completion(&wm8350->auxadc_done);
ret = wm8350_irq_init(wm8350, irq, pdata);
if (ret < 0)
goto err;
+ if (wm8350->irq_base) {
+ ret = request_threaded_irq(wm8350->irq_base +
+ WM8350_IRQ_AUXADC_DATARDY,
+ NULL, wm8350_auxadc_irq, 0,
+ "auxadc", wm8350);
+ if (ret < 0)
+ dev_warn(wm8350->dev,
+ "Failed to request AUXADC IRQ: %d\n", ret);
+ }
+
if (pdata && pdata->init) {
ret = pdata->init(wm8350);
if (ret != 0) {
@@ -736,6 +756,9 @@ void wm8350_device_exit(struct wm8350 *wm8350)
platform_device_unregister(wm8350->gpio.pdev);
platform_device_unregister(wm8350->codec.pdev);
+ if (wm8350->irq_base)
+ free_irq(wm8350->irq_base + WM8350_IRQ_AUXADC_DATARDY, wm8350);
+
wm8350_irq_exit(wm8350);
kfree(wm8350->reg_cache);
diff --git a/drivers/mfd/wm8350-irq.c b/drivers/mfd/wm8350-irq.c
index 9025f29e270..f56c9adf949 100644
--- a/drivers/mfd/wm8350-irq.c
+++ b/drivers/mfd/wm8350-irq.c
@@ -18,7 +18,7 @@
#include <linux/bug.h>
#include <linux/device.h>
#include <linux/interrupt.h>
-#include <linux/workqueue.h>
+#include <linux/irq.h>
#include <linux/mfd/wm8350/core.h>
#include <linux/mfd/wm8350/audio.h>
@@ -29,8 +29,6 @@
#include <linux/mfd/wm8350/supply.h>
#include <linux/mfd/wm8350/wdt.h>
-#define WM8350_NUM_IRQ_REGS 7
-
#define WM8350_INT_OFFSET_1 0
#define WM8350_INT_OFFSET_2 1
#define WM8350_POWER_UP_INT_OFFSET 2
@@ -366,19 +364,10 @@ static struct wm8350_irq_data wm8350_irqs[] = {
},
};
-static void wm8350_irq_call_handler(struct wm8350 *wm8350, int irq)
+static inline struct wm8350_irq_data *irq_to_wm8350_irq(struct wm8350 *wm8350,
+ int irq)
{
- mutex_lock(&wm8350->irq_mutex);
-
- if (wm8350->irq[irq].handler)
- wm8350->irq[irq].handler(irq, wm8350->irq[irq].data);
- else {
- dev_err(wm8350->dev, "irq %d nobody cared. now masked.\n",
- irq);
- wm8350_mask_irq(wm8350, irq);
- }
-
- mutex_unlock(&wm8350->irq_mutex);
+ return &wm8350_irqs[irq - wm8350->irq_base];
}
/*
@@ -386,7 +375,9 @@ static void wm8350_irq_call_handler(struct wm8350 *wm8350, int irq)
* interrupts are clear on read the IRQ line will be reasserted and
* the physical IRQ will be handled again if another interrupt is
* asserted while we run - in the normal course of events this is a
- * rare occurrence so we save I2C/SPI reads.
+ * rare occurrence so we save I2C/SPI reads. We're also assuming that
+ * it's rare to get lots of interrupts firing simultaneously so try to
+ * minimise I/O.
*/
static irqreturn_t wm8350_irq(int irq, void *irq_data)
{
@@ -397,7 +388,6 @@ static irqreturn_t wm8350_irq(int irq, void *irq_data)
struct wm8350_irq_data *data;
int i;
- /* TODO: Use block reads to improve performance? */
level_one = wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS)
& ~wm8350_reg_read(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK);
@@ -416,93 +406,101 @@ static irqreturn_t wm8350_irq(int irq, void *irq_data)
sub_reg[data->reg] =
wm8350_reg_read(wm8350, WM8350_INT_STATUS_1 +
data->reg);
- sub_reg[data->reg] &=
- ~wm8350_reg_read(wm8350,
- WM8350_INT_STATUS_1_MASK +
- data->reg);
+ sub_reg[data->reg] &= ~wm8350->irq_masks[data->reg];
read_done[data->reg] = 1;
}
if (sub_reg[data->reg] & data->mask)
- wm8350_irq_call_handler(wm8350, i);
+ handle_nested_irq(wm8350->irq_base + i);
}
return IRQ_HANDLED;
}
-int wm8350_register_irq(struct wm8350 *wm8350, int irq,
- irq_handler_t handler, unsigned long flags,
- const char *name, void *data)
+static void wm8350_irq_lock(unsigned int irq)
{
- if (irq < 0 || irq >= WM8350_NUM_IRQ || !handler)
- return -EINVAL;
-
- if (wm8350->irq[irq].handler)
- return -EBUSY;
-
- mutex_lock(&wm8350->irq_mutex);
- wm8350->irq[irq].handler = handler;
- wm8350->irq[irq].data = data;
- mutex_unlock(&wm8350->irq_mutex);
-
- wm8350_unmask_irq(wm8350, irq);
+ struct wm8350 *wm8350 = get_irq_chip_data(irq);
- return 0;
+ mutex_lock(&wm8350->irq_lock);
}
-EXPORT_SYMBOL_GPL(wm8350_register_irq);
-int wm8350_free_irq(struct wm8350 *wm8350, int irq)
+static void wm8350_irq_sync_unlock(unsigned int irq)
{
- if (irq < 0 || irq >= WM8350_NUM_IRQ)
- return -EINVAL;
+ struct wm8350 *wm8350 = get_irq_chip_data(irq);
+ int i;
- wm8350_mask_irq(wm8350, irq);
+ for (i = 0; i < ARRAY_SIZE(wm8350->irq_masks); i++) {
+ /* If there's been a change in the mask write it back
+ * to the hardware. */
+ if (wm8350->irq_masks[i] !=
+ wm8350->reg_cache[WM8350_INT_STATUS_1_MASK + i])
+ WARN_ON(wm8350_reg_write(wm8350,
+ WM8350_INT_STATUS_1_MASK + i,
+ wm8350->irq_masks[i]));
+ }
- mutex_lock(&wm8350->irq_mutex);
- wm8350->irq[irq].handler = NULL;
- mutex_unlock(&wm8350->irq_mutex);
- return 0;
+ mutex_unlock(&wm8350->irq_lock);
}
-EXPORT_SYMBOL_GPL(wm8350_free_irq);
-int wm8350_mask_irq(struct wm8350 *wm8350, int irq)
+static void wm8350_irq_enable(unsigned int irq)
{
- return wm8350_set_bits(wm8350, WM8350_INT_STATUS_1_MASK +
- wm8350_irqs[irq].reg,
- wm8350_irqs[irq].mask);
+ struct wm8350 *wm8350 = get_irq_chip_data(irq);
+ struct wm8350_irq_data *irq_data = irq_to_wm8350_irq(wm8350, irq);
+
+ wm8350->irq_masks[irq_data->reg] &= ~irq_data->mask;
}
-EXPORT_SYMBOL_GPL(wm8350_mask_irq);
-int wm8350_unmask_irq(struct wm8350 *wm8350, int irq)
+static void wm8350_irq_disable(unsigned int irq)
{
- return wm8350_clear_bits(wm8350, WM8350_INT_STATUS_1_MASK +
- wm8350_irqs[irq].reg,
- wm8350_irqs[irq].mask);
+ struct wm8350 *wm8350 = get_irq_chip_data(irq);
+ struct wm8350_irq_data *irq_data = irq_to_wm8350_irq(wm8350, irq);
+
+ wm8350->irq_masks[irq_data->reg] |= irq_data->mask;
}
-EXPORT_SYMBOL_GPL(wm8350_unmask_irq);
+
+static struct irq_chip wm8350_irq_chip = {
+ .name = "wm8350",
+ .bus_lock = wm8350_irq_lock,
+ .bus_sync_unlock = wm8350_irq_sync_unlock,
+ .disable = wm8350_irq_disable,
+ .enable = wm8350_irq_enable,
+};
int wm8350_irq_init(struct wm8350 *wm8350, int irq,
struct wm8350_platform_data *pdata)
{
- int ret;
+ int ret, cur_irq, i;
int flags = IRQF_ONESHOT;
if (!irq) {
- dev_err(wm8350->dev, "No IRQ configured\n");
- return -EINVAL;
+ dev_warn(wm8350->dev, "No interrupt support, no core IRQ\n");
+ return 0;
+ }
+
+ if (!pdata || !pdata->irq_base) {
+ dev_warn(wm8350->dev, "No interrupt support, no IRQ base\n");
+ return 0;
}
+ /* Mask top level interrupts */
wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0xFFFF);
- wm8350_reg_write(wm8350, WM8350_INT_STATUS_1_MASK, 0xFFFF);
- wm8350_reg_write(wm8350, WM8350_INT_STATUS_2_MASK, 0xFFFF);
- wm8350_reg_write(wm8350, WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, 0xFFFF);
- wm8350_reg_write(wm8350, WM8350_GPIO_INT_STATUS_MASK, 0xFFFF);
- wm8350_reg_write(wm8350, WM8350_COMPARATOR_INT_STATUS_MASK, 0xFFFF);
- mutex_init(&wm8350->irq_mutex);
+ /* Mask all individual interrupts by default and cache the
+ * masks. We read the masks back since there are unwritable
+ * bits in the mask registers. */
+ for (i = 0; i < ARRAY_SIZE(wm8350->irq_masks); i++) {
+ wm8350_reg_write(wm8350, WM8350_INT_STATUS_1_MASK + i,
+ 0xFFFF);
+ wm8350->irq_masks[i] =
+ wm8350_reg_read(wm8350,
+ WM8350_INT_STATUS_1_MASK + i);
+ }
+
+ mutex_init(&wm8350->irq_lock);
wm8350->chip_irq = irq;
+ wm8350->irq_base = pdata->irq_base;
- if (pdata && pdata->irq_high) {
+ if (pdata->irq_high) {
flags |= IRQF_TRIGGER_HIGH;
wm8350_set_bits(wm8350, WM8350_SYSTEM_CONTROL_1,
@@ -514,11 +512,32 @@ int wm8350_irq_init(struct wm8350 *wm8350, int irq,
WM8350_IRQ_POL);
}
+ /* Register with genirq */
+ for (cur_irq = wm8350->irq_base;
+ cur_irq < ARRAY_SIZE(wm8350_irqs) + wm8350->irq_base;
+ cur_irq++) {
+ set_irq_chip_data(cur_irq, wm8350);
+ set_irq_chip_and_handler(cur_irq, &wm8350_irq_chip,
+ handle_edge_irq);
+ set_irq_nested_thread(cur_irq, 1);
+
+ /* ARM needs us to explicitly flag the IRQ as valid
+ * and will set them noprobe when we do so. */
+#ifdef CONFIG_ARM
+ set_irq_flags(cur_irq, IRQF_VALID);
+#else
+ set_irq_noprobe(cur_irq);
+#endif
+ }
+
ret = request_threaded_irq(irq, NULL, wm8350_irq, flags,
"wm8350", wm8350);
if (ret != 0)
dev_err(wm8350->dev, "Failed to request IRQ: %d\n", ret);
+ /* Allow interrupts to fire */
+ wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0);
+
return ret;
}
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
new file mode 100644
index 00000000000..844e1c1b7d9
--- /dev/null
+++ b/drivers/mfd/wm8994-core.c
@@ -0,0 +1,537 @@
+/*
+ * wm8994-core.c -- Device access for Wolfson WM8994
+ *
+ * Copyright 2009 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/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/mfd/core.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+
+#include <linux/mfd/wm8994/core.h>
+#include <linux/mfd/wm8994/pdata.h>
+#include <linux/mfd/wm8994/registers.h>
+
+static int wm8994_read(struct wm8994 *wm8994, unsigned short reg,
+ int bytes, void *dest)
+{
+ int ret, i;
+ u16 *buf = dest;
+
+ BUG_ON(bytes % 2);
+ BUG_ON(bytes <= 0);
+
+ ret = wm8994->read_dev(wm8994, reg, bytes, dest);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < bytes / 2; i++) {
+ buf[i] = be16_to_cpu(buf[i]);
+
+ dev_vdbg(wm8994->dev, "Read %04x from R%d(0x%x)\n",
+ buf[i], reg + i, reg + i);
+ }
+
+ return 0;
+}
+
+/**
+ * wm8994_reg_read: Read a single WM8994 register.
+ *
+ * @wm8994: Device to read from.
+ * @reg: Register to read.
+ */
+int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg)
+{
+ unsigned short val;
+ int ret;
+
+ mutex_lock(&wm8994->io_lock);
+
+ ret = wm8994_read(wm8994, reg, 2, &val);
+
+ mutex_unlock(&wm8994->io_lock);
+
+ if (ret < 0)
+ return ret;
+ else
+ return val;
+}
+EXPORT_SYMBOL_GPL(wm8994_reg_read);
+
+/**
+ * wm8994_bulk_read: Read multiple WM8994 registers
+ *
+ * @wm8994: Device to read from
+ * @reg: First register
+ * @count: Number of registers
+ * @buf: Buffer to fill.
+ */
+int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
+ int count, u16 *buf)
+{
+ int ret;
+
+ mutex_lock(&wm8994->io_lock);
+
+ ret = wm8994_read(wm8994, reg, count * 2, buf);
+
+ mutex_unlock(&wm8994->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm8994_bulk_read);
+
+static int wm8994_write(struct wm8994 *wm8994, unsigned short reg,
+ int bytes, void *src)
+{
+ u16 *buf = src;
+ int i;
+
+ BUG_ON(bytes % 2);
+ BUG_ON(bytes <= 0);
+
+ for (i = 0; i < bytes / 2; i++) {
+ dev_vdbg(wm8994->dev, "Write %04x to R%d(0x%x)\n",
+ buf[i], reg + i, reg + i);
+
+ buf[i] = cpu_to_be16(buf[i]);
+ }
+
+ return wm8994->write_dev(wm8994, reg, bytes, src);
+}
+
+/**
+ * wm8994_reg_write: Write a single WM8994 register.
+ *
+ * @wm8994: Device to write to.
+ * @reg: Register to write to.
+ * @val: Value to write.
+ */
+int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg,
+ unsigned short val)
+{
+ int ret;
+
+ mutex_lock(&wm8994->io_lock);
+
+ ret = wm8994_write(wm8994, reg, 2, &val);
+
+ mutex_unlock(&wm8994->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm8994_reg_write);
+
+/**
+ * wm8994_set_bits: Set the value of a bitfield in a WM8994 register
+ *
+ * @wm8994: Device to write to.
+ * @reg: Register to write to.
+ * @mask: Mask of bits to set.
+ * @val: Value to set (unshifted)
+ */
+int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg,
+ unsigned short mask, unsigned short val)
+{
+ int ret;
+ u16 r;
+
+ mutex_lock(&wm8994->io_lock);
+
+ ret = wm8994_read(wm8994, reg, 2, &r);
+ if (ret < 0)
+ goto out;
+
+ r &= ~mask;
+ r |= val;
+
+ ret = wm8994_write(wm8994, reg, 2, &r);
+
+out:
+ mutex_unlock(&wm8994->io_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wm8994_set_bits);
+
+static struct mfd_cell wm8994_regulator_devs[] = {
+ { .name = "wm8994-ldo", .id = 1 },
+ { .name = "wm8994-ldo", .id = 2 },
+};
+
+static struct mfd_cell wm8994_devs[] = {
+ { .name = "wm8994-codec" },
+ { .name = "wm8994-gpio" },
+};
+
+/*
+ * Supplies for the main bulk of CODEC; the LDO supplies are ignored
+ * and should be handled via the standard regulator API supply
+ * management.
+ */
+static const char *wm8994_main_supplies[] = {
+ "DBVDD",
+ "DCVDD",
+ "AVDD1",
+ "AVDD2",
+ "CPVDD",
+ "SPKVDD1",
+ "SPKVDD2",
+};
+
+#ifdef CONFIG_PM
+static int wm8994_device_suspend(struct device *dev)
+{
+ struct wm8994 *wm8994 = dev_get_drvdata(dev);
+ int ret;
+
+ /* GPIO configuration state is saved here since we may be configuring
+ * the GPIO alternate functions even if we're not using the gpiolib
+ * driver for them.
+ */
+ ret = wm8994_read(wm8994, WM8994_GPIO_1, WM8994_NUM_GPIO_REGS * 2,
+ &wm8994->gpio_regs);
+ if (ret < 0)
+ dev_err(dev, "Failed to save GPIO registers: %d\n", ret);
+
+ /* For similar reasons we also stash the regulator states */
+ ret = wm8994_read(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
+ &wm8994->ldo_regs);
+ if (ret < 0)
+ dev_err(dev, "Failed to save LDO registers: %d\n", ret);
+
+ ret = regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
+ wm8994->supplies);
+ if (ret != 0) {
+ dev_err(dev, "Failed to disable supplies: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int wm8994_device_resume(struct device *dev)
+{
+ struct wm8994 *wm8994 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm8994_main_supplies),
+ wm8994->supplies);
+ if (ret != 0) {
+ dev_err(dev, "Failed to enable supplies: %d\n", ret);
+ return ret;
+ }
+
+ ret = wm8994_write(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
+ &wm8994->ldo_regs);
+ if (ret < 0)
+ dev_err(dev, "Failed to restore LDO registers: %d\n", ret);
+
+ ret = wm8994_write(wm8994, WM8994_GPIO_1, WM8994_NUM_GPIO_REGS * 2,
+ &wm8994->gpio_regs);
+ if (ret < 0)
+ dev_err(dev, "Failed to restore GPIO registers: %d\n", ret);
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_REGULATOR
+static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
+{
+ struct wm8994_ldo_pdata *ldo_pdata;
+
+ if (!pdata)
+ return 0;
+
+ ldo_pdata = &pdata->ldo[ldo];
+
+ if (!ldo_pdata->init_data)
+ return 0;
+
+ return ldo_pdata->init_data->num_consumer_supplies != 0;
+}
+#else
+static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
+{
+ return 0;
+}
+#endif
+
+/*
+ * Instantiate the generic non-control parts of the device.
+ */
+static int wm8994_device_init(struct wm8994 *wm8994, unsigned long id, int irq)
+{
+ struct wm8994_pdata *pdata = wm8994->dev->platform_data;
+ int ret, i;
+
+ mutex_init(&wm8994->io_lock);
+ dev_set_drvdata(wm8994->dev, wm8994);
+
+ /* Add the on-chip regulators first for bootstrapping */
+ ret = mfd_add_devices(wm8994->dev, -1,
+ wm8994_regulator_devs,
+ ARRAY_SIZE(wm8994_regulator_devs),
+ NULL, 0);
+ if (ret != 0) {
+ dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
+ goto err;
+ }
+
+ wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
+ ARRAY_SIZE(wm8994_main_supplies),
+ GFP_KERNEL);
+ if (!wm8994->supplies)
+ goto err;
+
+ for (i = 0; i < ARRAY_SIZE(wm8994_main_supplies); i++)
+ wm8994->supplies[i].supply = wm8994_main_supplies[i];
+
+ ret = regulator_bulk_get(wm8994->dev, ARRAY_SIZE(wm8994_main_supplies),
+ wm8994->supplies);
+ if (ret != 0) {
+ dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret);
+ goto err_supplies;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm8994_main_supplies),
+ wm8994->supplies);
+ if (ret != 0) {
+ dev_err(wm8994->dev, "Failed to enable supplies: %d\n", ret);
+ goto err_get;
+ }
+
+ ret = wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET);
+ if (ret < 0) {
+ dev_err(wm8994->dev, "Failed to read ID register\n");
+ goto err_enable;
+ }
+ if (ret != 0x8994) {
+ dev_err(wm8994->dev, "Device is not a WM8994, ID is %x\n",
+ ret);
+ ret = -EINVAL;
+ goto err_enable;
+ }
+
+ ret = wm8994_reg_read(wm8994, WM8994_CHIP_REVISION);
+ if (ret < 0) {
+ dev_err(wm8994->dev, "Failed to read revision register: %d\n",
+ ret);
+ goto err_enable;
+ }
+
+ switch (ret) {
+ case 0:
+ case 1:
+ dev_warn(wm8994->dev, "revision %c not fully supported\n",
+ 'A' + ret);
+ break;
+ default:
+ dev_info(wm8994->dev, "revision %c\n", 'A' + ret);
+ break;
+ }
+
+
+ if (pdata) {
+ wm8994->gpio_base = pdata->gpio_base;
+
+ /* GPIO configuration is only applied if it's non-zero */
+ for (i = 0; i < ARRAY_SIZE(pdata->gpio_defaults); i++) {
+ if (pdata->gpio_defaults[i]) {
+ wm8994_set_bits(wm8994, WM8994_GPIO_1 + i,
+ 0xffff,
+ pdata->gpio_defaults[i]);
+ }
+ }
+ }
+
+ /* In some system designs where the regulators are not in use,
+ * we can achieve a small reduction in leakage currents by
+ * floating LDO outputs. This bit makes no difference if the
+ * LDOs are enabled, it only affects cases where the LDOs were
+ * in operation and are then disabled.
+ */
+ for (i = 0; i < WM8994_NUM_LDO_REGS; i++) {
+ if (wm8994_ldo_in_use(pdata, i))
+ wm8994_set_bits(wm8994, WM8994_LDO_1 + i,
+ WM8994_LDO1_DISCH, WM8994_LDO1_DISCH);
+ else
+ wm8994_set_bits(wm8994, WM8994_LDO_1 + i,
+ WM8994_LDO1_DISCH, 0);
+ }
+
+ ret = mfd_add_devices(wm8994->dev, -1,
+ wm8994_devs, ARRAY_SIZE(wm8994_devs),
+ NULL, 0);
+ if (ret != 0) {
+ dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
+ goto err_enable;
+ }
+
+ return 0;
+
+err_enable:
+ regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
+ wm8994->supplies);
+err_get:
+ regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies);
+err_supplies:
+ kfree(wm8994->supplies);
+err:
+ mfd_remove_devices(wm8994->dev);
+ kfree(wm8994);
+ return ret;
+}
+
+static void wm8994_device_exit(struct wm8994 *wm8994)
+{
+ mfd_remove_devices(wm8994->dev);
+ regulator_bulk_disable(ARRAY_SIZE(wm8994_main_supplies),
+ wm8994->supplies);
+ regulator_bulk_free(ARRAY_SIZE(wm8994_main_supplies), wm8994->supplies);
+ kfree(wm8994->supplies);
+ kfree(wm8994);
+}
+
+static int wm8994_i2c_read_device(struct wm8994 *wm8994, unsigned short reg,
+ int bytes, void *dest)
+{
+ struct i2c_client *i2c = wm8994->control_data;
+ int ret;
+ u16 r = cpu_to_be16(reg);
+
+ ret = i2c_master_send(i2c, (unsigned char *)&r, 2);
+ if (ret < 0)
+ return ret;
+ if (ret != 2)
+ return -EIO;
+
+ ret = i2c_master_recv(i2c, dest, bytes);
+ if (ret < 0)
+ return ret;
+ if (ret != bytes)
+ return -EIO;
+ return 0;
+}
+
+/* Currently we allocate the write buffer on the stack; this is OK for
+ * small writes - if we need to do large writes this will need to be
+ * revised.
+ */
+static int wm8994_i2c_write_device(struct wm8994 *wm8994, unsigned short reg,
+ int bytes, void *src)
+{
+ struct i2c_client *i2c = wm8994->control_data;
+ unsigned char msg[bytes + 2];
+ int ret;
+
+ reg = cpu_to_be16(reg);
+ memcpy(&msg[0], &reg, 2);
+ memcpy(&msg[2], src, bytes);
+
+ ret = i2c_master_send(i2c, msg, bytes + 2);
+ if (ret < 0)
+ return ret;
+ if (ret < bytes + 2)
+ return -EIO;
+
+ return 0;
+}
+
+static int wm8994_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct wm8994 *wm8994;
+
+ wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL);
+ if (wm8994 == NULL) {
+ kfree(i2c);
+ return -ENOMEM;
+ }
+
+ i2c_set_clientdata(i2c, wm8994);
+ wm8994->dev = &i2c->dev;
+ wm8994->control_data = i2c;
+ wm8994->read_dev = wm8994_i2c_read_device;
+ wm8994->write_dev = wm8994_i2c_write_device;
+
+ return wm8994_device_init(wm8994, id->driver_data, i2c->irq);
+}
+
+static int wm8994_i2c_remove(struct i2c_client *i2c)
+{
+ struct wm8994 *wm8994 = i2c_get_clientdata(i2c);
+
+ wm8994_device_exit(wm8994);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int wm8994_i2c_suspend(struct i2c_client *i2c, pm_message_t state)
+{
+ return wm8994_device_suspend(&i2c->dev);
+}
+
+static int wm8994_i2c_resume(struct i2c_client *i2c)
+{
+ return wm8994_device_resume(&i2c->dev);
+}
+#else
+#define wm8994_i2c_suspend NULL
+#define wm8994_i2c_resume NULL
+#endif
+
+static const struct i2c_device_id wm8994_i2c_id[] = {
+ { "wm8994", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id);
+
+static struct i2c_driver wm8994_i2c_driver = {
+ .driver = {
+ .name = "wm8994",
+ .owner = THIS_MODULE,
+ },
+ .probe = wm8994_i2c_probe,
+ .remove = wm8994_i2c_remove,
+ .suspend = wm8994_i2c_suspend,
+ .resume = wm8994_i2c_resume,
+ .id_table = wm8994_i2c_id,
+};
+
+static int __init wm8994_i2c_init(void)
+{
+ int ret;
+
+ ret = i2c_add_driver(&wm8994_i2c_driver);
+ if (ret != 0)
+ pr_err("Failed to register wm8994 I2C driver: %d\n", ret);
+
+ return ret;
+}
+module_init(wm8994_i2c_init);
+
+static void __exit wm8994_i2c_exit(void)
+{
+ i2c_del_driver(&wm8994_i2c_driver);
+}
+module_exit(wm8994_i2c_exit);
+
+MODULE_DESCRIPTION("Core support for the WM8994 audio CODEC");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index e3551d20464..d16af6a423f 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -212,6 +212,15 @@ config CS5535_MFGPT_DEFAULT_IRQ
want to use a different IRQ by default. This is here for
architectures to set as necessary.
+config CS5535_CLOCK_EVENT_SRC
+ tristate "CS5535/CS5536 high-res timer (MFGPT) events"
+ depends on GENERIC_TIME && GENERIC_CLOCKEVENTS && CS5535_MFGPT
+ help
+ This driver provides a clock event source based on the MFGPT
+ timer(s) in the CS5535 and CS5536 companion chips.
+ MFGPTs have a better resolution and max interval than the
+ generic PIT, and are suitable for use as high-res timers.
+
config HP_ILO
tristate "Channel interface driver for HP iLO/iLO2 processor"
depends on PCI
diff --git a/drivers/misc/iwmc3200top/main.c b/drivers/misc/iwmc3200top/main.c
index dd0a3913bf6..3b7292a5cea 100644
--- a/drivers/misc/iwmc3200top/main.c
+++ b/drivers/misc/iwmc3200top/main.c
@@ -597,8 +597,6 @@ static void iwmct_remove(struct sdio_func *func)
struct iwmct_work_struct *read_req;
struct iwmct_priv *priv = sdio_get_drvdata(func);
- priv = sdio_get_drvdata(func);
-
LOG_INFO(priv, INIT, "enter\n");
sdio_claim_host(func);
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index 3648b23d5c9..4a0648301fd 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -26,21 +26,9 @@
* It is adapted from the Linux Kernel Dump Test Tool by
* Fernando Luis Vazquez Cao <http://lkdtt.sourceforge.net>
*
- * Usage : insmod lkdtm.ko [recur_count={>0}] cpoint_name=<> cpoint_type=<>
- * [cpoint_count={>0}]
+ * Debugfs support added by Simon Kagstrom <simon.kagstrom@netinsight.net>
*
- * recur_count : Recursion level for the stack overflow test. Default is 10.
- *
- * cpoint_name : Crash point where the kernel is to be crashed. It can be
- * one of INT_HARDWARE_ENTRY, INT_HW_IRQ_EN, INT_TASKLET_ENTRY,
- * FS_DEVRW, MEM_SWAPOUT, TIMERADD, SCSI_DISPATCH_CMD,
- * IDE_CORE_CP
- *
- * cpoint_type : Indicates the action to be taken on hitting the crash point.
- * It can be one of PANIC, BUG, EXCEPTION, LOOP, OVERFLOW
- *
- * cpoint_count : Indicates the number of times the crash point is to be hit
- * to trigger an action. The default is 10.
+ * See Documentation/fault-injection/provoke-crashes.txt for instructions
*/
#include <linux/kernel.h>
@@ -53,13 +41,12 @@
#include <linux/interrupt.h>
#include <linux/hrtimer.h>
#include <scsi/scsi_cmnd.h>
+#include <linux/debugfs.h>
#ifdef CONFIG_IDE
#include <linux/ide.h>
#endif
-#define NUM_CPOINTS 8
-#define NUM_CPOINT_TYPES 5
#define DEFAULT_COUNT 10
#define REC_NUM_DEFAULT 10
@@ -72,7 +59,8 @@ enum cname {
MEM_SWAPOUT,
TIMERADD,
SCSI_DISPATCH_CMD,
- IDE_CORE_CP
+ IDE_CORE_CP,
+ DIRECT,
};
enum ctype {
@@ -81,7 +69,11 @@ enum ctype {
BUG,
EXCEPTION,
LOOP,
- OVERFLOW
+ OVERFLOW,
+ CORRUPT_STACK,
+ UNALIGNED_LOAD_STORE_WRITE,
+ OVERWRITE_ALLOCATION,
+ WRITE_AFTER_FREE,
};
static char* cp_name[] = {
@@ -92,7 +84,8 @@ static char* cp_name[] = {
"MEM_SWAPOUT",
"TIMERADD",
"SCSI_DISPATCH_CMD",
- "IDE_CORE_CP"
+ "IDE_CORE_CP",
+ "DIRECT",
};
static char* cp_type[] = {
@@ -100,7 +93,11 @@ static char* cp_type[] = {
"BUG",
"EXCEPTION",
"LOOP",
- "OVERFLOW"
+ "OVERFLOW",
+ "CORRUPT_STACK",
+ "UNALIGNED_LOAD_STORE_WRITE",
+ "OVERWRITE_ALLOCATION",
+ "WRITE_AFTER_FREE",
};
static struct jprobe lkdtm;
@@ -193,34 +190,66 @@ int jp_generic_ide_ioctl(ide_drive_t *drive, struct file *file,
}
#endif
+/* Return the crashpoint number or NONE if the name is invalid */
+static enum ctype parse_cp_type(const char *what, size_t count)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cp_type); i++) {
+ if (!strcmp(what, cp_type[i]))
+ return i + 1;
+ }
+
+ return NONE;
+}
+
+static const char *cp_type_to_str(enum ctype type)
+{
+ if (type == NONE || type < 0 || type > ARRAY_SIZE(cp_type))
+ return "None";
+
+ return cp_type[type - 1];
+}
+
+static const char *cp_name_to_str(enum cname name)
+{
+ if (name == INVALID || name < 0 || name > ARRAY_SIZE(cp_name))
+ return "INVALID";
+
+ return cp_name[name - 1];
+}
+
+
static int lkdtm_parse_commandline(void)
{
int i;
- if (cpoint_name == NULL || cpoint_type == NULL ||
- cpoint_count < 1 || recur_count < 1)
+ if (cpoint_count < 1 || recur_count < 1)
return -EINVAL;
- for (i = 0; i < NUM_CPOINTS; ++i) {
+ count = cpoint_count;
+
+ /* No special parameters */
+ if (!cpoint_type && !cpoint_name)
+ return 0;
+
+ /* Neither or both of these need to be set */
+ if (!cpoint_type || !cpoint_name)
+ return -EINVAL;
+
+ cptype = parse_cp_type(cpoint_type, strlen(cpoint_type));
+ if (cptype == NONE)
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(cp_name); i++) {
if (!strcmp(cpoint_name, cp_name[i])) {
cpoint = i + 1;
- break;
- }
- }
-
- for (i = 0; i < NUM_CPOINT_TYPES; ++i) {
- if (!strcmp(cpoint_type, cp_type[i])) {
- cptype = i + 1;
- break;
+ return 0;
}
}
- if (cpoint == INVALID || cptype == NONE)
- return -EINVAL;
-
- count = cpoint_count;
-
- return 0;
+ /* Could not find a valid crash point */
+ return -EINVAL;
}
static int recursive_loop(int a)
@@ -235,53 +264,92 @@ static int recursive_loop(int a)
return recursive_loop(a);
}
-void lkdtm_handler(void)
+static void lkdtm_do_action(enum ctype which)
{
- printk(KERN_INFO "lkdtm : Crash point %s of type %s hit\n",
- cpoint_name, cpoint_type);
- --count;
+ switch (which) {
+ case PANIC:
+ panic("dumptest");
+ break;
+ case BUG:
+ BUG();
+ break;
+ case EXCEPTION:
+ *((int *) 0) = 0;
+ break;
+ case LOOP:
+ for (;;)
+ ;
+ break;
+ case OVERFLOW:
+ (void) recursive_loop(0);
+ break;
+ case CORRUPT_STACK: {
+ volatile u32 data[8];
+ volatile u32 *p = data;
+
+ p[12] = 0x12345678;
+ break;
+ }
+ case UNALIGNED_LOAD_STORE_WRITE: {
+ static u8 data[5] __attribute__((aligned(4))) = {1, 2,
+ 3, 4, 5};
+ u32 *p;
+ u32 val = 0x12345678;
+
+ p = (u32 *)(data + 1);
+ if (*p == 0)
+ val = 0x87654321;
+ *p = val;
+ break;
+ }
+ case OVERWRITE_ALLOCATION: {
+ size_t len = 1020;
+ u32 *data = kmalloc(len, GFP_KERNEL);
+
+ data[1024 / sizeof(u32)] = 0x12345678;
+ kfree(data);
+ break;
+ }
+ case WRITE_AFTER_FREE: {
+ size_t len = 1024;
+ u32 *data = kmalloc(len, GFP_KERNEL);
+
+ kfree(data);
+ schedule();
+ memset(data, 0x78, len);
+ break;
+ }
+ case NONE:
+ default:
+ break;
+ }
+
+}
+
+static void lkdtm_handler(void)
+{
+ count--;
+ printk(KERN_INFO "lkdtm: Crash point %s of type %s hit, trigger in %d rounds\n",
+ cp_name_to_str(cpoint), cp_type_to_str(cptype), count);
if (count == 0) {
- switch (cptype) {
- case NONE:
- break;
- case PANIC:
- printk(KERN_INFO "lkdtm : PANIC\n");
- panic("dumptest");
- break;
- case BUG:
- printk(KERN_INFO "lkdtm : BUG\n");
- BUG();
- break;
- case EXCEPTION:
- printk(KERN_INFO "lkdtm : EXCEPTION\n");
- *((int *) 0) = 0;
- break;
- case LOOP:
- printk(KERN_INFO "lkdtm : LOOP\n");
- for (;;);
- break;
- case OVERFLOW:
- printk(KERN_INFO "lkdtm : OVERFLOW\n");
- (void) recursive_loop(0);
- break;
- default:
- break;
- }
+ lkdtm_do_action(cptype);
count = cpoint_count;
}
}
-static int __init lkdtm_module_init(void)
+static int lkdtm_register_cpoint(enum cname which)
{
int ret;
- if (lkdtm_parse_commandline() == -EINVAL) {
- printk(KERN_INFO "lkdtm : Invalid command\n");
- return -EINVAL;
- }
+ cpoint = INVALID;
+ if (lkdtm.entry != NULL)
+ unregister_jprobe(&lkdtm);
- switch (cpoint) {
+ switch (which) {
+ case DIRECT:
+ lkdtm_do_action(cptype);
+ return 0;
case INT_HARDWARE_ENTRY:
lkdtm.kp.symbol_name = "do_IRQ";
lkdtm.entry = (kprobe_opcode_t*) jp_do_irq;
@@ -315,28 +383,268 @@ static int __init lkdtm_module_init(void)
lkdtm.kp.symbol_name = "generic_ide_ioctl";
lkdtm.entry = (kprobe_opcode_t*) jp_generic_ide_ioctl;
#else
- printk(KERN_INFO "lkdtm : Crash point not available\n");
+ printk(KERN_INFO "lkdtm: Crash point not available\n");
+ return -EINVAL;
#endif
break;
default:
- printk(KERN_INFO "lkdtm : Invalid Crash Point\n");
- break;
+ printk(KERN_INFO "lkdtm: Invalid Crash Point\n");
+ return -EINVAL;
}
+ cpoint = which;
if ((ret = register_jprobe(&lkdtm)) < 0) {
- printk(KERN_INFO "lkdtm : Couldn't register jprobe\n");
- return ret;
+ printk(KERN_INFO "lkdtm: Couldn't register jprobe\n");
+ cpoint = INVALID;
+ }
+
+ return ret;
+}
+
+static ssize_t do_register_entry(enum cname which, struct file *f,
+ const char __user *user_buf, size_t count, loff_t *off)
+{
+ char *buf;
+ int err;
+
+ if (count >= PAGE_SIZE)
+ return -EINVAL;
+
+ buf = (char *)__get_free_page(GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ if (copy_from_user(buf, user_buf, count)) {
+ free_page((unsigned long) buf);
+ return -EFAULT;
+ }
+ /* NULL-terminate and remove enter */
+ buf[count] = '\0';
+ strim(buf);
+
+ cptype = parse_cp_type(buf, count);
+ free_page((unsigned long) buf);
+
+ if (cptype == NONE)
+ return -EINVAL;
+
+ err = lkdtm_register_cpoint(which);
+ if (err < 0)
+ return err;
+
+ *off += count;
+
+ return count;
+}
+
+/* Generic read callback that just prints out the available crash types */
+static ssize_t lkdtm_debugfs_read(struct file *f, char __user *user_buf,
+ size_t count, loff_t *off)
+{
+ char *buf;
+ int i, n, out;
+
+ buf = (char *)__get_free_page(GFP_KERNEL);
+
+ n = snprintf(buf, PAGE_SIZE, "Available crash types:\n");
+ for (i = 0; i < ARRAY_SIZE(cp_type); i++)
+ n += snprintf(buf + n, PAGE_SIZE - n, "%s\n", cp_type[i]);
+ buf[n] = '\0';
+
+ out = simple_read_from_buffer(user_buf, count, off,
+ buf, n);
+ free_page((unsigned long) buf);
+
+ return out;
+}
+
+static int lkdtm_debugfs_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+
+static ssize_t int_hardware_entry(struct file *f, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ return do_register_entry(INT_HARDWARE_ENTRY, f, buf, count, off);
+}
+
+static ssize_t int_hw_irq_en(struct file *f, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ return do_register_entry(INT_HW_IRQ_EN, f, buf, count, off);
+}
+
+static ssize_t int_tasklet_entry(struct file *f, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ return do_register_entry(INT_TASKLET_ENTRY, f, buf, count, off);
+}
+
+static ssize_t fs_devrw_entry(struct file *f, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ return do_register_entry(FS_DEVRW, f, buf, count, off);
+}
+
+static ssize_t mem_swapout_entry(struct file *f, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ return do_register_entry(MEM_SWAPOUT, f, buf, count, off);
+}
+
+static ssize_t timeradd_entry(struct file *f, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ return do_register_entry(TIMERADD, f, buf, count, off);
+}
+
+static ssize_t scsi_dispatch_cmd_entry(struct file *f,
+ const char __user *buf, size_t count, loff_t *off)
+{
+ return do_register_entry(SCSI_DISPATCH_CMD, f, buf, count, off);
+}
+
+static ssize_t ide_core_cp_entry(struct file *f, const char __user *buf,
+ size_t count, loff_t *off)
+{
+ return do_register_entry(IDE_CORE_CP, f, buf, count, off);
+}
+
+/* Special entry to just crash directly. Available without KPROBEs */
+static ssize_t direct_entry(struct file *f, const char __user *user_buf,
+ size_t count, loff_t *off)
+{
+ enum ctype type;
+ char *buf;
+
+ if (count >= PAGE_SIZE)
+ return -EINVAL;
+ if (count < 1)
+ return -EINVAL;
+
+ buf = (char *)__get_free_page(GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ if (copy_from_user(buf, user_buf, count)) {
+ free_page((unsigned long) buf);
+ return -EFAULT;
+ }
+ /* NULL-terminate and remove enter */
+ buf[count] = '\0';
+ strim(buf);
+
+ type = parse_cp_type(buf, count);
+ free_page((unsigned long) buf);
+ if (type == NONE)
+ return -EINVAL;
+
+ printk(KERN_INFO "lkdtm: Performing direct entry %s\n",
+ cp_type_to_str(type));
+ lkdtm_do_action(type);
+ *off += count;
+
+ return count;
+}
+
+struct crash_entry {
+ const char *name;
+ const struct file_operations fops;
+};
+
+static const struct crash_entry crash_entries[] = {
+ {"DIRECT", {.read = lkdtm_debugfs_read,
+ .open = lkdtm_debugfs_open,
+ .write = direct_entry} },
+ {"INT_HARDWARE_ENTRY", {.read = lkdtm_debugfs_read,
+ .open = lkdtm_debugfs_open,
+ .write = int_hardware_entry} },
+ {"INT_HW_IRQ_EN", {.read = lkdtm_debugfs_read,
+ .open = lkdtm_debugfs_open,
+ .write = int_hw_irq_en} },
+ {"INT_TASKLET_ENTRY", {.read = lkdtm_debugfs_read,
+ .open = lkdtm_debugfs_open,
+ .write = int_tasklet_entry} },
+ {"FS_DEVRW", {.read = lkdtm_debugfs_read,
+ .open = lkdtm_debugfs_open,
+ .write = fs_devrw_entry} },
+ {"MEM_SWAPOUT", {.read = lkdtm_debugfs_read,
+ .open = lkdtm_debugfs_open,
+ .write = mem_swapout_entry} },
+ {"TIMERADD", {.read = lkdtm_debugfs_read,
+ .open = lkdtm_debugfs_open,
+ .write = timeradd_entry} },
+ {"SCSI_DISPATCH_CMD", {.read = lkdtm_debugfs_read,
+ .open = lkdtm_debugfs_open,
+ .write = scsi_dispatch_cmd_entry} },
+ {"IDE_CORE_CP", {.read = lkdtm_debugfs_read,
+ .open = lkdtm_debugfs_open,
+ .write = ide_core_cp_entry} },
+};
+
+static struct dentry *lkdtm_debugfs_root;
+
+static int __init lkdtm_module_init(void)
+{
+ int ret = -EINVAL;
+ int n_debugfs_entries = 1; /* Assume only the direct entry */
+ int i;
+
+ /* Register debugfs interface */
+ lkdtm_debugfs_root = debugfs_create_dir("provoke-crash", NULL);
+ if (!lkdtm_debugfs_root) {
+ printk(KERN_ERR "lkdtm: creating root dir failed\n");
+ return -ENODEV;
+ }
+
+#ifdef CONFIG_KPROBES
+ n_debugfs_entries = ARRAY_SIZE(crash_entries);
+#endif
+
+ for (i = 0; i < n_debugfs_entries; i++) {
+ const struct crash_entry *cur = &crash_entries[i];
+ struct dentry *de;
+
+ de = debugfs_create_file(cur->name, 0644, lkdtm_debugfs_root,
+ NULL, &cur->fops);
+ if (de == NULL) {
+ printk(KERN_ERR "lkdtm: could not create %s\n",
+ cur->name);
+ goto out_err;
+ }
+ }
+
+ if (lkdtm_parse_commandline() == -EINVAL) {
+ printk(KERN_INFO "lkdtm: Invalid command\n");
+ goto out_err;
+ }
+
+ if (cpoint != INVALID && cptype != NONE) {
+ ret = lkdtm_register_cpoint(cpoint);
+ if (ret < 0) {
+ printk(KERN_INFO "lkdtm: Invalid crash point %d\n",
+ cpoint);
+ goto out_err;
+ }
+ printk(KERN_INFO "lkdtm: Crash point %s of type %s registered\n",
+ cpoint_name, cpoint_type);
+ } else {
+ printk(KERN_INFO "lkdtm: No crash points registered, enable through debugfs\n");
}
- printk(KERN_INFO "lkdtm : Crash point %s of type %s registered\n",
- cpoint_name, cpoint_type);
return 0;
+
+out_err:
+ debugfs_remove_recursive(lkdtm_debugfs_root);
+ return ret;
}
static void __exit lkdtm_module_exit(void)
{
- unregister_jprobe(&lkdtm);
- printk(KERN_INFO "lkdtm : Crash point unregistered\n");
+ debugfs_remove_recursive(lkdtm_debugfs_root);
+
+ unregister_jprobe(&lkdtm);
+ printk(KERN_INFO "lkdtm: Crash point unregistered\n");
}
module_init(lkdtm_module_init);
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c
index 04c27266f56..779aa8ebe4c 100644
--- a/drivers/misc/phantom.c
+++ b/drivers/misc/phantom.c
@@ -497,12 +497,7 @@ static struct pci_driver phantom_pci_driver = {
.resume = phantom_resume
};
-static ssize_t phantom_show_version(struct class *cls, char *buf)
-{
- return sprintf(buf, PHANTOM_VERSION "\n");
-}
-
-static CLASS_ATTR(version, 0444, phantom_show_version, NULL);
+static CLASS_ATTR_STRING(version, 0444, PHANTOM_VERSION);
static int __init phantom_init(void)
{
@@ -515,7 +510,7 @@ static int __init phantom_init(void)
printk(KERN_ERR "phantom: can't register phantom class\n");
goto err;
}
- retval = class_create_file(phantom_class, &class_attr_version);
+ retval = class_create_file(phantom_class, &class_attr_version.attr);
if (retval) {
printk(KERN_ERR "phantom: can't create sysfs version file\n");
goto err_class;
@@ -541,7 +536,7 @@ static int __init phantom_init(void)
err_unchr:
unregister_chrdev_region(dev, PHANTOM_MAX_MINORS);
err_attr:
- class_remove_file(phantom_class, &class_attr_version);
+ class_remove_file(phantom_class, &class_attr_version.attr);
err_class:
class_destroy(phantom_class);
err:
@@ -554,7 +549,7 @@ static void __exit phantom_exit(void)
unregister_chrdev_region(MKDEV(phantom_major, 0), PHANTOM_MAX_MINORS);
- class_remove_file(phantom_class, &class_attr_version);
+ class_remove_file(phantom_class, &class_attr_version.attr);
class_destroy(phantom_class);
pr_debug("phantom: module successfully removed\n");
diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c
index 16f0abda142..57b152f8d1b 100644
--- a/drivers/misc/sgi-xp/xpnet.c
+++ b/drivers/misc/sgi-xp/xpnet.c
@@ -475,7 +475,7 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (skb->data[0] == 0xff) {
/* we are being asked to broadcast to all partitions */
- for_each_bit(dest_partid, xpnet_broadcast_partitions,
+ for_each_set_bit(dest_partid, xpnet_broadcast_partitions,
xp_max_npartitions) {
xpnet_send(skb, queued_msg, start_addr, end_addr,
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 30acd526582..f4b97d3c3d0 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1151,6 +1151,9 @@ void mmc_stop_host(struct mmc_host *host)
cancel_delayed_work(&host->detect);
mmc_flush_scheduled_work();
+ /* clear pm flags now and let card drivers set them as needed */
+ host->pm_flags = 0;
+
mmc_bus_get(host);
if (host->bus_ops && !host->bus_dead) {
if (host->bus_ops->remove)
@@ -1273,12 +1276,13 @@ int mmc_suspend_host(struct mmc_host *host, pm_message_t state)
mmc_claim_host(host);
mmc_detach_bus(host);
mmc_release_host(host);
+ host->pm_flags = 0;
err = 0;
}
}
mmc_bus_put(host);
- if (!err)
+ if (!err && !(host->pm_flags & MMC_PM_KEEP_POWER))
mmc_power_off(host);
return err;
@@ -1296,8 +1300,10 @@ int mmc_resume_host(struct mmc_host *host)
mmc_bus_get(host);
if (host->bus_ops && !host->bus_dead) {
- mmc_power_up(host);
- mmc_select_voltage(host, host->ocr);
+ if (!(host->pm_flags & MMC_PM_KEEP_POWER)) {
+ mmc_power_up(host);
+ mmc_select_voltage(host, host->ocr);
+ }
BUG_ON(!host->bus_ops->resume);
err = host->bus_ops->resume(host);
if (err) {
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 06b64085a35..2dd4cfe7ca1 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -188,6 +188,40 @@ static int sdio_disable_cd(struct mmc_card *card)
}
/*
+ * Devices that remain active during a system suspend are
+ * put back into 1-bit mode.
+ */
+static int sdio_disable_wide(struct mmc_card *card)
+{
+ int ret;
+ u8 ctrl;
+
+ if (!(card->host->caps & MMC_CAP_4_BIT_DATA))
+ return 0;
+
+ if (card->cccr.low_speed && !card->cccr.wide_bus)
+ return 0;
+
+ ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_IF, 0, &ctrl);
+ if (ret)
+ return ret;
+
+ if (!(ctrl & SDIO_BUS_WIDTH_4BIT))
+ return 0;
+
+ ctrl &= ~SDIO_BUS_WIDTH_4BIT;
+ ctrl |= SDIO_BUS_ASYNC_INT;
+
+ ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL);
+ if (ret)
+ return ret;
+
+ mmc_set_bus_width(card->host, MMC_BUS_WIDTH_1);
+
+ return 0;
+}
+
+/*
* Test if the card supports high-speed mode and, if so, switch to it.
*/
static int sdio_enable_hs(struct mmc_card *card)
@@ -224,7 +258,7 @@ static int sdio_enable_hs(struct mmc_card *card)
* we're trying to reinitialise.
*/
static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
- struct mmc_card *oldcard)
+ struct mmc_card *oldcard, int powered_resume)
{
struct mmc_card *card;
int err;
@@ -235,9 +269,11 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
/*
* Inform the card of the voltage
*/
- err = mmc_send_io_op_cond(host, host->ocr, &ocr);
- if (err)
- goto err;
+ if (!powered_resume) {
+ err = mmc_send_io_op_cond(host, host->ocr, &ocr);
+ if (err)
+ goto err;
+ }
/*
* For SPI, enable CRC as appropriate.
@@ -262,7 +298,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
/*
* For native busses: set card RCA and quit open drain mode.
*/
- if (!mmc_host_is_spi(host)) {
+ if (!powered_resume && !mmc_host_is_spi(host)) {
err = mmc_send_relative_addr(host, &card->rca);
if (err)
goto remove;
@@ -273,7 +309,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
/*
* Select card, as all following commands rely on that.
*/
- if (!mmc_host_is_spi(host)) {
+ if (!powered_resume && !mmc_host_is_spi(host)) {
err = mmc_select_card(card);
if (err)
goto remove;
@@ -425,6 +461,12 @@ static int mmc_sdio_suspend(struct mmc_host *host)
}
}
+ if (!err && host->pm_flags & MMC_PM_KEEP_POWER) {
+ mmc_claim_host(host);
+ sdio_disable_wide(host->card);
+ mmc_release_host(host);
+ }
+
return err;
}
@@ -437,7 +479,13 @@ static int mmc_sdio_resume(struct mmc_host *host)
/* Basic card reinitialization. */
mmc_claim_host(host);
- err = mmc_sdio_init_card(host, host->ocr, host->card);
+ err = mmc_sdio_init_card(host, host->ocr, host->card,
+ (host->pm_flags & MMC_PM_KEEP_POWER));
+ if (!err)
+ /* We may have switched to 1-bit mode during suspend. */
+ err = sdio_enable_wide(host->card);
+ if (!err && host->sdio_irqs)
+ mmc_signal_sdio_irq(host);
mmc_release_host(host);
/*
@@ -507,7 +555,7 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
/*
* Detect and init the card.
*/
- err = mmc_sdio_init_card(host, host->ocr, NULL);
+ err = mmc_sdio_init_card(host, host->ocr, NULL, 0);
if (err)
goto err;
card = host->card;
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c
index f9aa8a7deff..ff27c8c7135 100644
--- a/drivers/mmc/core/sdio_io.c
+++ b/drivers/mmc/core/sdio_io.c
@@ -189,7 +189,12 @@ static inline unsigned int sdio_max_byte_size(struct sdio_func *func)
{
unsigned mval = min(func->card->host->max_seg_size,
func->card->host->max_blk_size);
- mval = min(mval, func->max_blksize);
+
+ if (mmc_blksz_for_byte_mode(func->card))
+ mval = min(mval, func->cur_blksize);
+ else
+ mval = min(mval, func->max_blksize);
+
return min(mval, 512u); /* maximum size for byte mode */
}
@@ -635,3 +640,52 @@ void sdio_f0_writeb(struct sdio_func *func, unsigned char b, unsigned int addr,
*err_ret = ret;
}
EXPORT_SYMBOL_GPL(sdio_f0_writeb);
+
+/**
+ * sdio_get_host_pm_caps - get host power management capabilities
+ * @func: SDIO function attached to host
+ *
+ * Returns a capability bitmask corresponding to power management
+ * features supported by the host controller that the card function
+ * might rely upon during a system suspend. The host doesn't need
+ * to be claimed, nor the function active, for this information to be
+ * obtained.
+ */
+mmc_pm_flag_t sdio_get_host_pm_caps(struct sdio_func *func)
+{
+ BUG_ON(!func);
+ BUG_ON(!func->card);
+
+ return func->card->host->pm_caps;
+}
+EXPORT_SYMBOL_GPL(sdio_get_host_pm_caps);
+
+/**
+ * sdio_set_host_pm_flags - set wanted host power management capabilities
+ * @func: SDIO function attached to host
+ *
+ * Set a capability bitmask corresponding to wanted host controller
+ * power management features for the upcoming suspend state.
+ * This must be called, if needed, each time the suspend method of
+ * the function driver is called, and must contain only bits that
+ * were returned by sdio_get_host_pm_caps().
+ * The host doesn't need to be claimed, nor the function active,
+ * for this information to be set.
+ */
+int sdio_set_host_pm_flags(struct sdio_func *func, mmc_pm_flag_t flags)
+{
+ struct mmc_host *host;
+
+ BUG_ON(!func);
+ BUG_ON(!func->card);
+
+ host = func->card->host;
+
+ if (flags & ~host->pm_caps)
+ return -EINVAL;
+
+ /* function suspend methods are serialized, hence no lock needed */
+ host->pm_flags |= flags;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(sdio_set_host_pm_flags);
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index ce1d28884e2..2e13b94769f 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -69,20 +69,16 @@ config MMC_SDHCI_PCI
If unsure, say N.
config MMC_RICOH_MMC
- tristate "Ricoh MMC Controller Disabler (EXPERIMENTAL)"
+ bool "Ricoh MMC Controller Disabler (EXPERIMENTAL)"
depends on MMC_SDHCI_PCI
help
- This selects the disabler for the Ricoh MMC Controller. This
+ This adds a pci quirk to disable Ricoh MMC Controller. This
proprietary controller is unnecessary because the SDHCI driver
supports MMC cards on the SD controller, but if it is not
disabled, it will steal the MMC cards away - rendering them
- useless. It is safe to select this driver even if you don't
+ useless. It is safe to select this even if you don't
have a Ricoh based card reader.
-
- To compile this driver as a module, choose M here:
- the module will be called ricoh_mmc.
-
If unsure, say Y.
config MMC_SDHCI_OF
@@ -193,6 +189,7 @@ config MMC_AU1X
choice
prompt "Atmel SD/MMC Driver"
+ depends on AVR32 || ARCH_AT91
default MMC_ATMELMCI if AVR32
help
Choose which driver to use for the Atmel MCI Silicon
@@ -368,7 +365,7 @@ config MMC_SDRICOH_CS
config MMC_TMIO
tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function support"
- depends on MFD_TMIO || MFD_ASIC3 || SUPERH
+ depends on MFD_TMIO || MFD_ASIC3 || MFD_SH_MOBILE_SDHI
help
This provides support for the SD/MMC cell found in TC6393XB,
T7L66XB and also HTC ASIC3
@@ -399,7 +396,7 @@ config MMC_VIA_SDMMC
config SDH_BFIN
tristate "Blackfin Secure Digital Host support"
- depends on MMC && ((BF54x && !BF544) || (BF51x && !BF512))
+ depends on (BF54x && !BF544) || (BF51x && !BF512)
help
If you say yes here you will get support for the Blackfin on-chip
Secure Digital Host interface. This includes support for MMC and
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 3d253dd4240..f4803977dfc 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -12,7 +12,6 @@ obj-$(CONFIG_MMC_IMX) += imxmmc.o
obj-$(CONFIG_MMC_MXC) += mxcmmc.o
obj-$(CONFIG_MMC_SDHCI) += sdhci.o
obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
-obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o
obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o
obj-$(CONFIG_MMC_WBSD) += wbsd.o
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index 63924e0c7ea..91dc60cd032 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -78,6 +78,17 @@
#define DRIVER_NAME "at91_mci"
+static inline int at91mci_is_mci1rev2xx(void)
+{
+ return ( cpu_is_at91sam9260()
+ || cpu_is_at91sam9263()
+ || cpu_is_at91cap9()
+ || cpu_is_at91sam9rl()
+ || cpu_is_at91sam9g10()
+ || cpu_is_at91sam9g20()
+ );
+}
+
#define FL_SENT_COMMAND (1 << 0)
#define FL_SENT_STOP (1 << 1)
@@ -88,6 +99,10 @@
#define at91_mci_read(host, reg) __raw_readl((host)->baseaddr + (reg))
#define at91_mci_write(host, reg, val) __raw_writel((val), (host)->baseaddr + (reg))
+#define MCI_BLKSIZE 512
+#define MCI_MAXBLKSIZE 4095
+#define MCI_BLKATONCE 256
+#define MCI_BUFSIZE (MCI_BLKSIZE * MCI_BLKATONCE)
/*
* Low level type for this driver
@@ -200,8 +215,8 @@ static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data
size = data->blksz * data->blocks;
len = data->sg_len;
- /* AT91SAM926[0/3] Data Write Operation and number of bytes erratum */
- if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
+ /* MCI1 rev2xx Data Write Operation and number of bytes erratum */
+ if (at91mci_is_mci1rev2xx())
if (host->total_length == 12)
memset(dmabuf, 0, 12);
@@ -227,8 +242,10 @@ static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data
for (index = 0; index < (amount / 4); index++)
*dmabuf++ = swab32(sgbuffer[index]);
} else {
- memcpy(dmabuf, sgbuffer, amount);
- dmabuf += amount;
+ char *tmpv = (char *)dmabuf;
+ memcpy(tmpv, sgbuffer, amount);
+ tmpv += amount;
+ dmabuf = (unsigned *)tmpv;
}
kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
@@ -245,80 +262,14 @@ static inline void at91_mci_sg_to_dma(struct at91mci_host *host, struct mmc_data
}
/*
- * Prepare a dma read
- */
-static void at91_mci_pre_dma_read(struct at91mci_host *host)
-{
- int i;
- struct scatterlist *sg;
- struct mmc_command *cmd;
- struct mmc_data *data;
-
- pr_debug("pre dma read\n");
-
- cmd = host->cmd;
- if (!cmd) {
- pr_debug("no command\n");
- return;
- }
-
- data = cmd->data;
- if (!data) {
- pr_debug("no data\n");
- return;
- }
-
- for (i = 0; i < 2; i++) {
- /* nothing left to transfer */
- if (host->transfer_index >= data->sg_len) {
- pr_debug("Nothing left to transfer (index = %d)\n", host->transfer_index);
- break;
- }
-
- /* Check to see if this needs filling */
- if (i == 0) {
- if (at91_mci_read(host, ATMEL_PDC_RCR) != 0) {
- pr_debug("Transfer active in current\n");
- continue;
- }
- }
- else {
- if (at91_mci_read(host, ATMEL_PDC_RNCR) != 0) {
- pr_debug("Transfer active in next\n");
- continue;
- }
- }
-
- /* Setup the next transfer */
- pr_debug("Using transfer index %d\n", host->transfer_index);
-
- sg = &data->sg[host->transfer_index++];
- pr_debug("sg = %p\n", sg);
-
- sg->dma_address = dma_map_page(NULL, sg_page(sg), sg->offset, sg->length, DMA_FROM_DEVICE);
-
- pr_debug("dma address = %08X, length = %d\n", sg->dma_address, sg->length);
-
- if (i == 0) {
- at91_mci_write(host, ATMEL_PDC_RPR, sg->dma_address);
- at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ? sg->length : sg->length / 4);
- }
- else {
- at91_mci_write(host, ATMEL_PDC_RNPR, sg->dma_address);
- at91_mci_write(host, ATMEL_PDC_RNCR, (data->blksz & 0x3) ? sg->length : sg->length / 4);
- }
- }
-
- pr_debug("pre dma read done\n");
-}
-
-/*
* Handle after a dma read
*/
static void at91_mci_post_dma_read(struct at91mci_host *host)
{
struct mmc_command *cmd;
struct mmc_data *data;
+ unsigned int len, i, size;
+ unsigned *dmabuf = host->buffer;
pr_debug("post dma read\n");
@@ -334,42 +285,39 @@ static void at91_mci_post_dma_read(struct at91mci_host *host)
return;
}
- while (host->in_use_index < host->transfer_index) {
- struct scatterlist *sg;
+ size = data->blksz * data->blocks;
+ len = data->sg_len;
- pr_debug("finishing index %d\n", host->in_use_index);
+ at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
+ at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
- sg = &data->sg[host->in_use_index++];
+ for (i = 0; i < len; i++) {
+ struct scatterlist *sg;
+ int amount;
+ unsigned int *sgbuffer;
- pr_debug("Unmapping page %08X\n", sg->dma_address);
+ sg = &data->sg[i];
- dma_unmap_page(NULL, sg->dma_address, sg->length, DMA_FROM_DEVICE);
+ sgbuffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
+ amount = min(size, sg->length);
+ size -= amount;
if (cpu_is_at91rm9200()) { /* AT91RM9200 errata */
- unsigned int *buffer;
int index;
-
- /* Swap the contents of the buffer */
- buffer = kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
- pr_debug("buffer = %p, length = %d\n", buffer, sg->length);
-
- for (index = 0; index < (sg->length / 4); index++)
- buffer[index] = swab32(buffer[index]);
-
- kunmap_atomic(buffer, KM_BIO_SRC_IRQ);
+ for (index = 0; index < (amount / 4); index++)
+ sgbuffer[index] = swab32(*dmabuf++);
+ } else {
+ char *tmpv = (char *)dmabuf;
+ memcpy(sgbuffer, tmpv, amount);
+ tmpv += amount;
+ dmabuf = (unsigned *)tmpv;
}
- flush_dcache_page(sg_page(sg));
-
- data->bytes_xfered += sg->length;
- }
-
- /* Is there another transfer to trigger? */
- if (host->transfer_index < data->sg_len)
- at91_mci_pre_dma_read(host);
- else {
- at91_mci_write(host, AT91_MCI_IDR, AT91_MCI_ENDRX);
- at91_mci_write(host, AT91_MCI_IER, AT91_MCI_RXBUFF);
+ kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ);
+ dmac_flush_range((void *)sgbuffer, ((void *)sgbuffer) + amount);
+ data->bytes_xfered += amount;
+ if (size == 0)
+ break;
}
pr_debug("post dma read done\n");
@@ -461,7 +409,7 @@ static void at91_mci_enable(struct at91mci_host *host)
at91_mci_write(host, AT91_MCI_DTOR, AT91_MCI_DTOMUL_1M | AT91_MCI_DTOCYC);
mr = AT91_MCI_PDCMODE | 0x34a;
- if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
+ if (at91mci_is_mci1rev2xx())
mr |= AT91_MCI_RDPROOF | AT91_MCI_WRPROOF;
at91_mci_write(host, AT91_MCI_MR, mr);
@@ -602,10 +550,14 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command
/*
* Handle a read
*/
- host->buffer = NULL;
host->total_length = 0;
- at91_mci_pre_dma_read(host);
+ at91_mci_write(host, ATMEL_PDC_RPR, host->physical_address);
+ at91_mci_write(host, ATMEL_PDC_RCR, (data->blksz & 0x3) ?
+ (blocks * block_length) : (blocks * block_length) / 4);
+ at91_mci_write(host, ATMEL_PDC_RNPR, 0);
+ at91_mci_write(host, ATMEL_PDC_RNCR, 0);
+
ier = AT91_MCI_ENDRX /* | AT91_MCI_RXBUFF */;
}
else {
@@ -614,27 +566,15 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command
*/
host->total_length = block_length * blocks;
/*
- * AT91SAM926[0/3] Data Write Operation and
+ * MCI1 rev2xx Data Write Operation and
* number of bytes erratum
*/
- if (cpu_is_at91sam9260 () || cpu_is_at91sam9263())
+ if (at91mci_is_mci1rev2xx())
if (host->total_length < 12)
host->total_length = 12;
- host->buffer = kmalloc(host->total_length, GFP_KERNEL);
- if (!host->buffer) {
- pr_debug("Can't alloc tx buffer\n");
- cmd->error = -ENOMEM;
- mmc_request_done(host->mmc, host->request);
- return;
- }
-
at91_mci_sg_to_dma(host, data);
- host->physical_address = dma_map_single(NULL,
- host->buffer, host->total_length,
- DMA_TO_DEVICE);
-
pr_debug("Transmitting %d bytes\n", host->total_length);
at91_mci_write(host, ATMEL_PDC_TPR, host->physical_address);
@@ -701,14 +641,6 @@ static void at91_mci_completed_command(struct at91mci_host *host, unsigned int s
cmd->resp[2] = at91_mci_read(host, AT91_MCI_RSPR(2));
cmd->resp[3] = at91_mci_read(host, AT91_MCI_RSPR(3));
- if (host->buffer) {
- dma_unmap_single(NULL,
- host->physical_address, host->total_length,
- DMA_TO_DEVICE);
- kfree(host->buffer);
- host->buffer = NULL;
- }
-
pr_debug("Status = %08X/%08x [%08X %08X %08X %08X]\n",
status, at91_mci_read(host, AT91_MCI_SR),
cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]);
@@ -754,7 +686,8 @@ static void at91_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
host->request = mrq;
host->flags = 0;
- mod_timer(&host->timer, jiffies + HZ);
+ /* more than 1s timeout needed with slow SD cards */
+ mod_timer(&host->timer, jiffies + msecs_to_jiffies(2000));
at91_mci_process_next(host);
}
@@ -942,7 +875,8 @@ static irqreturn_t at91_mmc_det_irq(int irq, void *_host)
pr_debug("****** Resetting SD-card bus width ******\n");
at91_mci_write(host, AT91_MCI_SDCR, at91_mci_read(host, AT91_MCI_SDCR) & ~AT91_MCI_SDCBUS);
}
- mmc_detect_change(host->mmc, msecs_to_jiffies(100));
+ /* 0.5s needed because of early card detect switch firing */
+ mmc_detect_change(host->mmc, msecs_to_jiffies(500));
}
return IRQ_HANDLED;
}
@@ -1006,24 +940,42 @@ static int __init at91_mci_probe(struct platform_device *pdev)
mmc->f_min = 375000;
mmc->f_max = 25000000;
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
- mmc->caps = MMC_CAP_SDIO_IRQ;
+ mmc->caps = 0;
- mmc->max_blk_size = 4095;
- mmc->max_blk_count = mmc->max_req_size;
+ mmc->max_blk_size = MCI_MAXBLKSIZE;
+ mmc->max_blk_count = MCI_BLKATONCE;
+ mmc->max_req_size = MCI_BUFSIZE;
+ mmc->max_phys_segs = MCI_BLKATONCE;
+ mmc->max_hw_segs = MCI_BLKATONCE;
+ mmc->max_seg_size = MCI_BUFSIZE;
host = mmc_priv(mmc);
host->mmc = mmc;
- host->buffer = NULL;
host->bus_mode = 0;
host->board = pdev->dev.platform_data;
if (host->board->wire4) {
- if (cpu_is_at91sam9260() || cpu_is_at91sam9263())
+ if (at91mci_is_mci1rev2xx())
mmc->caps |= MMC_CAP_4_BIT_DATA;
else
dev_warn(&pdev->dev, "4 wire bus mode not supported"
" - using 1 wire\n");
}
+ host->buffer = dma_alloc_coherent(&pdev->dev, MCI_BUFSIZE,
+ &host->physical_address, GFP_KERNEL);
+ if (!host->buffer) {
+ ret = -ENOMEM;
+ dev_err(&pdev->dev, "Can't allocate transmit buffer\n");
+ goto fail5;
+ }
+
+ /* Add SDIO capability when available */
+ if (at91mci_is_mci1rev2xx()) {
+ /* at91mci MCI1 rev2xx sdio interrupt erratum */
+ if (host->board->wire4 || !host->board->slot_b)
+ mmc->caps |= MMC_CAP_SDIO_IRQ;
+ }
+
/*
* Reserve GPIOs ... board init code makes sure these pins are set
* up as GPIOs with the right direction (input, except for vcc)
@@ -1032,7 +984,7 @@ static int __init at91_mci_probe(struct platform_device *pdev)
ret = gpio_request(host->board->det_pin, "mmc_detect");
if (ret < 0) {
dev_dbg(&pdev->dev, "couldn't claim card detect pin\n");
- goto fail5;
+ goto fail4b;
}
}
if (host->board->wp_pin) {
@@ -1132,6 +1084,10 @@ fail3:
fail4:
if (host->board->det_pin)
gpio_free(host->board->det_pin);
+fail4b:
+ if (host->buffer)
+ dma_free_coherent(&pdev->dev, MCI_BUFSIZE,
+ host->buffer, host->physical_address);
fail5:
mmc_free_host(mmc);
fail6:
@@ -1154,6 +1110,10 @@ static int __exit at91_mci_remove(struct platform_device *pdev)
host = mmc_priv(mmc);
+ if (host->buffer)
+ dma_free_coherent(&pdev->dev, MCI_BUFSIZE,
+ host->buffer, host->physical_address);
+
if (host->board->det_pin) {
if (device_can_wakeup(&pdev->dev))
free_irq(gpio_to_irq(host->board->det_pin), host);
diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c
index 3343a57355c..56f7b448b91 100644
--- a/drivers/mmc/host/bfin_sdh.c
+++ b/drivers/mmc/host/bfin_sdh.c
@@ -115,7 +115,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data)
unsigned int length;
unsigned int data_ctl;
unsigned int dma_cfg;
- struct scatterlist *sg;
+ unsigned int cycle_ns, timeout;
dev_dbg(mmc_dev(host->mmc), "%s enter flags: 0x%x\n", __func__, data->flags);
host->data = data;
@@ -136,8 +136,11 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data)
data_ctl |= ((ffs(data->blksz) - 1) << 4);
bfin_write_SDH_DATA_CTL(data_ctl);
-
- bfin_write_SDH_DATA_TIMER(0xFFFF);
+ /* the time of a host clock period in ns */
+ cycle_ns = 1000000000 / (get_sclk() / (2 * (host->clk_div + 1)));
+ timeout = data->timeout_ns / cycle_ns;
+ timeout += data->timeout_clks;
+ bfin_write_SDH_DATA_TIMER(timeout);
SSYNC();
if (data->flags & MMC_DATA_READ) {
@@ -151,6 +154,7 @@ static int sdh_setup_data(struct sdh_host *host, struct mmc_data *data)
#if defined(CONFIG_BF54x)
dma_cfg |= DMAFLOW_ARRAY | NDSIZE_5 | RESTART | WDSIZE_32 | DMAEN;
{
+ struct scatterlist *sg;
int i;
for_each_sg(data->sg, sg, host->dma_len, i) {
host->sg_cpu[i].start_addr = sg_dma_address(sg);
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index dd45e7c3517..3bd0ba294e9 100644
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -73,6 +73,7 @@
/* DAVINCI_MMCCTL definitions */
#define MMCCTL_DATRST (1 << 0)
#define MMCCTL_CMDRST (1 << 1)
+#define MMCCTL_WIDTH_8_BIT (1 << 8)
#define MMCCTL_WIDTH_4_BIT (1 << 2)
#define MMCCTL_DATEG_DISABLED (0 << 6)
#define MMCCTL_DATEG_RISING (1 << 6)
@@ -791,22 +792,42 @@ static void calculate_clk_divider(struct mmc_host *mmc, struct mmc_ios *ios)
static void mmc_davinci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
- unsigned int mmc_pclk = 0;
struct mmc_davinci_host *host = mmc_priv(mmc);
- mmc_pclk = host->mmc_input_clk;
dev_dbg(mmc_dev(host->mmc),
"clock %dHz busmode %d powermode %d Vdd %04x\n",
ios->clock, ios->bus_mode, ios->power_mode,
ios->vdd);
- if (ios->bus_width == MMC_BUS_WIDTH_4) {
- dev_dbg(mmc_dev(host->mmc), "Enabling 4 bit mode\n");
- writel(readl(host->base + DAVINCI_MMCCTL) | MMCCTL_WIDTH_4_BIT,
- host->base + DAVINCI_MMCCTL);
- } else {
- dev_dbg(mmc_dev(host->mmc), "Disabling 4 bit mode\n");
- writel(readl(host->base + DAVINCI_MMCCTL) & ~MMCCTL_WIDTH_4_BIT,
+
+ switch (ios->bus_width) {
+ case MMC_BUS_WIDTH_8:
+ dev_dbg(mmc_dev(host->mmc), "Enabling 8 bit mode\n");
+ writel((readl(host->base + DAVINCI_MMCCTL) &
+ ~MMCCTL_WIDTH_4_BIT) | MMCCTL_WIDTH_8_BIT,
host->base + DAVINCI_MMCCTL);
+ break;
+ case MMC_BUS_WIDTH_4:
+ dev_dbg(mmc_dev(host->mmc), "Enabling 4 bit mode\n");
+ if (host->version == MMC_CTLR_VERSION_2)
+ writel((readl(host->base + DAVINCI_MMCCTL) &
+ ~MMCCTL_WIDTH_8_BIT) | MMCCTL_WIDTH_4_BIT,
+ host->base + DAVINCI_MMCCTL);
+ else
+ writel(readl(host->base + DAVINCI_MMCCTL) |
+ MMCCTL_WIDTH_4_BIT,
+ host->base + DAVINCI_MMCCTL);
+ break;
+ case MMC_BUS_WIDTH_1:
+ dev_dbg(mmc_dev(host->mmc), "Enabling 1 bit mode\n");
+ if (host->version == MMC_CTLR_VERSION_2)
+ writel(readl(host->base + DAVINCI_MMCCTL) &
+ ~(MMCCTL_WIDTH_8_BIT | MMCCTL_WIDTH_4_BIT),
+ host->base + DAVINCI_MMCCTL);
+ else
+ writel(readl(host->base + DAVINCI_MMCCTL) &
+ ~MMCCTL_WIDTH_4_BIT,
+ host->base + DAVINCI_MMCCTL);
+ break;
}
calculate_clk_divider(mmc, ios);
@@ -1189,10 +1210,14 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev)
/* REVISIT: someday, support IRQ-driven card detection. */
mmc->caps |= MMC_CAP_NEEDS_POLL;
+ mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
- if (!pdata || pdata->wires == 4 || pdata->wires == 0)
+ if (pdata && (pdata->wires == 4 || pdata->wires == 0))
mmc->caps |= MMC_CAP_4_BIT_DATA;
+ if (pdata && (pdata->wires == 8))
+ mmc->caps |= (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA);
+
host->version = pdata->version;
mmc->ops = &mmc_davinci_ops;
diff --git a/drivers/mmc/host/ricoh_mmc.c b/drivers/mmc/host/ricoh_mmc.c
deleted file mode 100644
index f6279051332..00000000000
--- a/drivers/mmc/host/ricoh_mmc.c
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * ricoh_mmc.c - Dummy driver to disable the Rioch MMC controller.
- *
- * Copyright (C) 2007 Philip Langdale, 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 is a conceptually ridiculous driver, but it is required by the way
- * the Ricoh multi-function chips (R5CXXX) work. These chips implement
- * the four main memory card controllers (SD, MMC, MS, xD) and one or both
- * of cardbus or firewire. It happens that they implement SD and MMC
- * support as separate controllers (and PCI functions). The linux SDHCI
- * driver supports MMC cards but the chip detects MMC cards in hardware
- * and directs them to the MMC controller - so the SDHCI driver never sees
- * them. To get around this, we must disable the useless MMC controller.
- * At that point, the SDHCI controller will start seeing them. As a bonus,
- * a detection event occurs immediately, even if the MMC card is already
- * in the reader.
- *
- * It seems to be the case that the relevant PCI registers to deactivate the
- * MMC controller live on PCI function 0, which might be the cardbus controller
- * or the firewire controller, depending on the particular chip in question. As
- * such, it makes what this driver has to do unavoidably ugly. Such is life.
- */
-
-#include <linux/pci.h>
-
-#define DRIVER_NAME "ricoh-mmc"
-
-static const struct pci_device_id pci_ids[] __devinitdata = {
- {
- .vendor = PCI_VENDOR_ID_RICOH,
- .device = PCI_DEVICE_ID_RICOH_R5C843,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- },
- { /* end: all zeroes */ },
-};
-
-MODULE_DEVICE_TABLE(pci, pci_ids);
-
-static int ricoh_mmc_disable(struct pci_dev *fw_dev)
-{
- u8 write_enable;
- u8 write_target;
- u8 disable;
-
- if (fw_dev->device == PCI_DEVICE_ID_RICOH_RL5C476) {
- /* via RL5C476 */
-
- pci_read_config_byte(fw_dev, 0xB7, &disable);
- if (disable & 0x02) {
- printk(KERN_INFO DRIVER_NAME
- ": Controller already disabled. " \
- "Nothing to do.\n");
- return -ENODEV;
- }
-
- pci_read_config_byte(fw_dev, 0x8E, &write_enable);
- pci_write_config_byte(fw_dev, 0x8E, 0xAA);
- pci_read_config_byte(fw_dev, 0x8D, &write_target);
- pci_write_config_byte(fw_dev, 0x8D, 0xB7);
- pci_write_config_byte(fw_dev, 0xB7, disable | 0x02);
- pci_write_config_byte(fw_dev, 0x8E, write_enable);
- pci_write_config_byte(fw_dev, 0x8D, write_target);
- } else {
- /* via R5C832 */
-
- pci_read_config_byte(fw_dev, 0xCB, &disable);
- if (disable & 0x02) {
- printk(KERN_INFO DRIVER_NAME
- ": Controller already disabled. " \
- "Nothing to do.\n");
- return -ENODEV;
- }
-
- pci_read_config_byte(fw_dev, 0xCA, &write_enable);
- pci_write_config_byte(fw_dev, 0xCA, 0x57);
- pci_write_config_byte(fw_dev, 0xCB, disable | 0x02);
- pci_write_config_byte(fw_dev, 0xCA, write_enable);
- }
-
- printk(KERN_INFO DRIVER_NAME
- ": Controller is now disabled.\n");
-
- return 0;
-}
-
-static int ricoh_mmc_enable(struct pci_dev *fw_dev)
-{
- u8 write_enable;
- u8 write_target;
- u8 disable;
-
- if (fw_dev->device == PCI_DEVICE_ID_RICOH_RL5C476) {
- /* via RL5C476 */
-
- pci_read_config_byte(fw_dev, 0x8E, &write_enable);
- pci_write_config_byte(fw_dev, 0x8E, 0xAA);
- pci_read_config_byte(fw_dev, 0x8D, &write_target);
- pci_write_config_byte(fw_dev, 0x8D, 0xB7);
- pci_read_config_byte(fw_dev, 0xB7, &disable);
- pci_write_config_byte(fw_dev, 0xB7, disable & ~0x02);
- pci_write_config_byte(fw_dev, 0x8E, write_enable);
- pci_write_config_byte(fw_dev, 0x8D, write_target);
- } else {
- /* via R5C832 */
-
- pci_read_config_byte(fw_dev, 0xCA, &write_enable);
- pci_read_config_byte(fw_dev, 0xCB, &disable);
- pci_write_config_byte(fw_dev, 0xCA, 0x57);
- pci_write_config_byte(fw_dev, 0xCB, disable & ~0x02);
- pci_write_config_byte(fw_dev, 0xCA, write_enable);
- }
-
- printk(KERN_INFO DRIVER_NAME
- ": Controller is now re-enabled.\n");
-
- return 0;
-}
-
-static int __devinit ricoh_mmc_probe(struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- u8 rev;
- u8 ctrlfound = 0;
-
- struct pci_dev *fw_dev = NULL;
-
- BUG_ON(pdev == NULL);
- BUG_ON(ent == NULL);
-
- pci_read_config_byte(pdev, PCI_CLASS_REVISION, &rev);
-
- printk(KERN_INFO DRIVER_NAME
- ": Ricoh MMC controller found at %s [%04x:%04x] (rev %x)\n",
- pci_name(pdev), (int)pdev->vendor, (int)pdev->device,
- (int)rev);
-
- while ((fw_dev =
- pci_get_device(PCI_VENDOR_ID_RICOH,
- PCI_DEVICE_ID_RICOH_RL5C476, fw_dev))) {
- if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) &&
- PCI_FUNC(fw_dev->devfn) == 0 &&
- pdev->bus == fw_dev->bus) {
- if (ricoh_mmc_disable(fw_dev) != 0)
- return -ENODEV;
-
- pci_set_drvdata(pdev, fw_dev);
-
- ++ctrlfound;
- break;
- }
- }
-
- fw_dev = NULL;
-
- while (!ctrlfound &&
- (fw_dev = pci_get_device(PCI_VENDOR_ID_RICOH,
- PCI_DEVICE_ID_RICOH_R5C832, fw_dev))) {
- if (PCI_SLOT(pdev->devfn) == PCI_SLOT(fw_dev->devfn) &&
- PCI_FUNC(fw_dev->devfn) == 0 &&
- pdev->bus == fw_dev->bus) {
- if (ricoh_mmc_disable(fw_dev) != 0)
- return -ENODEV;
-
- pci_set_drvdata(pdev, fw_dev);
-
- ++ctrlfound;
- }
- }
-
- if (!ctrlfound) {
- printk(KERN_WARNING DRIVER_NAME
- ": Main Ricoh function not found. Cannot disable controller.\n");
- return -ENODEV;
- }
-
- return 0;
-}
-
-static void __devexit ricoh_mmc_remove(struct pci_dev *pdev)
-{
- struct pci_dev *fw_dev = NULL;
-
- fw_dev = pci_get_drvdata(pdev);
- BUG_ON(fw_dev == NULL);
-
- ricoh_mmc_enable(fw_dev);
-
- pci_set_drvdata(pdev, NULL);
-}
-
-static int ricoh_mmc_suspend_late(struct pci_dev *pdev, pm_message_t state)
-{
- struct pci_dev *fw_dev = NULL;
-
- fw_dev = pci_get_drvdata(pdev);
- BUG_ON(fw_dev == NULL);
-
- printk(KERN_INFO DRIVER_NAME ": Suspending.\n");
-
- ricoh_mmc_enable(fw_dev);
-
- return 0;
-}
-
-static int ricoh_mmc_resume_early(struct pci_dev *pdev)
-{
- struct pci_dev *fw_dev = NULL;
-
- fw_dev = pci_get_drvdata(pdev);
- BUG_ON(fw_dev == NULL);
-
- printk(KERN_INFO DRIVER_NAME ": Resuming.\n");
-
- ricoh_mmc_disable(fw_dev);
-
- return 0;
-}
-
-static struct pci_driver ricoh_mmc_driver = {
- .name = DRIVER_NAME,
- .id_table = pci_ids,
- .probe = ricoh_mmc_probe,
- .remove = __devexit_p(ricoh_mmc_remove),
- .suspend_late = ricoh_mmc_suspend_late,
- .resume_early = ricoh_mmc_resume_early,
-};
-
-/*****************************************************************************\
- * *
- * Driver init/exit *
- * *
-\*****************************************************************************/
-
-static int __init ricoh_mmc_drv_init(void)
-{
- printk(KERN_INFO DRIVER_NAME
- ": Ricoh MMC Controller disabling driver\n");
- printk(KERN_INFO DRIVER_NAME ": Copyright(c) Philip Langdale\n");
-
- return pci_register_driver(&ricoh_mmc_driver);
-}
-
-static void __exit ricoh_mmc_drv_exit(void)
-{
- pci_unregister_driver(&ricoh_mmc_driver);
-}
-
-module_init(ricoh_mmc_drv_init);
-module_exit(ricoh_mmc_drv_exit);
-
-MODULE_AUTHOR("Philip Langdale <philipl@alumni.utexas.net>");
-MODULE_DESCRIPTION("Ricoh MMC Controller disabling driver");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index d96e1abf2d6..2fdf7689ae6 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -1179,7 +1179,7 @@ static int s3cmci_card_present(struct mmc_host *mmc)
struct s3c24xx_mci_pdata *pdata = host->pdata;
int ret;
- if (pdata->gpio_detect == 0)
+ if (pdata->no_detect)
return -ENOSYS;
ret = gpio_get_value(pdata->gpio_detect) ? 0 : 1;
@@ -1360,6 +1360,8 @@ static struct mmc_host_ops s3cmci_ops = {
static struct s3c24xx_mci_pdata s3cmci_def_pdata = {
/* This is currently here to avoid a number of if (host->pdata)
* checks. Any zero fields to ensure reasonable defaults are picked. */
+ .no_wprotect = 1,
+ .no_detect = 1,
};
#ifdef CONFIG_CPU_FREQ
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 5c3a1767770..8e1020cf73f 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -80,9 +80,6 @@ struct sdhci_pci_chip {
static int ricoh_probe(struct sdhci_pci_chip *chip)
{
- if (chip->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM)
- chip->quirks |= SDHCI_QUIRK_CLOCK_BEFORE_RESET;
-
if (chip->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG ||
chip->pdev->subsystem_vendor == PCI_VENDOR_ID_SONY)
chip->quirks |= SDHCI_QUIRK_NO_CARD_NO_RESET;
@@ -92,7 +89,9 @@ static int ricoh_probe(struct sdhci_pci_chip *chip)
static const struct sdhci_pci_fixes sdhci_ricoh = {
.probe = ricoh_probe,
- .quirks = SDHCI_QUIRK_32BIT_DMA_ADDR,
+ .quirks = SDHCI_QUIRK_32BIT_DMA_ADDR |
+ SDHCI_QUIRK_FORCE_DMA |
+ SDHCI_QUIRK_CLOCK_BEFORE_RESET,
};
static const struct sdhci_pci_fixes sdhci_ene_712 = {
@@ -501,6 +500,7 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
{
struct sdhci_pci_chip *chip;
struct sdhci_pci_slot *slot;
+ mmc_pm_flag_t pm_flags = 0;
int i, ret;
chip = pci_get_drvdata(pdev);
@@ -519,6 +519,8 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
sdhci_resume_host(chip->slots[i]->host);
return ret;
}
+
+ pm_flags |= slot->host->mmc->pm_flags;
}
if (chip->fixes && chip->fixes->suspend) {
@@ -531,9 +533,15 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
}
pci_save_state(pdev);
- pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
- pci_disable_device(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ if (pm_flags & MMC_PM_KEEP_POWER) {
+ if (pm_flags & MMC_PM_WAKE_SDIO_IRQ)
+ pci_enable_wake(pdev, PCI_D3hot, 1);
+ pci_set_power_state(pdev, PCI_D3hot);
+ } else {
+ pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ }
return 0;
}
@@ -653,6 +661,8 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
goto unmap;
}
+ host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ;
+
ret = sdhci_add_host(host);
if (ret)
goto remove;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index c279fbc4c2e..d6ab62d539f 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -174,20 +174,31 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier);
}
-static void sdhci_init(struct sdhci_host *host)
+static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios);
+
+static void sdhci_init(struct sdhci_host *host, int soft)
{
- sdhci_reset(host, SDHCI_RESET_ALL);
+ if (soft)
+ sdhci_reset(host, SDHCI_RESET_CMD|SDHCI_RESET_DATA);
+ else
+ sdhci_reset(host, SDHCI_RESET_ALL);
sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK,
SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE);
+
+ if (soft) {
+ /* force clock reconfiguration */
+ host->clock = 0;
+ sdhci_set_ios(host->mmc, &host->mmc->ios);
+ }
}
static void sdhci_reinit(struct sdhci_host *host)
{
- sdhci_init(host);
+ sdhci_init(host, 0);
sdhci_enable_card_detection(host);
}
@@ -376,6 +387,20 @@ static void sdhci_kunmap_atomic(void *buffer, unsigned long *flags)
local_irq_restore(*flags);
}
+static void sdhci_set_adma_desc(u8 *desc, u32 addr, int len, unsigned cmd)
+{
+ __le32 *dataddr = (__le32 __force *)(desc + 4);
+ __le16 *cmdlen = (__le16 __force *)desc;
+
+ /* SDHCI specification says ADMA descriptors should be 4 byte
+ * aligned, so using 16 or 32bit operations should be safe. */
+
+ cmdlen[0] = cpu_to_le16(cmd);
+ cmdlen[1] = cpu_to_le16(len);
+
+ dataddr[0] = cpu_to_le32(addr);
+}
+
static int sdhci_adma_table_pre(struct sdhci_host *host,
struct mmc_data *data)
{
@@ -443,19 +468,11 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
sdhci_kunmap_atomic(buffer, &flags);
}
- desc[7] = (align_addr >> 24) & 0xff;
- desc[6] = (align_addr >> 16) & 0xff;
- desc[5] = (align_addr >> 8) & 0xff;
- desc[4] = (align_addr >> 0) & 0xff;
+ /* tran, valid */
+ sdhci_set_adma_desc(desc, align_addr, offset, 0x21);
BUG_ON(offset > 65536);
- desc[3] = (offset >> 8) & 0xff;
- desc[2] = (offset >> 0) & 0xff;
-
- desc[1] = 0x00;
- desc[0] = 0x21; /* tran, valid */
-
align += 4;
align_addr += 4;
@@ -465,19 +482,10 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
len -= offset;
}
- desc[7] = (addr >> 24) & 0xff;
- desc[6] = (addr >> 16) & 0xff;
- desc[5] = (addr >> 8) & 0xff;
- desc[4] = (addr >> 0) & 0xff;
-
BUG_ON(len > 65536);
- desc[3] = (len >> 8) & 0xff;
- desc[2] = (len >> 0) & 0xff;
-
- desc[1] = 0x00;
- desc[0] = 0x21; /* tran, valid */
-
+ /* tran, valid */
+ sdhci_set_adma_desc(desc, addr, len, 0x21);
desc += 8;
/*
@@ -490,16 +498,9 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
/*
* Add a terminating entry.
*/
- desc[7] = 0;
- desc[6] = 0;
- desc[5] = 0;
- desc[4] = 0;
- desc[3] = 0;
- desc[2] = 0;
-
- desc[1] = 0x00;
- desc[0] = 0x03; /* nop, end, valid */
+ /* nop, end, valid */
+ sdhci_set_adma_desc(desc, 0, 0, 0x3);
/*
* Resync align buffer as we might have changed it.
@@ -1610,16 +1611,13 @@ int sdhci_resume_host(struct sdhci_host *host)
if (ret)
return ret;
- sdhci_init(host);
+ sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER));
mmiowb();
ret = mmc_resume_host(host->mmc);
- if (ret)
- return ret;
-
sdhci_enable_card_detection(host);
- return 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(sdhci_resume_host);
@@ -1874,7 +1872,7 @@ int sdhci_add_host(struct sdhci_host *host)
if (ret)
goto untasklet;
- sdhci_init(host);
+ sdhci_init(host, 0);
#ifdef CONFIG_MMC_DEBUG
sdhci_dumpregs(host);
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index e22c3fa3516..b2b577f6afd 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -323,7 +323,7 @@ static irqreturn_t tmio_mmc_irq(int irq, void *devid)
if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) {
ack_mmc_irqs(host, TMIO_STAT_CARD_INSERT |
TMIO_STAT_CARD_REMOVE);
- mmc_detect_change(host->mmc, 0);
+ mmc_detect_change(host->mmc, msecs_to_jiffies(100));
}
/* CRC and other errors */
@@ -550,6 +550,7 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
mmc->ops = &tmio_mmc_ops;
mmc->caps = MMC_CAP_4_BIT_DATA;
+ mmc->caps |= pdata->capabilities;
mmc->f_max = pdata->hclk;
mmc->f_min = mmc->f_max / 512;
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
@@ -568,14 +569,14 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
if (ret >= 0)
host->irq = ret;
else
- goto unmap_ctl;
+ goto cell_disable;
disable_mmc_irqs(host, TMIO_MASK_ALL);
ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED |
IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host);
if (ret)
- goto unmap_ctl;
+ goto cell_disable;
mmc_add_host(mmc);
@@ -587,6 +588,9 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
return 0;
+cell_disable:
+ if (cell->disable)
+ cell->disable(dev);
unmap_ctl:
iounmap(host->ctl);
host_free:
@@ -597,6 +601,7 @@ out:
static int __devexit tmio_mmc_remove(struct platform_device *dev)
{
+ struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
struct mmc_host *mmc = platform_get_drvdata(dev);
platform_set_drvdata(dev, NULL);
@@ -605,6 +610,8 @@ static int __devexit tmio_mmc_remove(struct platform_device *dev)
struct tmio_mmc_host *host = mmc_priv(mmc);
mmc_remove_host(mmc);
free_irq(host->irq, host);
+ if (cell->disable)
+ cell->disable(dev);
iounmap(host->ctl);
mmc_free_host(mmc);
}
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index 692dc23363b..dafecfbcd91 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -55,10 +55,8 @@
/* Define some IRQ masks */
/* This is the mask used at reset by the chip */
#define TMIO_MASK_ALL 0x837f031d
-#define TMIO_MASK_READOP (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND | \
- TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT)
-#define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND | \
- TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT)
+#define TMIO_MASK_READOP (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND)
+#define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND)
#define TMIO_MASK_CMD (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT | \
TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT)
#define TMIO_MASK_IRQ (TMIO_MASK_READOP | TMIO_MASK_WRITEOP | TMIO_MASK_CMD)
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 14cec04c34f..fad40aa6f09 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -37,6 +37,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/stringify.h>
+#include <linux/namei.h>
#include <linux/stat.h>
#include <linux/miscdevice.h>
#include <linux/log2.h>
@@ -50,7 +51,8 @@
/**
* struct mtd_dev_param - MTD device parameter description data structure.
- * @name: MTD device name or number string
+ * @name: MTD character device node path, MTD device name, or MTD device number
+ * string
* @vid_hdr_offs: VID header offset
*/
struct mtd_dev_param {
@@ -59,10 +61,10 @@ struct mtd_dev_param {
};
/* Numbers of elements set in the @mtd_dev_param array */
-static int mtd_devs;
+static int __initdata mtd_devs;
/* MTD devices specification parameters */
-static struct mtd_dev_param mtd_dev_param[UBI_MAX_DEVICES];
+static struct mtd_dev_param __initdata mtd_dev_param[UBI_MAX_DEVICES];
/* Root UBI "class" object (corresponds to '/<sysfs>/class/ubi/') */
struct class *ubi_class;
@@ -87,7 +89,8 @@ DEFINE_MUTEX(ubi_devices_mutex);
static DEFINE_SPINLOCK(ubi_devices_lock);
/* "Show" method for files in '/<sysfs>/class/ubi/' */
-static ssize_t ubi_version_show(struct class *class, char *buf)
+static ssize_t ubi_version_show(struct class *class, struct class_attribute *attr,
+ char *buf)
{
return sprintf(buf, "%d\n", UBI_VERSION);
}
@@ -363,11 +366,13 @@ static void dev_release(struct device *dev)
/**
* ubi_sysfs_init - initialize sysfs for an UBI device.
* @ubi: UBI device description object
+ * @ref: set to %1 on exit in case of failure if a reference to @ubi->dev was
+ * taken
*
* This function returns zero in case of success and a negative error code in
* case of failure.
*/
-static int ubi_sysfs_init(struct ubi_device *ubi)
+static int ubi_sysfs_init(struct ubi_device *ubi, int *ref)
{
int err;
@@ -379,6 +384,7 @@ static int ubi_sysfs_init(struct ubi_device *ubi)
if (err)
return err;
+ *ref = 1;
err = device_create_file(&ubi->dev, &dev_eraseblock_size);
if (err)
return err;
@@ -434,7 +440,7 @@ static void ubi_sysfs_close(struct ubi_device *ubi)
}
/**
- * kill_volumes - destroy all volumes.
+ * kill_volumes - destroy all user volumes.
* @ubi: UBI device description object
*/
static void kill_volumes(struct ubi_device *ubi)
@@ -447,36 +453,29 @@ static void kill_volumes(struct ubi_device *ubi)
}
/**
- * free_user_volumes - free all user volumes.
- * @ubi: UBI device description object
- *
- * Normally the volumes are freed at the release function of the volume device
- * objects. However, on error paths the volumes have to be freed before the
- * device objects have been initialized.
- */
-static void free_user_volumes(struct ubi_device *ubi)
-{
- int i;
-
- for (i = 0; i < ubi->vtbl_slots; i++)
- if (ubi->volumes[i]) {
- kfree(ubi->volumes[i]->eba_tbl);
- kfree(ubi->volumes[i]);
- }
-}
-
-/**
* uif_init - initialize user interfaces for an UBI device.
* @ubi: UBI device description object
+ * @ref: set to %1 on exit in case of failure if a reference to @ubi->dev was
+ * taken, otherwise set to %0
+ *
+ * This function initializes various user interfaces for an UBI device. If the
+ * initialization fails at an early stage, this function frees all the
+ * resources it allocated, returns an error, and @ref is set to %0. However,
+ * if the initialization fails after the UBI device was registered in the
+ * driver core subsystem, this function takes a reference to @ubi->dev, because
+ * otherwise the release function ('dev_release()') would free whole @ubi
+ * object. The @ref argument is set to %1 in this case. The caller has to put
+ * this reference.
*
* This function returns zero in case of success and a negative error code in
- * case of failure. Note, this function destroys all volumes if it fails.
+ * case of failure.
*/
-static int uif_init(struct ubi_device *ubi)
+static int uif_init(struct ubi_device *ubi, int *ref)
{
int i, err;
dev_t dev;
+ *ref = 0;
sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num);
/*
@@ -504,7 +503,7 @@ static int uif_init(struct ubi_device *ubi)
goto out_unreg;
}
- err = ubi_sysfs_init(ubi);
+ err = ubi_sysfs_init(ubi, ref);
if (err)
goto out_sysfs;
@@ -522,6 +521,8 @@ static int uif_init(struct ubi_device *ubi)
out_volumes:
kill_volumes(ubi);
out_sysfs:
+ if (*ref)
+ get_device(&ubi->dev);
ubi_sysfs_close(ubi);
cdev_del(&ubi->cdev);
out_unreg:
@@ -875,7 +876,7 @@ static int ubi_reboot_notifier(struct notifier_block *n, unsigned long state,
int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
{
struct ubi_device *ubi;
- int i, err, do_free = 1;
+ int i, err, ref = 0;
/*
* Check if we already have the same MTD device attached.
@@ -975,9 +976,9 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
goto out_detach;
}
- err = uif_init(ubi);
+ err = uif_init(ubi, &ref);
if (err)
- goto out_nofree;
+ goto out_detach;
ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name);
if (IS_ERR(ubi->bgt_thread)) {
@@ -1025,12 +1026,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
out_uif:
uif_close(ubi);
-out_nofree:
- do_free = 0;
out_detach:
ubi_wl_close(ubi);
- if (do_free)
- free_user_volumes(ubi);
free_internal_volumes(ubi);
vfree(ubi->vtbl);
out_free:
@@ -1039,7 +1036,10 @@ out_free:
#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
vfree(ubi->dbg_peb_buf);
#endif
- kfree(ubi);
+ if (ref)
+ put_device(&ubi->dev);
+ else
+ kfree(ubi);
return err;
}
@@ -1096,7 +1096,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
/*
* Get a reference to the device in order to prevent 'dev_release()'
- * from freeing @ubi object.
+ * from freeing the @ubi object.
*/
get_device(&ubi->dev);
@@ -1116,13 +1116,50 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
}
/**
- * find_mtd_device - open an MTD device by its name or number.
- * @mtd_dev: name or number of the device
+ * open_mtd_by_chdev - open an MTD device by its character device node path.
+ * @mtd_dev: MTD character device node path
+ *
+ * This helper function opens an MTD device by its character node device path.
+ * Returns MTD device description object in case of success and a negative
+ * error code in case of failure.
+ */
+static struct mtd_info * __init open_mtd_by_chdev(const char *mtd_dev)
+{
+ int err, major, minor, mode;
+ struct path path;
+
+ /* Probably this is an MTD character device node path */
+ err = kern_path(mtd_dev, LOOKUP_FOLLOW, &path);
+ if (err)
+ return ERR_PTR(err);
+
+ /* MTD device number is defined by the major / minor numbers */
+ major = imajor(path.dentry->d_inode);
+ minor = iminor(path.dentry->d_inode);
+ mode = path.dentry->d_inode->i_mode;
+ path_put(&path);
+ if (major != MTD_CHAR_MAJOR || !S_ISCHR(mode))
+ return ERR_PTR(-EINVAL);
+
+ if (minor & 1)
+ /*
+ * Just do not think the "/dev/mtdrX" devices support is need,
+ * so do not support them to avoid doing extra work.
+ */
+ return ERR_PTR(-EINVAL);
+
+ return get_mtd_device(NULL, minor / 2);
+}
+
+/**
+ * open_mtd_device - open MTD device by name, character device path, or number.
+ * @mtd_dev: name, character device node path, or MTD device device number
*
* This function tries to open and MTD device described by @mtd_dev string,
- * which is first treated as an ASCII number, and if it is not true, it is
- * treated as MTD device name. Returns MTD device description object in case of
- * success and a negative error code in case of failure.
+ * which is first treated as ASCII MTD device number, and if it is not true, it
+ * is treated as MTD device name, and if that is also not true, it is treated
+ * as MTD character device node path. Returns MTD device description object in
+ * case of success and a negative error code in case of failure.
*/
static struct mtd_info * __init open_mtd_device(const char *mtd_dev)
{
@@ -1137,6 +1174,9 @@ static struct mtd_info * __init open_mtd_device(const char *mtd_dev)
* MTD device name.
*/
mtd = get_mtd_device_nm(mtd_dev);
+ if (IS_ERR(mtd) && PTR_ERR(mtd) == -ENODEV)
+ /* Probably this is an MTD character device node path */
+ mtd = open_mtd_by_chdev(mtd_dev);
} else
mtd = get_mtd_device(NULL, mtd_num);
@@ -1352,13 +1392,15 @@ static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp)
module_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 000);
MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: "
- "mtd=<name|num>[,<vid_hdr_offs>].\n"
+ "mtd=<name|num|path>[,<vid_hdr_offs>].\n"
"Multiple \"mtd\" parameters may be specified.\n"
- "MTD devices may be specified by their number or name.\n"
+ "MTD devices may be specified by their number, name, or "
+ "path to the MTD character device node.\n"
"Optional \"vid_hdr_offs\" parameter specifies UBI VID "
- "header position and data starting position to be used "
- "by UBI.\n"
- "Example: mtd=content,1984 mtd=4 - attach MTD device"
+ "header position to be used by UBI.\n"
+ "Example 1: mtd=/dev/mtd0 - attach MTD device "
+ "/dev/mtd0.\n"
+ "Example 2: mtd=content,1984 mtd=4 - attach MTD device "
"with name \"content\" using VID header offset 1984, and "
"MTD device number 4 with default VID header offset.");
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
index f30bcb372c0..17a10712972 100644
--- a/drivers/mtd/ubi/debug.h
+++ b/drivers/mtd/ubi/debug.h
@@ -96,8 +96,11 @@ void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len);
#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len);
+int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
+ int offset, int len);
#else
#define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0
+#define ubi_dbg_check_write(ubi, buf, pnum, offset, len) 0
#endif
#ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT
@@ -176,6 +179,7 @@ static inline int ubi_dbg_is_erase_failure(void)
#define ubi_dbg_is_write_failure() 0
#define ubi_dbg_is_erase_failure() 0
#define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0
+#define ubi_dbg_check_write(ubi, buf, pnum, offset, len) 0
#endif /* !CONFIG_MTD_UBI_DEBUG */
#endif /* !__UBI_DEBUG_H__ */
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 8aa51e7a6a7..b4ecc84c754 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -143,7 +143,7 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
err = paranoid_check_not_bad(ubi, pnum);
if (err)
- return err > 0 ? -EINVAL : err;
+ return err;
addr = (loff_t)pnum * ubi->peb_size + offset;
retry:
@@ -236,12 +236,12 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
err = paranoid_check_not_bad(ubi, pnum);
if (err)
- return err > 0 ? -EINVAL : err;
+ return err;
/* The area we are writing to has to contain all 0xFF bytes */
err = ubi_dbg_check_all_ff(ubi, pnum, offset, len);
if (err)
- return err > 0 ? -EINVAL : err;
+ return err;
if (offset >= ubi->leb_start) {
/*
@@ -250,10 +250,10 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
*/
err = paranoid_check_peb_ec_hdr(ubi, pnum);
if (err)
- return err > 0 ? -EINVAL : err;
+ return err;
err = paranoid_check_peb_vid_hdr(ubi, pnum);
if (err)
- return err > 0 ? -EINVAL : err;
+ return err;
}
if (ubi_dbg_is_write_failure()) {
@@ -273,6 +273,21 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset,
} else
ubi_assert(written == len);
+ if (!err) {
+ err = ubi_dbg_check_write(ubi, buf, pnum, offset, len);
+ if (err)
+ return err;
+
+ /*
+ * Since we always write sequentially, the rest of the PEB has
+ * to contain only 0xFF bytes.
+ */
+ offset += len;
+ len = ubi->peb_size - offset;
+ if (len)
+ err = ubi_dbg_check_all_ff(ubi, pnum, offset, len);
+ }
+
return err;
}
@@ -348,7 +363,7 @@ retry:
err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size);
if (err)
- return err > 0 ? -EINVAL : err;
+ return err;
if (ubi_dbg_is_erase_failure() && !err) {
dbg_err("cannot erase PEB %d (emulated)", pnum);
@@ -542,7 +557,7 @@ int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture)
err = paranoid_check_not_bad(ubi, pnum);
if (err != 0)
- return err > 0 ? -EINVAL : err;
+ return err;
if (ubi->ro_mode) {
ubi_err("read-only mode");
@@ -819,7 +834,7 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum,
err = paranoid_check_ec_hdr(ubi, pnum, ec_hdr);
if (err)
- return -EINVAL;
+ return err;
err = ubi_io_write(ubi, ec_hdr, pnum, 0, ubi->ec_hdr_alsize);
return err;
@@ -1083,7 +1098,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
err = paranoid_check_peb_ec_hdr(ubi, pnum);
if (err)
- return err > 0 ? -EINVAL : err;
+ return err;
vid_hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC);
vid_hdr->version = UBI_VERSION;
@@ -1092,7 +1107,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
err = paranoid_check_vid_hdr(ubi, pnum, vid_hdr);
if (err)
- return -EINVAL;
+ return err;
p = (char *)vid_hdr - ubi->vid_hdr_shift;
err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset,
@@ -1107,8 +1122,8 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
* @ubi: UBI device description object
* @pnum: physical eraseblock number to check
*
- * This function returns zero if the physical eraseblock is good, a positive
- * number if it is bad and a negative error code if an error occurred.
+ * This function returns zero if the physical eraseblock is good, %-EINVAL if
+ * it is bad and a negative error code if an error occurred.
*/
static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum)
{
@@ -1120,7 +1135,7 @@ static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum)
ubi_err("paranoid check failed for PEB %d", pnum);
ubi_dbg_dump_stack();
- return err;
+ return err > 0 ? -EINVAL : err;
}
/**
@@ -1130,7 +1145,7 @@ static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum)
* @ec_hdr: the erase counter header to check
*
* This function returns zero if the erase counter header contains valid
- * values, and %1 if not.
+ * values, and %-EINVAL if not.
*/
static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
const struct ubi_ec_hdr *ec_hdr)
@@ -1156,7 +1171,7 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
fail:
ubi_dbg_dump_ec_hdr(ec_hdr);
ubi_dbg_dump_stack();
- return 1;
+ return -EINVAL;
}
/**
@@ -1164,8 +1179,8 @@ fail:
* @ubi: UBI device description object
* @pnum: the physical eraseblock number to check
*
- * This function returns zero if the erase counter header is all right, %1 if
- * not, and a negative error code if an error occurred.
+ * This function returns zero if the erase counter header is all right and and
+ * a negative error code if not or if an error occurred.
*/
static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
{
@@ -1188,7 +1203,7 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum)
ubi_err("paranoid check failed for PEB %d", pnum);
ubi_dbg_dump_ec_hdr(ec_hdr);
ubi_dbg_dump_stack();
- err = 1;
+ err = -EINVAL;
goto exit;
}
@@ -1206,7 +1221,7 @@ exit:
* @vid_hdr: the volume identifier header to check
*
* This function returns zero if the volume identifier header is all right, and
- * %1 if not.
+ * %-EINVAL if not.
*/
static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum,
const struct ubi_vid_hdr *vid_hdr)
@@ -1233,7 +1248,7 @@ fail:
ubi_err("paranoid check failed for PEB %d", pnum);
ubi_dbg_dump_vid_hdr(vid_hdr);
ubi_dbg_dump_stack();
- return 1;
+ return -EINVAL;
}
@@ -1243,7 +1258,7 @@ fail:
* @pnum: the physical eraseblock number to check
*
* This function returns zero if the volume identifier header is all right,
- * %1 if not, and a negative error code if an error occurred.
+ * and a negative error code if not or if an error occurred.
*/
static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
{
@@ -1270,7 +1285,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum)
ubi_err("paranoid check failed for PEB %d", pnum);
ubi_dbg_dump_vid_hdr(vid_hdr);
ubi_dbg_dump_stack();
- err = 1;
+ err = -EINVAL;
goto exit;
}
@@ -1282,6 +1297,61 @@ exit:
}
/**
+ * ubi_dbg_check_write - make sure write succeeded.
+ * @ubi: UBI device description object
+ * @buf: buffer with data which were written
+ * @pnum: physical eraseblock number the data were written to
+ * @offset: offset within the physical eraseblock the data were written to
+ * @len: how many bytes were written
+ *
+ * This functions reads data which were recently written and compares it with
+ * the original data buffer - the data have to match. Returns zero if the data
+ * match and a negative error code if not or in case of failure.
+ */
+int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
+ int offset, int len)
+{
+ int err, i;
+
+ mutex_lock(&ubi->dbg_buf_mutex);
+ err = ubi_io_read(ubi, ubi->dbg_peb_buf, pnum, offset, len);
+ if (err)
+ goto out_unlock;
+
+ for (i = 0; i < len; i++) {
+ uint8_t c = ((uint8_t *)buf)[i];
+ uint8_t c1 = ((uint8_t *)ubi->dbg_peb_buf)[i];
+ int dump_len;
+
+ if (c == c1)
+ continue;
+
+ ubi_err("paranoid check failed for PEB %d:%d, len %d",
+ pnum, offset, len);
+ ubi_msg("data differ at position %d", i);
+ dump_len = max_t(int, 128, len - i);
+ ubi_msg("hex dump of the original buffer from %d to %d",
+ i, i + dump_len);
+ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
+ buf + i, dump_len, 1);
+ ubi_msg("hex dump of the read buffer from %d to %d",
+ i, i + dump_len);
+ print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
+ ubi->dbg_peb_buf + i, dump_len, 1);
+ ubi_dbg_dump_stack();
+ err = -EINVAL;
+ goto out_unlock;
+ }
+ mutex_unlock(&ubi->dbg_buf_mutex);
+
+ return 0;
+
+out_unlock:
+ mutex_unlock(&ubi->dbg_buf_mutex);
+ return err;
+}
+
+/**
* ubi_dbg_check_all_ff - check that a region of flash is empty.
* @ubi: UBI device description object
* @pnum: the physical eraseblock number to check
@@ -1289,8 +1359,8 @@ exit:
* @len: the length of the region to check
*
* This function returns zero if only 0xFF bytes are present at offset
- * @offset of the physical eraseblock @pnum, %1 if not, and a negative error
- * code if an error occurred.
+ * @offset of the physical eraseblock @pnum, and a negative error code if not
+ * or if an error occurred.
*/
int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
{
@@ -1321,7 +1391,7 @@ fail:
ubi_msg("hex dump of the %d-%d region", offset, offset + len);
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
ubi->dbg_peb_buf, len, 1);
- err = 1;
+ err = -EINVAL;
error:
ubi_dbg_dump_stack();
mutex_unlock(&ubi->dbg_buf_mutex);
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 90af61a2c3e..594184bbd56 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -974,11 +974,8 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi)
seb->ec = si->mean_ec;
err = paranoid_check_si(ubi, si);
- if (err) {
- if (err > 0)
- err = -EINVAL;
+ if (err)
goto out_vidh;
- }
ubi_free_vid_hdr(ubi, vidh);
kfree(ech);
@@ -1086,8 +1083,8 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si)
* @ubi: UBI device description object
* @si: scanning information
*
- * This function returns zero if the scanning information is all right, %1 if
- * not and a negative error code if an error occurred.
+ * This function returns zero if the scanning information is all right, and a
+ * negative error code if not or if an error occurred.
*/
static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si)
{
@@ -1346,7 +1343,7 @@ bad_vid_hdr:
out:
ubi_dbg_dump_stack();
- return 1;
+ return -EINVAL;
}
#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 600c7229d5c..f64ddabd4ac 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -464,7 +464,7 @@ retry:
ubi->peb_size - ubi->vid_hdr_aloffset);
if (err) {
ubi_err("new PEB %d does not contain all 0xFF bytes", e->pnum);
- return err > 0 ? -EINVAL : err;
+ return err;
}
return e->pnum;
@@ -513,7 +513,7 @@ static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
dbg_wl("erase PEB %d, old EC %llu", e->pnum, ec);
err = paranoid_check_ec(ubi, e->pnum, e->ec);
- if (err > 0)
+ if (err)
return -EINVAL;
ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
@@ -1572,8 +1572,7 @@ void ubi_wl_close(struct ubi_device *ubi)
* @ec: the erase counter to check
*
* This function returns zero if the erase counter of physical eraseblock @pnum
- * is equivalent to @ec, %1 if not, and a negative error code if an error
- * occurred.
+ * is equivalent to @ec, and a negative error code if not or if an error occurred.
*/
static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec)
{
@@ -1611,8 +1610,8 @@ out_free:
* @e: the wear-leveling entry to check
* @root: the root of the tree
*
- * This function returns zero if @e is in the @root RB-tree and %1 if it is
- * not.
+ * This function returns zero if @e is in the @root RB-tree and %-EINVAL if it
+ * is not.
*/
static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
struct rb_root *root)
@@ -1623,7 +1622,7 @@ static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
ubi_err("paranoid check failed for PEB %d, EC %d, RB-tree %p ",
e->pnum, e->ec, root);
ubi_dbg_dump_stack();
- return 1;
+ return -EINVAL;
}
/**
@@ -1632,7 +1631,7 @@ static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
* @ubi: UBI device description object
* @e: the wear-leveling entry to check
*
- * This function returns zero if @e is in @ubi->pq and %1 if it is not.
+ * This function returns zero if @e is in @ubi->pq and %-EINVAL if it is not.
*/
static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e)
{
@@ -1647,6 +1646,6 @@ static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e)
ubi_err("paranoid check failed for PEB %d, EC %d, Protect queue",
e->pnum, e->ec);
ubi_dbg_dump_stack();
- return 1;
+ return -EINVAL;
}
#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 5acd557cea9..b8bec086daa 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -51,7 +51,9 @@
* "show" function for the bond_masters attribute.
* The class parameter is ignored.
*/
-static ssize_t bonding_show_bonds(struct class *cls, char *buf)
+static ssize_t bonding_show_bonds(struct class *cls,
+ struct class_attribute *attr,
+ char *buf)
{
struct net *net = current->nsproxy->net_ns;
struct bond_net *bn = net_generic(net, bond_net_id);
@@ -98,6 +100,7 @@ static struct net_device *bond_get_by_name(struct net *net, const char *ifname)
*/
static ssize_t bonding_store_bonds(struct class *cls,
+ struct class_attribute *attr,
const char *buffer, size_t count)
{
struct net *net = current->nsproxy->net_ns;
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 6aa526ee909..61a7b4351e7 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -998,7 +998,7 @@ static int gfar_probe(struct of_device *ofdev,
}
/* Need to reverse the bit maps as bit_map's MSB is q0
- * but, for_each_bit parses from right to left, which
+ * but, for_each_set_bit parses from right to left, which
* basically reverses the queue numbers */
for (i = 0; i< priv->num_grps; i++) {
priv->gfargrp[i].tx_bit_map = reverse_bitmap(
@@ -1011,7 +1011,7 @@ static int gfar_probe(struct of_device *ofdev,
* also assign queues to groups */
for (grp_idx = 0; grp_idx < priv->num_grps; grp_idx++) {
priv->gfargrp[grp_idx].num_rx_queues = 0x0;
- for_each_bit(i, &priv->gfargrp[grp_idx].rx_bit_map,
+ for_each_set_bit(i, &priv->gfargrp[grp_idx].rx_bit_map,
priv->num_rx_queues) {
priv->gfargrp[grp_idx].num_rx_queues++;
priv->rx_queue[i]->grp = &priv->gfargrp[grp_idx];
@@ -1019,7 +1019,7 @@ static int gfar_probe(struct of_device *ofdev,
rqueue = rqueue | ((RQUEUE_EN0 | RQUEUE_EX0) >> i);
}
priv->gfargrp[grp_idx].num_tx_queues = 0x0;
- for_each_bit (i, &priv->gfargrp[grp_idx].tx_bit_map,
+ for_each_set_bit(i, &priv->gfargrp[grp_idx].tx_bit_map,
priv->num_tx_queues) {
priv->gfargrp[grp_idx].num_tx_queues++;
priv->tx_queue[i]->grp = &priv->gfargrp[grp_idx];
@@ -1709,7 +1709,7 @@ void gfar_configure_coalescing(struct gfar_private *priv,
if (priv->mode == MQ_MG_MODE) {
baddr = &regs->txic0;
- for_each_bit (i, &tx_mask, priv->num_tx_queues) {
+ for_each_set_bit(i, &tx_mask, priv->num_tx_queues) {
if (likely(priv->tx_queue[i]->txcoalescing)) {
gfar_write(baddr + i, 0);
gfar_write(baddr + i, priv->tx_queue[i]->txic);
@@ -1717,7 +1717,7 @@ void gfar_configure_coalescing(struct gfar_private *priv,
}
baddr = &regs->rxic0;
- for_each_bit (i, &rx_mask, priv->num_rx_queues) {
+ for_each_set_bit(i, &rx_mask, priv->num_rx_queues) {
if (likely(priv->rx_queue[i]->rxcoalescing)) {
gfar_write(baddr + i, 0);
gfar_write(baddr + i, priv->rx_queue[i]->rxic);
@@ -2607,7 +2607,7 @@ static int gfar_poll(struct napi_struct *napi, int budget)
budget_per_queue = left_over_budget/num_queues;
left_over_budget = 0;
- for_each_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) {
+ for_each_set_bit(i, &gfargrp->rx_bit_map, priv->num_rx_queues) {
if (test_bit(i, &serviced_queues))
continue;
rx_queue = priv->rx_queue[i];
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index f2b93796695..0bc777bac9b 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -1577,7 +1577,7 @@ static struct attribute * veth_pool_attrs[] = {
NULL,
};
-static struct sysfs_ops veth_pool_ops = {
+static const struct sysfs_ops veth_pool_ops = {
.show = veth_pool_show,
.store = veth_pool_store,
};
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index 966de5d6952..e6e972d9b7c 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -384,7 +384,7 @@ static struct attribute *veth_cnx_default_attrs[] = {
NULL
};
-static struct sysfs_ops veth_cnx_sysfs_ops = {
+static const struct sysfs_ops veth_cnx_sysfs_ops = {
.show = veth_cnx_attribute_show
};
@@ -441,7 +441,7 @@ static struct attribute *veth_port_default_attrs[] = {
NULL
};
-static struct sysfs_ops veth_port_sysfs_ops = {
+static const struct sysfs_ops veth_port_sysfs_ops = {
.show = veth_port_attribute_show
};
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 45e3532b166..684af371462 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -1050,7 +1050,7 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
*/
for (v_idx = 0; v_idx < q_vectors; v_idx++) {
q_vector = adapter->q_vector[v_idx];
- /* XXX for_each_bit(...) */
+ /* XXX for_each_set_bit(...) */
r_idx = find_first_bit(q_vector->rxr_idx,
adapter->num_rx_queues);
diff --git a/drivers/net/ixgbevf/ixgbevf_main.c b/drivers/net/ixgbevf/ixgbevf_main.c
index 235b5fd4b8d..ca653c49b76 100644
--- a/drivers/net/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ixgbevf/ixgbevf_main.c
@@ -751,7 +751,7 @@ static void ixgbevf_configure_msix(struct ixgbevf_adapter *adapter)
*/
for (v_idx = 0; v_idx < q_vectors; v_idx++) {
q_vector = adapter->q_vector[v_idx];
- /* XXX for_each_bit(...) */
+ /* XXX for_each_set_bit(...) */
r_idx = find_first_bit(q_vector->rxr_idx,
adapter->num_rx_queues);
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c
index 8a964f13036..a6452af9c6c 100644
--- a/drivers/net/wireless/ath/ar9170/main.c
+++ b/drivers/net/wireless/ath/ar9170/main.c
@@ -394,7 +394,7 @@ static void ar9170_tx_fake_ampdu_status(struct ar9170 *ar)
ieee80211_tx_status_irqsafe(ar->hw, skb);
}
- for_each_bit(i, &queue_bitmap, BITS_PER_BYTE) {
+ for_each_set_bit(i, &queue_bitmap, BITS_PER_BYTE) {
#ifdef AR9170_QUEUE_STOP_DEBUG
printk(KERN_DEBUG "%s: wake queue %d\n",
wiphy_name(ar->hw->wiphy), i);
diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c
index be992ca41cf..c29c994de0e 100644
--- a/drivers/net/wireless/iwmc3200wifi/debugfs.c
+++ b/drivers/net/wireless/iwmc3200wifi/debugfs.c
@@ -89,7 +89,7 @@ static int iwm_debugfs_dbg_modules_write(void *data, u64 val)
for (i = 0; i < __IWM_DM_NR; i++)
iwm->dbg.dbg_module[i] = 0;
- for_each_bit(bit, &iwm->dbg.dbg_modules, __IWM_DM_NR)
+ for_each_set_bit(bit, &iwm->dbg.dbg_modules, __IWM_DM_NR)
iwm->dbg.dbg_module[bit] = iwm->dbg.dbg_level;
return 0;
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c
index ad8f7eabb5a..8456b4dbd14 100644
--- a/drivers/net/wireless/iwmc3200wifi/rx.c
+++ b/drivers/net/wireless/iwmc3200wifi/rx.c
@@ -1116,7 +1116,7 @@ static int iwm_ntf_stop_resume_tx(struct iwm_priv *iwm, u8 *buf,
return -EINVAL;
}
- for_each_bit(bit, (unsigned long *)&tid_msk, IWM_UMAC_TID_NR) {
+ for_each_set_bit(bit, (unsigned long *)&tid_msk, IWM_UMAC_TID_NR) {
tid_info = &sta_info->tid_info[bit];
mutex_lock(&tid_info->mutex);
diff --git a/drivers/parisc/eisa_enumerator.c b/drivers/parisc/eisa_enumerator.c
index 0be1d50645a..caa15313375 100644
--- a/drivers/parisc/eisa_enumerator.c
+++ b/drivers/parisc/eisa_enumerator.c
@@ -460,7 +460,7 @@ static int init_slot(int slot, struct eeprom_eisa_slot_info *es)
slot, id_string);
print_eisa_id(id_string, es->eisa_slot_id);
- printk(" expected %s \n", id_string);
+ printk(" expected %s\n", id_string);
return -1;
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index 0bc5d474b16..1062b8ffe24 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -481,7 +481,7 @@ pdcspath_attr_store(struct kobject *kobj, struct attribute *attr,
return ret;
}
-static struct sysfs_ops pdcspath_attr_ops = {
+static const struct sysfs_ops pdcspath_attr_ops = {
.show = pdcspath_attr_show,
.store = pdcspath_attr_store,
};
diff --git a/drivers/parisc/superio.c b/drivers/parisc/superio.c
index a35c9c5b89e..f7806d81f1e 100644
--- a/drivers/parisc/superio.c
+++ b/drivers/parisc/superio.c
@@ -169,7 +169,7 @@ superio_init(struct pci_dev *pcidev)
/* ...then properly fixup the USB to point at suckyio PIC */
sio->usb_pdev->irq = superio_fixup_irq(sio->usb_pdev);
- printk(KERN_INFO PFX "Found NS87560 Legacy I/O device at %s (IRQ %i) \n",
+ printk(KERN_INFO PFX "Found NS87560 Legacy I/O device at %s (IRQ %i)\n",
pci_name(pdev), pdev->irq);
pci_read_config_dword (pdev, SIO_SP1BAR, &sio->sp1_base);
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 712250f5874..26301cb25e7 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -288,9 +288,9 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
next = dev->bus_list.next;
/* Run device routines with the device locked */
- down(&dev->dev.sem);
+ device_lock(&dev->dev);
retval = cb(dev, userdata);
- up(&dev->dev.sem);
+ device_unlock(&dev->dev);
if (retval)
break;
}
diff --git a/drivers/pci/hotplug/fakephp.c b/drivers/pci/hotplug/fakephp.c
index 6151389fd90..0a894efd4b9 100644
--- a/drivers/pci/hotplug/fakephp.c
+++ b/drivers/pci/hotplug/fakephp.c
@@ -73,7 +73,7 @@ static void legacy_release(struct kobject *kobj)
}
static struct kobj_type legacy_ktype = {
- .sysfs_ops = &(struct sysfs_ops){
+ .sysfs_ops = &(const struct sysfs_ops){
.store = legacy_store, .show = legacy_show
},
.release = &legacy_release,
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 807224ec835..de296452c95 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -642,6 +642,7 @@ void pci_create_legacy_files(struct pci_bus *b)
if (!b->legacy_io)
goto kzalloc_err;
+ sysfs_bin_attr_init(b->legacy_io);
b->legacy_io->attr.name = "legacy_io";
b->legacy_io->size = 0xffff;
b->legacy_io->attr.mode = S_IRUSR | S_IWUSR;
@@ -654,6 +655,7 @@ void pci_create_legacy_files(struct pci_bus *b)
goto legacy_io_err;
/* Allocated above after the legacy_io struct */
+ sysfs_bin_attr_init(b->legacy_mem);
b->legacy_mem = b->legacy_io + 1;
b->legacy_mem->attr.name = "legacy_mem";
b->legacy_mem->size = 1024*1024;
@@ -800,6 +802,7 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
if (res_attr) {
char *res_attr_name = (char *)(res_attr + 1);
+ sysfs_bin_attr_init(res_attr);
if (write_combine) {
pdev->res_attr_wc[num] = res_attr;
sprintf(res_attr_name, "resource%d_wc", num);
@@ -972,6 +975,7 @@ static int pci_create_capabilities_sysfs(struct pci_dev *dev)
if (!attr)
return -ENOMEM;
+ sysfs_bin_attr_init(attr);
attr->size = dev->vpd->len;
attr->attr.name = "vpd";
attr->attr.mode = S_IRUSR | S_IWUSR;
@@ -1038,6 +1042,7 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev)
retval = -ENOMEM;
goto err_resource_files;
}
+ sysfs_bin_attr_init(attr);
attr->size = rom_size;
attr->attr.name = "rom";
attr->attr.mode = S_IRUSR;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 6e100ae7f5b..fdcf01af676 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -303,6 +303,49 @@ int pci_find_ext_capability(struct pci_dev *dev, int cap)
}
EXPORT_SYMBOL_GPL(pci_find_ext_capability);
+/**
+ * pci_bus_find_ext_capability - find an extended capability
+ * @bus: the PCI bus to query
+ * @devfn: PCI device to query
+ * @cap: capability code
+ *
+ * Like pci_find_ext_capability() but works for pci devices that do not have a
+ * pci_dev structure set up yet.
+ *
+ * Returns the address of the requested capability structure within the
+ * device's PCI configuration space or 0 in case the device does not
+ * support it.
+ */
+int pci_bus_find_ext_capability(struct pci_bus *bus, unsigned int devfn,
+ int cap)
+{
+ u32 header;
+ int ttl;
+ int pos = PCI_CFG_SPACE_SIZE;
+
+ /* minimum 8 bytes per capability */
+ ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
+
+ if (!pci_bus_read_config_dword(bus, devfn, pos, &header))
+ return 0;
+ if (header == 0xffffffff || header == 0)
+ return 0;
+
+ while (ttl-- > 0) {
+ if (PCI_EXT_CAP_ID(header) == cap)
+ return pos;
+
+ pos = PCI_EXT_CAP_NEXT(header);
+ if (pos < PCI_CFG_SPACE_SIZE)
+ break;
+
+ if (!pci_bus_read_config_dword(bus, devfn, pos, &header))
+ break;
+ }
+
+ return 0;
+}
+
static int __pci_find_next_ht_cap(struct pci_dev *dev, int pos, int ht_cap)
{
int rc, ttl = PCI_FIND_CAP_TTL;
@@ -2445,7 +2488,7 @@ static int pci_dev_reset(struct pci_dev *dev, int probe)
if (!probe) {
pci_block_user_cfg_access(dev);
/* block PM suspend, driver probe, etc. */
- down(&dev->dev.sem);
+ device_lock(&dev->dev);
}
rc = pci_dev_specific_reset(dev, probe);
@@ -2467,7 +2510,7 @@ static int pci_dev_reset(struct pci_dev *dev, int probe)
rc = pci_parent_bus_reset(dev, probe);
done:
if (!probe) {
- up(&dev->dev.sem);
+ device_unlock(&dev->dev);
pci_unblock_user_cfg_access(dev);
}
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 039e87b7144..81d19d5683a 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -2533,6 +2533,91 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1518, quirk_i82576_sriov);
#endif /* CONFIG_PCI_IOV */
+/*
+ * This is a quirk for the Ricoh MMC controller found as a part of
+ * some mulifunction chips.
+
+ * This is very similiar and based on the ricoh_mmc driver written by
+ * Philip Langdale. Thank you for these magic sequences.
+ *
+ * These chips implement the four main memory card controllers (SD, MMC, MS, xD)
+ * and one or both of cardbus or firewire.
+ *
+ * It happens that they implement SD and MMC
+ * support as separate controllers (and PCI functions). The linux SDHCI
+ * driver supports MMC cards but the chip detects MMC cards in hardware
+ * and directs them to the MMC controller - so the SDHCI driver never sees
+ * them.
+ *
+ * To get around this, we must disable the useless MMC controller.
+ * At that point, the SDHCI controller will start seeing them
+ * It seems to be the case that the relevant PCI registers to deactivate the
+ * MMC controller live on PCI function 0, which might be the cardbus controller
+ * or the firewire controller, depending on the particular chip in question
+ *
+ * This has to be done early, because as soon as we disable the MMC controller
+ * other pci functions shift up one level, e.g. function #2 becomes function
+ * #1, and this will confuse the pci core.
+ */
+
+#ifdef CONFIG_MMC_RICOH_MMC
+static void ricoh_mmc_fixup_rl5c476(struct pci_dev *dev)
+{
+ /* disable via cardbus interface */
+ u8 write_enable;
+ u8 write_target;
+ u8 disable;
+
+ /* disable must be done via function #0 */
+ if (PCI_FUNC(dev->devfn))
+ return;
+
+ pci_read_config_byte(dev, 0xB7, &disable);
+ if (disable & 0x02)
+ return;
+
+ pci_read_config_byte(dev, 0x8E, &write_enable);
+ pci_write_config_byte(dev, 0x8E, 0xAA);
+ pci_read_config_byte(dev, 0x8D, &write_target);
+ pci_write_config_byte(dev, 0x8D, 0xB7);
+ pci_write_config_byte(dev, 0xB7, disable | 0x02);
+ pci_write_config_byte(dev, 0x8E, write_enable);
+ pci_write_config_byte(dev, 0x8D, write_target);
+
+ dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via cardbus function)\n");
+ dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n");
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, ricoh_mmc_fixup_rl5c476);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C476, ricoh_mmc_fixup_rl5c476);
+
+static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev)
+{
+ /* disable via firewire interface */
+ u8 write_enable;
+ u8 disable;
+
+ /* disable must be done via function #0 */
+ if (PCI_FUNC(dev->devfn))
+ return;
+
+ pci_read_config_byte(dev, 0xCB, &disable);
+
+ if (disable & 0x02)
+ return;
+
+ pci_read_config_byte(dev, 0xCA, &write_enable);
+ pci_write_config_byte(dev, 0xCA, 0x57);
+ pci_write_config_byte(dev, 0xCB, disable | 0x02);
+ pci_write_config_byte(dev, 0xCA, write_enable);
+
+ dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via firewire function)\n");
+ dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n");
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);
+#endif /*CONFIG_MMC_RICOH_MMC*/
+
+
static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
struct pci_fixup *end)
{
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
index 49c9e6c9779..f75a44d37fb 100644
--- a/drivers/pci/slot.c
+++ b/drivers/pci/slot.c
@@ -29,7 +29,7 @@ static ssize_t pci_slot_attr_store(struct kobject *kobj,
return attribute->store ? attribute->store(slot, buf, len) : -EIO;
}
-static struct sysfs_ops pci_slot_sysfs_ops = {
+static const struct sysfs_ops pci_slot_sysfs_ops = {
.show = pci_slot_attr_show,
.store = pci_slot_attr_store,
};
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 0f98be4450b..ad93ebd7b2a 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -971,9 +971,9 @@ static int runtime_suspend(struct device *dev)
{
int rc;
- down(&dev->sem);
+ device_lock(dev);
rc = pcmcia_dev_suspend(dev, PMSG_SUSPEND);
- up(&dev->sem);
+ device_unlock(dev);
return rc;
}
@@ -981,9 +981,9 @@ static int runtime_resume(struct device *dev)
{
int rc;
- down(&dev->sem);
+ device_lock(dev);
rc = pcmcia_dev_resume(dev);
- up(&dev->sem);
+ device_unlock(dev);
return rc;
}
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index cd2ee6fce1b..e631dbeafd7 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -150,6 +150,7 @@ config MSI_LAPTOP
tristate "MSI Laptop Extras"
depends on ACPI
depends on BACKLIGHT_CLASS_DEVICE
+ depends on RFKILL
---help---
This is a driver for laptops built by MSI (MICRO-STAR
INTERNATIONAL):
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index 3aa57da8b43..7ccf33c0896 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -57,7 +57,7 @@ enum hp_wmi_radio {
HPWMI_WWAN = 2,
};
-static int __init hp_wmi_bios_setup(struct platform_device *device);
+static int __devinit hp_wmi_bios_setup(struct platform_device *device);
static int __exit hp_wmi_bios_remove(struct platform_device *device);
static int hp_wmi_resume_handler(struct device *device);
@@ -447,7 +447,7 @@ static void cleanup_sysfs(struct platform_device *device)
device_remove_file(&device->dev, &dev_attr_tablet);
}
-static int __init hp_wmi_bios_setup(struct platform_device *device)
+static int __devinit hp_wmi_bios_setup(struct platform_device *device)
{
int err;
int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
diff --git a/drivers/platform/x86/msi-laptop.c b/drivers/platform/x86/msi-laptop.c
index 759763d18e4..c2b05da4289 100644
--- a/drivers/platform/x86/msi-laptop.c
+++ b/drivers/platform/x86/msi-laptop.c
@@ -58,6 +58,7 @@
#include <linux/dmi.h>
#include <linux/backlight.h>
#include <linux/platform_device.h>
+#include <linux/rfkill.h>
#define MSI_DRIVER_VERSION "0.5"
@@ -66,6 +67,20 @@
#define MSI_EC_COMMAND_WIRELESS 0x10
#define MSI_EC_COMMAND_LCD_LEVEL 0x11
+#define MSI_STANDARD_EC_COMMAND_ADDRESS 0x2e
+#define MSI_STANDARD_EC_BLUETOOTH_MASK (1 << 0)
+#define MSI_STANDARD_EC_WEBCAM_MASK (1 << 1)
+#define MSI_STANDARD_EC_WLAN_MASK (1 << 3)
+#define MSI_STANDARD_EC_3G_MASK (1 << 4)
+
+/* For set SCM load flag to disable BIOS fn key */
+#define MSI_STANDARD_EC_SCM_LOAD_ADDRESS 0x2d
+#define MSI_STANDARD_EC_SCM_LOAD_MASK (1 << 0)
+
+static int msi_laptop_resume(struct platform_device *device);
+
+#define MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS 0x2f
+
static int force;
module_param(force, bool, 0);
MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
@@ -74,6 +89,23 @@ static int auto_brightness;
module_param(auto_brightness, int, 0);
MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disabled; 1: enabled; 2: don't touch)");
+static bool old_ec_model;
+static int wlan_s, bluetooth_s, threeg_s;
+static int threeg_exists;
+
+/* Some MSI 3G netbook only have one fn key to control Wlan/Bluetooth/3G,
+ * those netbook will load the SCM (windows app) to disable the original
+ * Wlan/Bluetooth control by BIOS when user press fn key, then control
+ * Wlan/Bluetooth/3G by SCM (software control by OS). Without SCM, user
+ * cann't on/off 3G module on those 3G netbook.
+ * On Linux, msi-laptop driver will do the same thing to disable the
+ * original BIOS control, then might need use HAL or other userland
+ * application to do the software control that simulate with SCM.
+ * e.g. MSI N034 netbook
+ */
+static bool load_scm_model;
+static struct rfkill *rfk_wlan, *rfk_bluetooth, *rfk_threeg;
+
/* Hardware access */
static int set_lcd_level(int level)
@@ -130,6 +162,35 @@ static int set_auto_brightness(int enable)
return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 2, NULL, 0, 1);
}
+static ssize_t set_device_state(const char *buf, size_t count, u8 mask)
+{
+ int status;
+ u8 wdata = 0, rdata;
+ int result;
+
+ if (sscanf(buf, "%i", &status) != 1 || (status < 0 || status > 1))
+ return -EINVAL;
+
+ /* read current device state */
+ result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata);
+ if (result < 0)
+ return -EINVAL;
+
+ if (!!(rdata & mask) != status) {
+ /* reverse device bit */
+ if (rdata & mask)
+ wdata = rdata & ~mask;
+ else
+ wdata = rdata | mask;
+
+ result = ec_write(MSI_STANDARD_EC_COMMAND_ADDRESS, wdata);
+ if (result < 0)
+ return -EINVAL;
+ }
+
+ return count;
+}
+
static int get_wireless_state(int *wlan, int *bluetooth)
{
u8 wdata = 0, rdata;
@@ -148,6 +209,38 @@ static int get_wireless_state(int *wlan, int *bluetooth)
return 0;
}
+static int get_wireless_state_ec_standard(void)
+{
+ u8 rdata;
+ int result;
+
+ result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata);
+ if (result < 0)
+ return -1;
+
+ wlan_s = !!(rdata & MSI_STANDARD_EC_WLAN_MASK);
+
+ bluetooth_s = !!(rdata & MSI_STANDARD_EC_BLUETOOTH_MASK);
+
+ threeg_s = !!(rdata & MSI_STANDARD_EC_3G_MASK);
+
+ return 0;
+}
+
+static int get_threeg_exists(void)
+{
+ u8 rdata;
+ int result;
+
+ result = ec_read(MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS, &rdata);
+ if (result < 0)
+ return -1;
+
+ threeg_exists = !!(rdata & MSI_STANDARD_EC_3G_MASK);
+
+ return 0;
+}
+
/* Backlight device stuff */
static int bl_get_brightness(struct backlight_device *b)
@@ -176,26 +269,71 @@ static ssize_t show_wlan(struct device *dev,
int ret, enabled;
- ret = get_wireless_state(&enabled, NULL);
+ if (old_ec_model) {
+ ret = get_wireless_state(&enabled, NULL);
+ } else {
+ ret = get_wireless_state_ec_standard();
+ enabled = wlan_s;
+ }
if (ret < 0)
return ret;
return sprintf(buf, "%i\n", enabled);
}
+static ssize_t store_wlan(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ return set_device_state(buf, count, MSI_STANDARD_EC_WLAN_MASK);
+}
+
static ssize_t show_bluetooth(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret, enabled;
- ret = get_wireless_state(NULL, &enabled);
+ if (old_ec_model) {
+ ret = get_wireless_state(NULL, &enabled);
+ } else {
+ ret = get_wireless_state_ec_standard();
+ enabled = bluetooth_s;
+ }
if (ret < 0)
return ret;
return sprintf(buf, "%i\n", enabled);
}
+static ssize_t store_bluetooth(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ return set_device_state(buf, count, MSI_STANDARD_EC_BLUETOOTH_MASK);
+}
+
+static ssize_t show_threeg(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+
+ int ret;
+
+ /* old msi ec not support 3G */
+ if (old_ec_model)
+ return -1;
+
+ ret = get_wireless_state_ec_standard();
+ if (ret < 0)
+ return ret;
+
+ return sprintf(buf, "%i\n", threeg_s);
+}
+
+static ssize_t store_threeg(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ return set_device_state(buf, count, MSI_STANDARD_EC_3G_MASK);
+}
+
static ssize_t show_lcd_level(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -258,6 +396,7 @@ static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level);
static DEVICE_ATTR(auto_brightness, 0644, show_auto_brightness, store_auto_brightness);
static DEVICE_ATTR(bluetooth, 0444, show_bluetooth, NULL);
static DEVICE_ATTR(wlan, 0444, show_wlan, NULL);
+static DEVICE_ATTR(threeg, 0444, show_threeg, NULL);
static struct attribute *msipf_attributes[] = {
&dev_attr_lcd_level.attr,
@@ -275,7 +414,8 @@ static struct platform_driver msipf_driver = {
.driver = {
.name = "msi-laptop-pf",
.owner = THIS_MODULE,
- }
+ },
+ .resume = msi_laptop_resume,
};
static struct platform_device *msipf_device;
@@ -332,6 +472,192 @@ static struct dmi_system_id __initdata msi_dmi_table[] = {
{ }
};
+static struct dmi_system_id __initdata msi_load_scm_models_dmi_table[] = {
+ {
+ .ident = "MSI N034",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR,
+ "MICRO-STAR INTERNATIONAL CO., LTD"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MS-N034"),
+ DMI_MATCH(DMI_CHASSIS_VENDOR,
+ "MICRO-STAR INTERNATIONAL CO., LTD")
+ },
+ .callback = dmi_check_cb
+ },
+ { }
+};
+
+static int rfkill_bluetooth_set(void *data, bool blocked)
+{
+ /* Do something with blocked...*/
+ /*
+ * blocked == false is on
+ * blocked == true is off
+ */
+ if (blocked)
+ set_device_state("0", 0, MSI_STANDARD_EC_BLUETOOTH_MASK);
+ else
+ set_device_state("1", 0, MSI_STANDARD_EC_BLUETOOTH_MASK);
+
+ return 0;
+}
+
+static int rfkill_wlan_set(void *data, bool blocked)
+{
+ if (blocked)
+ set_device_state("0", 0, MSI_STANDARD_EC_WLAN_MASK);
+ else
+ set_device_state("1", 0, MSI_STANDARD_EC_WLAN_MASK);
+
+ return 0;
+}
+
+static int rfkill_threeg_set(void *data, bool blocked)
+{
+ if (blocked)
+ set_device_state("0", 0, MSI_STANDARD_EC_3G_MASK);
+ else
+ set_device_state("1", 0, MSI_STANDARD_EC_3G_MASK);
+
+ return 0;
+}
+
+static struct rfkill_ops rfkill_bluetooth_ops = {
+ .set_block = rfkill_bluetooth_set
+};
+
+static struct rfkill_ops rfkill_wlan_ops = {
+ .set_block = rfkill_wlan_set
+};
+
+static struct rfkill_ops rfkill_threeg_ops = {
+ .set_block = rfkill_threeg_set
+};
+
+static void rfkill_cleanup(void)
+{
+ if (rfk_bluetooth) {
+ rfkill_unregister(rfk_bluetooth);
+ rfkill_destroy(rfk_bluetooth);
+ }
+
+ if (rfk_threeg) {
+ rfkill_unregister(rfk_threeg);
+ rfkill_destroy(rfk_threeg);
+ }
+
+ if (rfk_wlan) {
+ rfkill_unregister(rfk_wlan);
+ rfkill_destroy(rfk_wlan);
+ }
+}
+
+static int rfkill_init(struct platform_device *sdev)
+{
+ /* add rfkill */
+ int retval;
+
+ rfk_bluetooth = rfkill_alloc("msi-bluetooth", &sdev->dev,
+ RFKILL_TYPE_BLUETOOTH,
+ &rfkill_bluetooth_ops, NULL);
+ if (!rfk_bluetooth) {
+ retval = -ENOMEM;
+ goto err_bluetooth;
+ }
+ retval = rfkill_register(rfk_bluetooth);
+ if (retval)
+ goto err_bluetooth;
+
+ rfk_wlan = rfkill_alloc("msi-wlan", &sdev->dev, RFKILL_TYPE_WLAN,
+ &rfkill_wlan_ops, NULL);
+ if (!rfk_wlan) {
+ retval = -ENOMEM;
+ goto err_wlan;
+ }
+ retval = rfkill_register(rfk_wlan);
+ if (retval)
+ goto err_wlan;
+
+ if (threeg_exists) {
+ rfk_threeg = rfkill_alloc("msi-threeg", &sdev->dev,
+ RFKILL_TYPE_WWAN, &rfkill_threeg_ops, NULL);
+ if (!rfk_threeg) {
+ retval = -ENOMEM;
+ goto err_threeg;
+ }
+ retval = rfkill_register(rfk_threeg);
+ if (retval)
+ goto err_threeg;
+ }
+
+ return 0;
+
+err_threeg:
+ rfkill_destroy(rfk_threeg);
+ if (rfk_wlan)
+ rfkill_unregister(rfk_wlan);
+err_wlan:
+ rfkill_destroy(rfk_wlan);
+ if (rfk_bluetooth)
+ rfkill_unregister(rfk_bluetooth);
+err_bluetooth:
+ rfkill_destroy(rfk_bluetooth);
+
+ return retval;
+}
+
+static int msi_laptop_resume(struct platform_device *device)
+{
+ u8 data;
+ int result;
+
+ if (!load_scm_model)
+ return 0;
+
+ /* set load SCM to disable hardware control by fn key */
+ result = ec_read(MSI_STANDARD_EC_SCM_LOAD_ADDRESS, &data);
+ if (result < 0)
+ return result;
+
+ result = ec_write(MSI_STANDARD_EC_SCM_LOAD_ADDRESS,
+ data | MSI_STANDARD_EC_SCM_LOAD_MASK);
+ if (result < 0)
+ return result;
+
+ return 0;
+}
+
+static int load_scm_model_init(struct platform_device *sdev)
+{
+ u8 data;
+ int result;
+
+ /* allow userland write sysfs file */
+ dev_attr_bluetooth.store = store_bluetooth;
+ dev_attr_wlan.store = store_wlan;
+ dev_attr_threeg.store = store_threeg;
+ dev_attr_bluetooth.attr.mode |= S_IWUSR;
+ dev_attr_wlan.attr.mode |= S_IWUSR;
+ dev_attr_threeg.attr.mode |= S_IWUSR;
+
+ /* disable hardware control by fn key */
+ result = ec_read(MSI_STANDARD_EC_SCM_LOAD_ADDRESS, &data);
+ if (result < 0)
+ return result;
+
+ result = ec_write(MSI_STANDARD_EC_SCM_LOAD_ADDRESS,
+ data | MSI_STANDARD_EC_SCM_LOAD_MASK);
+ if (result < 0)
+ return result;
+
+ /* initial rfkill */
+ result = rfkill_init(sdev);
+ if (result < 0)
+ return result;
+
+ return 0;
+}
+
static int __init msi_init(void)
{
int ret;
@@ -339,8 +665,14 @@ static int __init msi_init(void)
if (acpi_disabled)
return -ENODEV;
- if (!force && !dmi_check_system(msi_dmi_table))
- return -ENODEV;
+ if (force || dmi_check_system(msi_dmi_table))
+ old_ec_model = 1;
+
+ if (!old_ec_model)
+ get_threeg_exists();
+
+ if (!old_ec_model && dmi_check_system(msi_load_scm_models_dmi_table))
+ load_scm_model = 1;
if (auto_brightness < 0 || auto_brightness > 2)
return -EINVAL;
@@ -374,10 +706,23 @@ static int __init msi_init(void)
if (ret)
goto fail_platform_device1;
+ if (load_scm_model && (load_scm_model_init(msipf_device) < 0)) {
+ ret = -EINVAL;
+ goto fail_platform_device1;
+ }
+
ret = sysfs_create_group(&msipf_device->dev.kobj, &msipf_attribute_group);
if (ret)
goto fail_platform_device2;
+ if (!old_ec_model) {
+ if (threeg_exists)
+ ret = device_create_file(&msipf_device->dev,
+ &dev_attr_threeg);
+ if (ret)
+ goto fail_platform_device2;
+ }
+
/* Disable automatic brightness control by default because
* this module was probably loaded to do brightness control in
* software. */
@@ -412,10 +757,14 @@ static void __exit msi_cleanup(void)
{
sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group);
+ if (!old_ec_model && threeg_exists)
+ device_remove_file(&msipf_device->dev, &dev_attr_threeg);
platform_device_unregister(msipf_device);
platform_driver_unregister(&msipf_driver);
backlight_device_unregister(msibl_device);
+ rfkill_cleanup();
+
/* Enable automatic brightness control again */
if (auto_brightness != 2)
set_auto_brightness(1);
@@ -435,3 +784,4 @@ MODULE_ALIAS("dmi:*:svnMICRO-STARINT'LCO.,LTD:pnMS-1013:pvr0131*:cvnMICRO-STARIN
MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1058:pvr0581:rvnMSI:rnMS-1058:*:ct10:*");
MODULE_ALIAS("dmi:*:svnMicro-StarInternational:pnMS-1412:*:rvnMSI:rnMS-1412:*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");
MODULE_ALIAS("dmi:*:svnNOTEBOOK:pnSAM2000:pvr0131*:cvnMICRO-STARINT'LCO.,LTD:ct10:*");
+MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-N034:*");
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index bf146721395..faaa9b4d0d0 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -29,6 +29,13 @@ config APM_POWER
Say Y here to enable support APM status emulation using
battery class devices.
+config MAX8925_POWER
+ tristate "MAX8925 battery charger support"
+ depends on MFD_MAX8925
+ help
+ Say Y here to enable support for the battery charger in the Maxim
+ MAX8925 PMIC.
+
config WM831X_BACKUP
tristate "WM831X backup battery charger support"
depends on MFD_WM831X
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 573597c683b..a2ba7c85c97 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_POWER_SUPPLY) += power_supply.o
obj-$(CONFIG_PDA_POWER) += pda_power.o
obj-$(CONFIG_APM_POWER) += apm_power.o
+obj-$(CONFIG_MAX8925_POWER) += max8925_power.o
obj-$(CONFIG_WM831X_BACKUP) += wm831x_backup.o
obj-$(CONFIG_WM831X_POWER) += wm831x_power.o
obj-$(CONFIG_WM8350_POWER) += wm8350_power.o
diff --git a/drivers/power/max8925_power.c b/drivers/power/max8925_power.c
new file mode 100644
index 00000000000..a1b4410544d
--- /dev/null
+++ b/drivers/power/max8925_power.c
@@ -0,0 +1,534 @@
+/*
+ * Battery driver for Maxim MAX8925
+ *
+ * Copyright (c) 2009-2010 Marvell International Ltd.
+ * Haojian Zhuang <haojian.zhuang@marvell.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/err.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/mfd/max8925.h>
+
+/* registers in GPM */
+#define MAX8925_OUT5VEN 0x54
+#define MAX8925_OUT3VEN 0x58
+#define MAX8925_CHG_CNTL1 0x7c
+
+/* bits definition */
+#define MAX8925_CHG_STAT_VSYSLOW (1 << 0)
+#define MAX8925_CHG_STAT_MODE_MASK (3 << 2)
+#define MAX8925_CHG_STAT_EN_MASK (1 << 4)
+#define MAX8925_CHG_MBDET (1 << 1)
+#define MAX8925_CHG_AC_RANGE_MASK (3 << 6)
+
+/* registers in ADC */
+#define MAX8925_ADC_RES_CNFG1 0x06
+#define MAX8925_ADC_AVG_CNFG1 0x07
+#define MAX8925_ADC_ACQ_CNFG1 0x08
+#define MAX8925_ADC_ACQ_CNFG2 0x09
+/* 2 bytes registers in below. MSB is 1st, LSB is 2nd. */
+#define MAX8925_ADC_AUX2 0x62
+#define MAX8925_ADC_VCHG 0x64
+#define MAX8925_ADC_VBBATT 0x66
+#define MAX8925_ADC_VMBATT 0x68
+#define MAX8925_ADC_ISNS 0x6a
+#define MAX8925_ADC_THM 0x6c
+#define MAX8925_ADC_TDIE 0x6e
+#define MAX8925_CMD_AUX2 0xc8
+#define MAX8925_CMD_VCHG 0xd0
+#define MAX8925_CMD_VBBATT 0xd8
+#define MAX8925_CMD_VMBATT 0xe0
+#define MAX8925_CMD_ISNS 0xe8
+#define MAX8925_CMD_THM 0xf0
+#define MAX8925_CMD_TDIE 0xf8
+
+enum {
+ MEASURE_AUX2,
+ MEASURE_VCHG,
+ MEASURE_VBBATT,
+ MEASURE_VMBATT,
+ MEASURE_ISNS,
+ MEASURE_THM,
+ MEASURE_TDIE,
+ MEASURE_MAX,
+};
+
+struct max8925_power_info {
+ struct max8925_chip *chip;
+ struct i2c_client *gpm;
+ struct i2c_client *adc;
+
+ struct power_supply ac;
+ struct power_supply usb;
+ struct power_supply battery;
+ int irq_base;
+ unsigned ac_online:1;
+ unsigned usb_online:1;
+ unsigned bat_online:1;
+ unsigned chg_mode:2;
+ unsigned batt_detect:1; /* detecing MB by ID pin */
+ unsigned topoff_threshold:2;
+ unsigned fast_charge:3;
+
+ int (*set_charger) (int);
+};
+
+static int __set_charger(struct max8925_power_info *info, int enable)
+{
+ struct max8925_chip *chip = info->chip;
+ if (enable) {
+ /* enable charger in platform */
+ if (info->set_charger)
+ info->set_charger(1);
+ /* enable charger */
+ max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 0);
+ } else {
+ /* disable charge */
+ max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 1 << 7);
+ if (info->set_charger)
+ info->set_charger(0);
+ }
+ dev_dbg(chip->dev, "%s\n", (enable) ? "Enable charger"
+ : "Disable charger");
+ return 0;
+}
+
+static irqreturn_t max8925_charger_handler(int irq, void *data)
+{
+ struct max8925_power_info *info = (struct max8925_power_info *)data;
+ struct max8925_chip *chip = info->chip;
+
+ switch (irq - chip->irq_base) {
+ case MAX8925_IRQ_VCHG_DC_R:
+ info->ac_online = 1;
+ __set_charger(info, 1);
+ dev_dbg(chip->dev, "Adapter inserted\n");
+ break;
+ case MAX8925_IRQ_VCHG_DC_F:
+ info->ac_online = 0;
+ __set_charger(info, 0);
+ dev_dbg(chip->dev, "Adapter is removal\n");
+ break;
+ case MAX8925_IRQ_VCHG_USB_R:
+ info->usb_online = 1;
+ __set_charger(info, 1);
+ dev_dbg(chip->dev, "USB inserted\n");
+ break;
+ case MAX8925_IRQ_VCHG_USB_F:
+ info->usb_online = 0;
+ __set_charger(info, 0);
+ dev_dbg(chip->dev, "USB is removal\n");
+ break;
+ case MAX8925_IRQ_VCHG_THM_OK_F:
+ /* Battery is not ready yet */
+ dev_dbg(chip->dev, "Battery temperature is out of range\n");
+ case MAX8925_IRQ_VCHG_DC_OVP:
+ dev_dbg(chip->dev, "Error detection\n");
+ __set_charger(info, 0);
+ break;
+ case MAX8925_IRQ_VCHG_THM_OK_R:
+ /* Battery is ready now */
+ dev_dbg(chip->dev, "Battery temperature is in range\n");
+ break;
+ case MAX8925_IRQ_VCHG_SYSLOW_R:
+ /* VSYS is low */
+ dev_info(chip->dev, "Sys power is too low\n");
+ break;
+ case MAX8925_IRQ_VCHG_SYSLOW_F:
+ dev_dbg(chip->dev, "Sys power is above low threshold\n");
+ break;
+ case MAX8925_IRQ_VCHG_DONE:
+ __set_charger(info, 0);
+ dev_dbg(chip->dev, "Charging is done\n");
+ break;
+ case MAX8925_IRQ_VCHG_TOPOFF:
+ dev_dbg(chip->dev, "Charging in top-off mode\n");
+ break;
+ case MAX8925_IRQ_VCHG_TMR_FAULT:
+ __set_charger(info, 0);
+ dev_dbg(chip->dev, "Safe timer is expired\n");
+ break;
+ case MAX8925_IRQ_VCHG_RST:
+ __set_charger(info, 0);
+ dev_dbg(chip->dev, "Charger is reset\n");
+ break;
+ }
+ return IRQ_HANDLED;
+}
+
+static int start_measure(struct max8925_power_info *info, int type)
+{
+ unsigned char buf[2] = {0, 0};
+ int meas_reg = 0, ret;
+
+ switch (type) {
+ case MEASURE_VCHG:
+ meas_reg = MAX8925_ADC_VCHG;
+ break;
+ case MEASURE_VBBATT:
+ meas_reg = MAX8925_ADC_VBBATT;
+ break;
+ case MEASURE_VMBATT:
+ meas_reg = MAX8925_ADC_VMBATT;
+ break;
+ case MEASURE_ISNS:
+ meas_reg = MAX8925_ADC_ISNS;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ max8925_bulk_read(info->adc, meas_reg, 2, buf);
+ ret = (buf[0] << 4) | (buf[1] >> 4);
+
+ return ret;
+}
+
+static int max8925_ac_get_prop(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
+ int ret = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = info->ac_online;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ if (info->ac_online) {
+ ret = start_measure(info, MEASURE_VCHG);
+ if (ret >= 0) {
+ val->intval = ret << 1; /* unit is mV */
+ goto out;
+ }
+ }
+ ret = -ENODATA;
+ break;
+ default:
+ ret = -ENODEV;
+ break;
+ }
+out:
+ return ret;
+}
+
+static enum power_supply_property max8925_ac_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+};
+
+static int max8925_usb_get_prop(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
+ int ret = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = info->usb_online;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ if (info->usb_online) {
+ ret = start_measure(info, MEASURE_VCHG);
+ if (ret >= 0) {
+ val->intval = ret << 1; /* unit is mV */
+ goto out;
+ }
+ }
+ ret = -ENODATA;
+ break;
+ default:
+ ret = -ENODEV;
+ break;
+ }
+out:
+ return ret;
+}
+
+static enum power_supply_property max8925_usb_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+};
+
+static int max8925_bat_get_prop(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
+ long long int tmp = 0;
+ int ret = 0;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval = info->bat_online;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ if (info->bat_online) {
+ ret = start_measure(info, MEASURE_VMBATT);
+ if (ret >= 0) {
+ val->intval = ret << 1; /* unit is mV */
+ ret = 0;
+ break;
+ }
+ }
+ ret = -ENODATA;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ if (info->bat_online) {
+ ret = start_measure(info, MEASURE_ISNS);
+ if (ret >= 0) {
+ tmp = (long long int)ret * 6250 / 4096 - 3125;
+ ret = (int)tmp;
+ val->intval = 0;
+ if (ret > 0)
+ val->intval = ret; /* unit is mA */
+ ret = 0;
+ break;
+ }
+ }
+ ret = -ENODATA;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_TYPE:
+ if (!info->bat_online) {
+ ret = -ENODATA;
+ break;
+ }
+ ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS);
+ ret = (ret & MAX8925_CHG_STAT_MODE_MASK) >> 2;
+ switch (ret) {
+ case 1:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
+ break;
+ case 0:
+ case 2:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+ break;
+ case 3:
+ val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
+ break;
+ }
+ ret = 0;
+ break;
+ case POWER_SUPPLY_PROP_STATUS:
+ if (!info->bat_online) {
+ ret = -ENODATA;
+ break;
+ }
+ ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS);
+ if (info->usb_online || info->ac_online) {
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ if (ret & MAX8925_CHG_STAT_EN_MASK)
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ } else
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ ret = 0;
+ break;
+ default:
+ ret = -ENODEV;
+ break;
+ }
+ return ret;
+}
+
+static enum power_supply_property max8925_battery_props[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CHARGE_TYPE,
+ POWER_SUPPLY_PROP_STATUS,
+};
+
+#define REQUEST_IRQ(_irq, _name) \
+do { \
+ ret = request_threaded_irq(chip->irq_base + _irq, NULL, \
+ max8925_charger_handler, \
+ IRQF_ONESHOT, _name, info); \
+ if (ret) \
+ dev_err(chip->dev, "Failed to request IRQ #%d: %d\n", \
+ _irq, ret); \
+} while (0)
+
+static __devinit int max8925_init_charger(struct max8925_chip *chip,
+ struct max8925_power_info *info)
+{
+ int ret;
+
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_OVP, "ac-ovp");
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_F, "ac-remove");
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_R, "ac-insert");
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_OVP, "usb-ovp");
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_F, "usb-remove");
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_R, "usb-insert");
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_R, "batt-temp-in-range");
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_F, "batt-temp-out-range");
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_F, "vsys-high");
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_R, "vsys-low");
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_RST, "charger-reset");
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_DONE, "charger-done");
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_TOPOFF, "charger-topoff");
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_TMR_FAULT, "charger-timer-expire");
+
+ info->ac_online = 0;
+ info->usb_online = 0;
+ info->bat_online = 0;
+ ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS);
+ if (ret >= 0) {
+ /*
+ * If battery detection is enabled, ID pin of battery is
+ * connected to MBDET pin of MAX8925. It could be used to
+ * detect battery presence.
+ * Otherwise, we have to assume that battery is always on.
+ */
+ if (info->batt_detect)
+ info->bat_online = (ret & MAX8925_CHG_MBDET) ? 0 : 1;
+ else
+ info->bat_online = 1;
+ if (ret & MAX8925_CHG_AC_RANGE_MASK)
+ info->ac_online = 1;
+ else
+ info->ac_online = 0;
+ }
+ /* disable charge */
+ max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 1 << 7, 1 << 7);
+ /* set charging current in charge topoff mode */
+ max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 3 << 5,
+ info->topoff_threshold << 5);
+ /* set charing current in fast charge mode */
+ max8925_set_bits(info->gpm, MAX8925_CHG_CNTL1, 7, info->fast_charge);
+
+ return 0;
+}
+
+static __devexit int max8925_deinit_charger(struct max8925_power_info *info)
+{
+ struct max8925_chip *chip = info->chip;
+ int irq;
+
+ irq = chip->irq_base + MAX8925_IRQ_VCHG_DC_OVP;
+ for (; irq <= chip->irq_base + MAX8925_IRQ_VCHG_TMR_FAULT; irq++)
+ free_irq(irq, info);
+
+ return 0;
+}
+
+static __devinit int max8925_power_probe(struct platform_device *pdev)
+{
+ struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ struct max8925_platform_data *max8925_pdata;
+ struct max8925_power_pdata *pdata = NULL;
+ struct max8925_power_info *info;
+ int ret;
+
+ if (pdev->dev.parent->platform_data) {
+ max8925_pdata = pdev->dev.parent->platform_data;
+ pdata = max8925_pdata->power;
+ }
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "platform data isn't assigned to "
+ "power supply\n");
+ return -EINVAL;
+ }
+
+ info = kzalloc(sizeof(struct max8925_power_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+ info->chip = chip;
+ info->gpm = chip->i2c;
+ info->adc = chip->adc;
+
+ info->ac.name = "max8925-ac";
+ info->ac.type = POWER_SUPPLY_TYPE_MAINS;
+ info->ac.properties = max8925_ac_props;
+ info->ac.num_properties = ARRAY_SIZE(max8925_ac_props);
+ info->ac.get_property = max8925_ac_get_prop;
+ ret = power_supply_register(&pdev->dev, &info->ac);
+ if (ret)
+ goto out;
+ info->ac.dev->parent = &pdev->dev;
+
+ info->usb.name = "max8925-usb";
+ info->usb.type = POWER_SUPPLY_TYPE_USB;
+ info->usb.properties = max8925_usb_props;
+ info->usb.num_properties = ARRAY_SIZE(max8925_usb_props);
+ info->usb.get_property = max8925_usb_get_prop;
+ ret = power_supply_register(&pdev->dev, &info->usb);
+ if (ret)
+ goto out_usb;
+ info->usb.dev->parent = &pdev->dev;
+
+ info->battery.name = "max8925-battery";
+ info->battery.type = POWER_SUPPLY_TYPE_BATTERY;
+ info->battery.properties = max8925_battery_props;
+ info->battery.num_properties = ARRAY_SIZE(max8925_battery_props);
+ info->battery.get_property = max8925_bat_get_prop;
+ ret = power_supply_register(&pdev->dev, &info->battery);
+ if (ret)
+ goto out_battery;
+ info->battery.dev->parent = &pdev->dev;
+
+ info->batt_detect = pdata->batt_detect;
+ info->topoff_threshold = pdata->topoff_threshold;
+ info->fast_charge = pdata->fast_charge;
+ info->set_charger = pdata->set_charger;
+ dev_set_drvdata(&pdev->dev, info);
+ platform_set_drvdata(pdev, info);
+
+ max8925_init_charger(chip, info);
+ return 0;
+out_battery:
+ power_supply_unregister(&info->battery);
+out_usb:
+ power_supply_unregister(&info->ac);
+out:
+ kfree(info);
+ return ret;
+}
+
+static __devexit int max8925_power_remove(struct platform_device *pdev)
+{
+ struct max8925_power_info *info = platform_get_drvdata(pdev);
+
+ if (info) {
+ power_supply_unregister(&info->ac);
+ power_supply_unregister(&info->usb);
+ power_supply_unregister(&info->battery);
+ max8925_deinit_charger(info);
+ kfree(info);
+ }
+ return 0;
+}
+
+static struct platform_driver max8925_power_driver = {
+ .probe = max8925_power_probe,
+ .remove = __devexit_p(max8925_power_remove),
+ .driver = {
+ .name = "max8925-power",
+ },
+};
+
+static int __init max8925_power_init(void)
+{
+ return platform_driver_register(&max8925_power_driver);
+}
+module_init(max8925_power_init);
+
+static void __exit max8925_power_exit(void)
+{
+ platform_driver_unregister(&max8925_power_driver);
+}
+module_exit(max8925_power_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Power supply driver for MAX8925");
+MODULE_ALIAS("platform:max8925-power");
diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c
index ad4f071e128..0693902d615 100644
--- a/drivers/power/wm8350_power.c
+++ b/drivers/power/wm8350_power.c
@@ -190,7 +190,7 @@ static irqreturn_t wm8350_charger_handler(int irq, void *data)
struct wm8350_power *power = &wm8350->power;
struct wm8350_charger_policy *policy = power->policy;
- switch (irq) {
+ switch (irq - wm8350->irq_base) {
case WM8350_IRQ_CHG_BAT_FAIL:
dev_err(wm8350->dev, "battery failed\n");
break;
@@ -428,18 +428,18 @@ static void wm8350_init_charger(struct wm8350 *wm8350)
static void free_charger_irq(struct wm8350 *wm8350)
{
- wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT);
- wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD);
- wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL);
- wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO);
- wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END);
- wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START);
- wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9);
- wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1);
- wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85);
- wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB);
- wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB);
- wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT, wm8350);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD, wm8350);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL, wm8350);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO, wm8350);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END, wm8350);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START, wm8350);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9, wm8350);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1, wm8350);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85, wm8350);
+ wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB, wm8350);
+ wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB, wm8350);
+ wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB, wm8350);
}
static __devinit int wm8350_power_probe(struct platform_device *pdev)
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
index 04719551381..5fb83e2ced2 100644
--- a/drivers/regulator/88pm8607.c
+++ b/drivers/regulator/88pm8607.c
@@ -11,15 +11,17 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/err.h>
+#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
-#include <linux/mfd/88pm8607.h>
+#include <linux/mfd/88pm860x.h>
struct pm8607_regulator_info {
struct regulator_desc desc;
- struct pm8607_chip *chip;
+ struct pm860x_chip *chip;
struct regulator_dev *regulator;
+ struct i2c_client *i2c;
int min_uV;
int max_uV;
@@ -46,7 +48,6 @@ static inline int check_range(struct pm8607_regulator_info *info,
static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index)
{
struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
- uint8_t chip_id = info->chip->chip_id;
int ret = -EINVAL;
switch (info->desc.id) {
@@ -88,79 +89,29 @@ static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index)
case PM8607_ID_LDO2:
case PM8607_ID_LDO3:
case PM8607_ID_LDO9:
- switch (chip_id) {
- case PM8607_CHIP_A0:
- case PM8607_CHIP_A1:
- ret = (index < 3) ? (index * 50000 + 1800000) :
- ((index < 8) ? (index * 50000 + 2550000) :
- -EINVAL);
- break;
- case PM8607_CHIP_B0:
- ret = (index < 3) ? (index * 50000 + 1800000) :
- ((index < 7) ? (index * 50000 + 2550000) :
- 3300000);
- break;
- }
+ ret = (index < 3) ? (index * 50000 + 1800000) :
+ ((index < 7) ? (index * 50000 + 2550000) :
+ 3300000);
break;
case PM8607_ID_LDO4:
- switch (chip_id) {
- case PM8607_CHIP_A0:
- case PM8607_CHIP_A1:
- ret = (index < 3) ? (index * 50000 + 1800000) :
- ((index < 8) ? (index * 50000 + 2550000) :
- -EINVAL);
- break;
- case PM8607_CHIP_B0:
- ret = (index < 3) ? (index * 50000 + 1800000) :
- ((index < 6) ? (index * 50000 + 2550000) :
- ((index == 6) ? 2900000 : 3300000));
- break;
- }
+ ret = (index < 3) ? (index * 50000 + 1800000) :
+ ((index < 6) ? (index * 50000 + 2550000) :
+ ((index == 6) ? 2900000 : 3300000));
break;
case PM8607_ID_LDO6:
- switch (chip_id) {
- case PM8607_CHIP_A0:
- case PM8607_CHIP_A1:
- ret = (index < 3) ? (index * 50000 + 1800000) :
- ((index < 8) ? (index * 50000 + 2450000) :
- -EINVAL);
- break;
- case PM8607_CHIP_B0:
- ret = (index < 2) ? (index * 50000 + 1800000) :
- ((index < 7) ? (index * 50000 + 2500000) :
- 3300000);
- break;
- }
+ ret = (index < 2) ? (index * 50000 + 1800000) :
+ ((index < 7) ? (index * 50000 + 2500000) :
+ 3300000);
break;
case PM8607_ID_LDO10:
- switch (chip_id) {
- case PM8607_CHIP_A0:
- case PM8607_CHIP_A1:
- ret = (index < 3) ? (index * 50000 + 1800000) :
- ((index < 8) ? (index * 50000 + 2550000) :
- 1200000);
- break;
- case PM8607_CHIP_B0:
- ret = (index < 3) ? (index * 50000 + 1800000) :
- ((index < 7) ? (index * 50000 + 2550000) :
- ((index == 7) ? 3300000 : 1200000));
- break;
- }
+ ret = (index < 3) ? (index * 50000 + 1800000) :
+ ((index < 7) ? (index * 50000 + 2550000) :
+ ((index == 7) ? 3300000 : 1200000));
break;
case PM8607_ID_LDO14:
- switch (chip_id) {
- case PM8607_CHIP_A0:
- case PM8607_CHIP_A1:
- ret = (index < 3) ? (index * 50000 + 1800000) :
- ((index < 8) ? (index * 50000 + 2550000) :
- -EINVAL);
- break;
- case PM8607_CHIP_B0:
- ret = (index < 2) ? (index * 50000 + 1800000) :
- ((index < 7) ? (index * 50000 + 2600000) :
- 3300000);
- break;
- }
+ ret = (index < 2) ? (index * 50000 + 1800000) :
+ ((index < 7) ? (index * 50000 + 2600000) :
+ 3300000);
break;
}
return ret;
@@ -169,7 +120,6 @@ static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index)
static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
{
struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
- uint8_t chip_id = info->chip->chip_id;
int val = -ENOENT;
int ret;
@@ -254,161 +204,77 @@ static int choose_voltage(struct regulator_dev *rdev, int min_uV, int max_uV)
case PM8607_ID_LDO2:
case PM8607_ID_LDO3:
case PM8607_ID_LDO9:
- switch (chip_id) {
- case PM8607_CHIP_A0:
- case PM8607_CHIP_A1:
- if (min_uV < 2700000) /* 1800mV ~ 1900mV / 50mV */
- if (min_uV <= 1800000)
- val = 0;
- else if (min_uV <= 1900000)
- val = (min_uV - 1750001) / 50000;
- else
- val = 3; /* 2700mV */
- else { /* 2700mV ~ 2900mV / 50mV */
- if (min_uV <= 2900000) {
- val = (min_uV - 2650001) / 50000;
- val += 3;
- } else
- val = -EINVAL;
- }
- break;
- case PM8607_CHIP_B0:
- if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */
- if (min_uV <= 1800000)
- val = 0;
- else if (min_uV <= 1900000)
- val = (min_uV - 1750001) / 50000;
- else
- val = 3; /* 2700mV */
- } else { /* 2700mV ~ 2850mV / 50mV */
- if (min_uV <= 2850000) {
- val = (min_uV - 2650001) / 50000;
- val += 3;
- } else if (min_uV <= 3300000)
- val = 7;
- else
- val = -EINVAL;
- }
- break;
+ if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */
+ if (min_uV <= 1800000)
+ val = 0;
+ else if (min_uV <= 1900000)
+ val = (min_uV - 1750001) / 50000;
+ else
+ val = 3; /* 2700mV */
+ } else { /* 2700mV ~ 2850mV / 50mV */
+ if (min_uV <= 2850000) {
+ val = (min_uV - 2650001) / 50000;
+ val += 3;
+ } else if (min_uV <= 3300000)
+ val = 7;
+ else
+ val = -EINVAL;
}
break;
case PM8607_ID_LDO4:
- switch (chip_id) {
- case PM8607_CHIP_A0:
- case PM8607_CHIP_A1:
- if (min_uV < 2700000) /* 1800mV ~ 1900mV / 50mV */
- if (min_uV <= 1800000)
- val = 0;
- else if (min_uV <= 1900000)
- val = (min_uV - 1750001) / 50000;
- else
- val = 3; /* 2700mV */
- else { /* 2700mV ~ 2900mV / 50mV */
- if (min_uV <= 2900000) {
- val = (min_uV - 2650001) / 50000;
- val += 3;
- } else
- val = -EINVAL;
- }
- break;
- case PM8607_CHIP_B0:
- if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */
- if (min_uV <= 1800000)
- val = 0;
- else if (min_uV <= 1900000)
- val = (min_uV - 1750001) / 50000;
- else
- val = 3; /* 2700mV */
- } else { /* 2700mV ~ 2800mV / 50mV */
- if (min_uV <= 2850000) {
- val = (min_uV - 2650001) / 50000;
- val += 3;
- } else if (min_uV <= 2900000)
- val = 6;
- else if (min_uV <= 3300000)
- val = 7;
- else
- val = -EINVAL;
- }
- break;
+ if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */
+ if (min_uV <= 1800000)
+ val = 0;
+ else if (min_uV <= 1900000)
+ val = (min_uV - 1750001) / 50000;
+ else
+ val = 3; /* 2700mV */
+ } else { /* 2700mV ~ 2800mV / 50mV */
+ if (min_uV <= 2850000) {
+ val = (min_uV - 2650001) / 50000;
+ val += 3;
+ } else if (min_uV <= 2900000)
+ val = 6;
+ else if (min_uV <= 3300000)
+ val = 7;
+ else
+ val = -EINVAL;
}
break;
case PM8607_ID_LDO6:
- switch (chip_id) {
- case PM8607_CHIP_A0:
- case PM8607_CHIP_A1:
- if (min_uV < 2600000) { /* 1800mV ~ 1900mV / 50mV */
- if (min_uV <= 1800000)
- val = 0;
- else if (min_uV <= 1900000)
- val = (min_uV - 1750001) / 50000;
- else
- val = 3; /* 2600mV */
- } else { /* 2600mV ~ 2800mV / 50mV */
- if (min_uV <= 2800000) {
- val = (min_uV - 2550001) / 50000;
- val += 3;
- } else
- val = -EINVAL;
- }
- break;
- case PM8607_CHIP_B0:
- if (min_uV < 2600000) { /* 1800mV ~ 1850mV / 50mV */
- if (min_uV <= 1800000)
- val = 0;
- else if (min_uV <= 1850000)
- val = (min_uV - 1750001) / 50000;
- else
- val = 2; /* 2600mV */
- } else { /* 2600mV ~ 2800mV / 50mV */
- if (min_uV <= 2800000) {
- val = (min_uV - 2550001) / 50000;
- val += 2;
- } else if (min_uV <= 3300000)
- val = 7;
- else
- val = -EINVAL;
- }
- break;
+ if (min_uV < 2600000) { /* 1800mV ~ 1850mV / 50mV */
+ if (min_uV <= 1800000)
+ val = 0;
+ else if (min_uV <= 1850000)
+ val = (min_uV - 1750001) / 50000;
+ else
+ val = 2; /* 2600mV */
+ } else { /* 2600mV ~ 2800mV / 50mV */
+ if (min_uV <= 2800000) {
+ val = (min_uV - 2550001) / 50000;
+ val += 2;
+ } else if (min_uV <= 3300000)
+ val = 7;
+ else
+ val = -EINVAL;
}
break;
case PM8607_ID_LDO14:
- switch (chip_id) {
- case PM8607_CHIP_A0:
- case PM8607_CHIP_A1:
- if (min_uV < 2700000) { /* 1800mV ~ 1900mV / 50mV */
- if (min_uV <= 1800000)
- val = 0;
- else if (min_uV <= 1900000)
- val = (min_uV - 1750001) / 50000;
- else
- val = 3; /* 2700mV */
- } else { /* 2700mV ~ 2900mV / 50mV */
- if (min_uV <= 2900000) {
- val = (min_uV - 2650001) / 50000;
- val += 3;
- } else
- val = -EINVAL;
- }
- break;
- case PM8607_CHIP_B0:
- if (min_uV < 2700000) { /* 1800mV ~ 1850mV / 50mV */
- if (min_uV <= 1800000)
- val = 0;
- else if (min_uV <= 1850000)
- val = (min_uV - 1750001) / 50000;
- else
- val = 2; /* 2700mV */
- } else { /* 2700mV ~ 2900mV / 50mV */
- if (min_uV <= 2900000) {
- val = (min_uV - 2650001) / 50000;
- val += 2;
- } else if (min_uV <= 3300000)
- val = 7;
- else
- val = -EINVAL;
- }
- break;
+ if (min_uV < 2700000) { /* 1800mV ~ 1850mV / 50mV */
+ if (min_uV <= 1800000)
+ val = 0;
+ else if (min_uV <= 1850000)
+ val = (min_uV - 1750001) / 50000;
+ else
+ val = 2; /* 2700mV */
+ } else { /* 2700mV ~ 2900mV / 50mV */
+ if (min_uV <= 2900000) {
+ val = (min_uV - 2650001) / 50000;
+ val += 2;
+ } else if (min_uV <= 3300000)
+ val = 7;
+ else
+ val = -EINVAL;
}
break;
}
@@ -428,7 +294,6 @@ static int pm8607_set_voltage(struct regulator_dev *rdev,
int min_uV, int max_uV)
{
struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
- struct pm8607_chip *chip = info->chip;
uint8_t val, mask;
int ret;
@@ -443,13 +308,13 @@ static int pm8607_set_voltage(struct regulator_dev *rdev,
val = (uint8_t)(ret << info->vol_shift);
mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
- ret = pm8607_set_bits(chip, info->vol_reg, mask, val);
+ ret = pm860x_set_bits(info->i2c, info->vol_reg, mask, val);
if (ret)
return ret;
switch (info->desc.id) {
case PM8607_ID_BUCK1:
case PM8607_ID_BUCK3:
- ret = pm8607_set_bits(chip, info->update_reg,
+ ret = pm860x_set_bits(info->i2c, info->update_reg,
1 << info->update_bit,
1 << info->update_bit);
break;
@@ -460,11 +325,10 @@ static int pm8607_set_voltage(struct regulator_dev *rdev,
static int pm8607_get_voltage(struct regulator_dev *rdev)
{
struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
- struct pm8607_chip *chip = info->chip;
uint8_t val, mask;
int ret;
- ret = pm8607_reg_read(chip, info->vol_reg);
+ ret = pm860x_reg_read(info->i2c, info->vol_reg);
if (ret < 0)
return ret;
@@ -477,9 +341,8 @@ static int pm8607_get_voltage(struct regulator_dev *rdev)
static int pm8607_enable(struct regulator_dev *rdev)
{
struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
- struct pm8607_chip *chip = info->chip;
- return pm8607_set_bits(chip, info->enable_reg,
+ return pm860x_set_bits(info->i2c, info->enable_reg,
1 << info->enable_bit,
1 << info->enable_bit);
}
@@ -487,19 +350,17 @@ static int pm8607_enable(struct regulator_dev *rdev)
static int pm8607_disable(struct regulator_dev *rdev)
{
struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
- struct pm8607_chip *chip = info->chip;
- return pm8607_set_bits(chip, info->enable_reg,
+ return pm860x_set_bits(info->i2c, info->enable_reg,
1 << info->enable_bit, 0);
}
static int pm8607_is_enabled(struct regulator_dev *rdev)
{
struct pm8607_regulator_info *info = rdev_get_drvdata(rdev);
- struct pm8607_chip *chip = info->chip;
int ret;
- ret = pm8607_reg_read(chip, info->enable_reg);
+ ret = pm860x_reg_read(info->i2c, info->enable_reg);
if (ret < 0)
return ret;
@@ -589,8 +450,8 @@ static inline struct pm8607_regulator_info *find_regulator_info(int id)
static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
{
- struct pm8607_chip *chip = dev_get_drvdata(pdev->dev.parent);
- struct pm8607_platform_data *pdata = chip->dev->platform_data;
+ struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ struct pm860x_platform_data *pdata = chip->dev->platform_data;
struct pm8607_regulator_info *info = NULL;
info = find_regulator_info(pdev->id);
@@ -599,6 +460,7 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
return -EINVAL;
}
+ info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
info->chip = chip;
info->regulator = regulator_register(&info->desc, &pdev->dev,
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 834b4844182..04f2e085116 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -94,6 +94,12 @@ config REGULATOR_MAX8660
This driver controls a Maxim 8660/8661 voltage output
regulator via I2C bus.
+config REGULATOR_MAX8925
+ tristate "Maxim MAX8925 Power Management IC"
+ depends on MFD_MAX8925
+ help
+ Say y here to support the voltage regulaltor of Maxim MAX8925 PMIC.
+
config REGULATOR_TWL4030
bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC"
depends on TWL4030_CORE
@@ -191,7 +197,7 @@ config REGULATOR_TPS6507X
config REGULATOR_88PM8607
bool "Marvell 88PM8607 Power regulators"
- depends on MFD_88PM8607=y
+ depends on MFD_88PM860X=y
help
This driver supports 88PM8607 voltage regulator chips.
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index e845b66ad59..4e7feece22d 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o
obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
+obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c
new file mode 100644
index 00000000000..67873f08ed4
--- /dev/null
+++ b/drivers/regulator/max8925-regulator.c
@@ -0,0 +1,306 @@
+/*
+ * Regulators driver for Maxim max8925
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ * Haojian Zhuang <haojian.zhuang@marvell.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/max8925.h>
+
+#define SD1_DVM_VMIN 850000
+#define SD1_DVM_VMAX 1000000
+#define SD1_DVM_STEP 50000
+#define SD1_DVM_SHIFT 5 /* SDCTL1 bit5 */
+#define SD1_DVM_EN 6 /* SDV1 bit 6 */
+
+struct max8925_regulator_info {
+ struct regulator_desc desc;
+ struct regulator_dev *regulator;
+ struct i2c_client *i2c;
+ struct max8925_chip *chip;
+
+ int min_uV;
+ int max_uV;
+ int step_uV;
+ int vol_reg;
+ int vol_shift;
+ int vol_nbits;
+ int enable_bit;
+ int enable_reg;
+};
+
+static inline int check_range(struct max8925_regulator_info *info,
+ int min_uV, int max_uV)
+{
+ if (min_uV < info->min_uV || min_uV > info->max_uV)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int max8925_list_voltage(struct regulator_dev *rdev, unsigned index)
+{
+ struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
+ return info->min_uV + index * info->step_uV;
+}
+
+static int max8925_set_voltage(struct regulator_dev *rdev,
+ int min_uV, int max_uV)
+{
+ struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
+ unsigned char data, mask;
+
+ if (check_range(info, min_uV, max_uV)) {
+ dev_err(info->chip->dev, "invalid voltage range (%d, %d) uV\n",
+ min_uV, max_uV);
+ return -EINVAL;
+ }
+ data = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV;
+ data <<= info->vol_shift;
+ mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
+
+ return max8925_set_bits(info->i2c, info->vol_reg, mask, data);
+}
+
+static int max8925_get_voltage(struct regulator_dev *rdev)
+{
+ struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
+ unsigned char data, mask;
+ int ret;
+
+ ret = max8925_reg_read(info->i2c, info->vol_reg);
+ if (ret < 0)
+ return ret;
+ mask = ((1 << info->vol_nbits) - 1) << info->vol_shift;
+ data = (ret & mask) >> info->vol_shift;
+
+ return max8925_list_voltage(rdev, data);
+}
+
+static int max8925_enable(struct regulator_dev *rdev)
+{
+ struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
+
+ return max8925_set_bits(info->i2c, info->enable_reg,
+ 1 << info->enable_bit,
+ 1 << info->enable_bit);
+}
+
+static int max8925_disable(struct regulator_dev *rdev)
+{
+ struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
+
+ return max8925_set_bits(info->i2c, info->enable_reg,
+ 1 << info->enable_bit, 0);
+}
+
+static int max8925_is_enabled(struct regulator_dev *rdev)
+{
+ struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
+ int ret;
+
+ ret = max8925_reg_read(info->i2c, info->vol_reg);
+ if (ret < 0)
+ return ret;
+
+ return ret & (1 << info->enable_bit);
+}
+
+static int max8925_set_dvm_voltage(struct regulator_dev *rdev, int uV)
+{
+ struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
+ unsigned char data, mask;
+
+ if (uV < SD1_DVM_VMIN || uV > SD1_DVM_VMAX)
+ return -EINVAL;
+
+ data = (uV - SD1_DVM_VMIN + SD1_DVM_STEP - 1) / SD1_DVM_STEP;
+ data <<= SD1_DVM_SHIFT;
+ mask = 3 << SD1_DVM_SHIFT;
+
+ return max8925_set_bits(info->i2c, info->enable_reg, mask, data);
+}
+
+static int max8925_set_dvm_enable(struct regulator_dev *rdev)
+{
+ struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
+
+ return max8925_set_bits(info->i2c, info->vol_reg, 1 << SD1_DVM_EN,
+ 1 << SD1_DVM_EN);
+}
+
+static int max8925_set_dvm_disable(struct regulator_dev *rdev)
+{
+ struct max8925_regulator_info *info = rdev_get_drvdata(rdev);
+
+ return max8925_set_bits(info->i2c, info->vol_reg, 1 << SD1_DVM_EN, 0);
+}
+
+static struct regulator_ops max8925_regulator_sdv_ops = {
+ .set_voltage = max8925_set_voltage,
+ .get_voltage = max8925_get_voltage,
+ .enable = max8925_enable,
+ .disable = max8925_disable,
+ .is_enabled = max8925_is_enabled,
+ .set_suspend_voltage = max8925_set_dvm_voltage,
+ .set_suspend_enable = max8925_set_dvm_enable,
+ .set_suspend_disable = max8925_set_dvm_disable,
+};
+
+static struct regulator_ops max8925_regulator_ldo_ops = {
+ .set_voltage = max8925_set_voltage,
+ .get_voltage = max8925_get_voltage,
+ .enable = max8925_enable,
+ .disable = max8925_disable,
+ .is_enabled = max8925_is_enabled,
+};
+
+#define MAX8925_SDV(_id, min, max, step) \
+{ \
+ .desc = { \
+ .name = "SDV" #_id, \
+ .ops = &max8925_regulator_sdv_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MAX8925_ID_SD##_id, \
+ .owner = THIS_MODULE, \
+ }, \
+ .min_uV = min * 1000, \
+ .max_uV = max * 1000, \
+ .step_uV = step * 1000, \
+ .vol_reg = MAX8925_SDV##_id, \
+ .vol_shift = 0, \
+ .vol_nbits = 6, \
+ .enable_reg = MAX8925_SDCTL##_id, \
+ .enable_bit = 0, \
+}
+
+#define MAX8925_LDO(_id, min, max, step) \
+{ \
+ .desc = { \
+ .name = "LDO" #_id, \
+ .ops = &max8925_regulator_ldo_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .id = MAX8925_ID_LDO##_id, \
+ .owner = THIS_MODULE, \
+ }, \
+ .min_uV = min * 1000, \
+ .max_uV = max * 1000, \
+ .step_uV = step * 1000, \
+ .vol_reg = MAX8925_LDOVOUT##_id, \
+ .vol_shift = 0, \
+ .vol_nbits = 6, \
+ .enable_reg = MAX8925_LDOCTL##_id, \
+ .enable_bit = 0, \
+}
+
+static struct max8925_regulator_info max8925_regulator_info[] = {
+ MAX8925_SDV(1, 637.5, 1425, 12.5),
+ MAX8925_SDV(2, 650, 2225, 25),
+ MAX8925_SDV(3, 750, 3900, 50),
+
+ MAX8925_LDO(1, 750, 3900, 50),
+ MAX8925_LDO(2, 650, 2250, 25),
+ MAX8925_LDO(3, 650, 2250, 25),
+ MAX8925_LDO(4, 750, 3900, 50),
+ MAX8925_LDO(5, 750, 3900, 50),
+ MAX8925_LDO(6, 750, 3900, 50),
+ MAX8925_LDO(7, 750, 3900, 50),
+ MAX8925_LDO(8, 750, 3900, 50),
+ MAX8925_LDO(9, 750, 3900, 50),
+ MAX8925_LDO(10, 750, 3900, 50),
+ MAX8925_LDO(11, 750, 3900, 50),
+ MAX8925_LDO(12, 750, 3900, 50),
+ MAX8925_LDO(13, 750, 3900, 50),
+ MAX8925_LDO(14, 750, 3900, 50),
+ MAX8925_LDO(15, 750, 3900, 50),
+ MAX8925_LDO(16, 750, 3900, 50),
+ MAX8925_LDO(17, 650, 2250, 25),
+ MAX8925_LDO(18, 650, 2250, 25),
+ MAX8925_LDO(19, 750, 3900, 50),
+ MAX8925_LDO(20, 750, 3900, 50),
+};
+
+static inline struct max8925_regulator_info *find_regulator_info(int id)
+{
+ struct max8925_regulator_info *ri;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(max8925_regulator_info); i++) {
+ ri = &max8925_regulator_info[i];
+ if (ri->desc.id == id)
+ return ri;
+ }
+ return NULL;
+}
+
+static int __devinit max8925_regulator_probe(struct platform_device *pdev)
+{
+ struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ struct max8925_platform_data *pdata = chip->dev->platform_data;
+ struct max8925_regulator_info *ri = NULL;
+ struct regulator_dev *rdev;
+
+ ri = find_regulator_info(pdev->id);
+ if (ri == NULL) {
+ dev_err(&pdev->dev, "invalid regulator ID specified\n");
+ return -EINVAL;
+ }
+ ri->i2c = chip->i2c;
+ ri->chip = chip;
+
+ rdev = regulator_register(&ri->desc, &pdev->dev,
+ pdata->regulator[pdev->id], ri);
+ if (IS_ERR(rdev)) {
+ dev_err(&pdev->dev, "failed to register regulator %s\n",
+ ri->desc.name);
+ return PTR_ERR(rdev);
+ }
+
+ platform_set_drvdata(pdev, rdev);
+ return 0;
+}
+
+static int __devexit max8925_regulator_remove(struct platform_device *pdev)
+{
+ struct regulator_dev *rdev = platform_get_drvdata(pdev);
+
+ regulator_unregister(rdev);
+ return 0;
+}
+
+static struct platform_driver max8925_regulator_driver = {
+ .driver = {
+ .name = "max8925-regulator",
+ .owner = THIS_MODULE,
+ },
+ .probe = max8925_regulator_probe,
+ .remove = __devexit_p(max8925_regulator_remove),
+};
+
+static int __init max8925_regulator_init(void)
+{
+ return platform_driver_register(&max8925_regulator_driver);
+}
+subsys_initcall(max8925_regulator_init);
+
+static void __exit max8925_regulator_exit(void)
+{
+ platform_driver_unregister(&max8925_regulator_driver);
+}
+module_exit(max8925_regulator_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_DESCRIPTION("Regulator Driver for Maxim 8925 PMIC");
+MODULE_ALIAS("platform:max8925-regulator");
+
diff --git a/drivers/regulator/wm8350-regulator.c b/drivers/regulator/wm8350-regulator.c
index 94227dd6ba7..723cd1fb486 100644
--- a/drivers/regulator/wm8350-regulator.c
+++ b/drivers/regulator/wm8350-regulator.c
@@ -1453,7 +1453,7 @@ static int wm8350_regulator_remove(struct platform_device *pdev)
struct regulator_dev *rdev = platform_get_drvdata(pdev);
struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
- wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq);
+ wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq, rdev);
regulator_unregister(rdev);
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 2bb8a8b7ffa..6a130375943 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -175,6 +175,16 @@ config RTC_DRV_MAX6900
This driver can also be built as a module. If so, the module
will be called rtc-max6900.
+config RTC_DRV_MAX8925
+ tristate "Maxim MAX8925"
+ depends on MFD_MAX8925
+ help
+ If you say yes here you will get support for the
+ RTC of Maxim MAX8925 PMIC.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-max8925.
+
config RTC_DRV_RS5C372
tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A"
help
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index b7148afb8f5..44ef194a957 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o
obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
obj-$(CONFIG_RTC_MXC) += rtc-mxc.o
obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
+obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
obj-$(CONFIG_RTC_DRV_MC13783) += rtc-mc13783.o
obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index be5a6b73e60..40845c7e932 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -226,6 +226,7 @@ static void __exit rtc_exit(void)
{
rtc_dev_exit();
class_destroy(rtc_class);
+ idr_destroy(&rtc_idr);
}
subsys_initcall(rtc_init);
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 86c61f14351..78a018b5c94 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -161,7 +161,7 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
if (offset == 0)
return -EILSEQ;
- memset(alrm, 0, sizeof(alrm));
+ memset(alrm, 0, sizeof(*alrm));
if (alarm != ALARM_DISABLED && offset != 0) {
rtc_time_to_tm(offset + alarm, tm);
diff --git a/drivers/rtc/rtc-coh901331.c b/drivers/rtc/rtc-coh901331.c
index 03ea530981d..44c4399ee71 100644
--- a/drivers/rtc/rtc-coh901331.c
+++ b/drivers/rtc/rtc-coh901331.c
@@ -271,12 +271,13 @@ static int coh901331_resume(struct platform_device *pdev)
{
struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev);
- if (device_may_wakeup(&pdev->dev))
+ if (device_may_wakeup(&pdev->dev)) {
disable_irq_wake(rtap->irq);
- else
+ } else {
clk_enable(rtap->clk);
writel(rtap->irqmaskstore, rtap->virtbase + COH901331_IRQ_MASK);
clk_disable(rtap->clk);
+ }
return 0;
}
#else
diff --git a/drivers/rtc/rtc-ep93xx.c b/drivers/rtc/rtc-ep93xx.c
index 9da02d108b7..91bde976bc0 100644
--- a/drivers/rtc/rtc-ep93xx.c
+++ b/drivers/rtc/rtc-ep93xx.c
@@ -115,6 +115,15 @@ static ssize_t ep93xx_rtc_show_comp_delete(struct device *dev,
}
static DEVICE_ATTR(comp_delete, S_IRUGO, ep93xx_rtc_show_comp_delete, NULL);
+static struct attribute *ep93xx_rtc_attrs[] = {
+ &dev_attr_comp_preload.attr,
+ &dev_attr_comp_delete.attr,
+ NULL
+};
+
+static const struct attribute_group ep93xx_rtc_sysfs_files = {
+ .attrs = ep93xx_rtc_attrs,
+};
static int __init ep93xx_rtc_probe(struct platform_device *pdev)
{
@@ -123,27 +132,22 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev)
struct rtc_device *rtc;
int err;
- ep93xx_rtc = kzalloc(sizeof(struct ep93xx_rtc), GFP_KERNEL);
- if (ep93xx_rtc == NULL)
+ ep93xx_rtc = devm_kzalloc(&pdev->dev, sizeof(*ep93xx_rtc), GFP_KERNEL);
+ if (!ep93xx_rtc)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- err = -ENXIO;
- goto fail_free;
- }
+ if (!res)
+ return -ENXIO;
- res = request_mem_region(res->start, resource_size(res), pdev->name);
- if (res == NULL) {
- err = -EBUSY;
- goto fail_free;
- }
+ if (!devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res), pdev->name))
+ return -EBUSY;
- ep93xx_rtc->mmio_base = ioremap(res->start, resource_size(res));
- if (ep93xx_rtc->mmio_base == NULL) {
- err = -ENXIO;
- goto fail;
- }
+ ep93xx_rtc->mmio_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!ep93xx_rtc->mmio_base)
+ return -ENXIO;
pdev->dev.platform_data = ep93xx_rtc;
@@ -151,53 +155,34 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev)
&pdev->dev, &ep93xx_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc)) {
err = PTR_ERR(rtc);
- goto fail;
+ goto exit;
}
platform_set_drvdata(pdev, rtc);
- err = device_create_file(&pdev->dev, &dev_attr_comp_preload);
+ err = sysfs_create_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files);
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));
-fail_free:
- kfree(ep93xx_rtc);
+ platform_set_drvdata(pdev, NULL);
+ rtc_device_unregister(rtc);
+exit:
+ pdev->dev.platform_data = NULL;
return err;
}
static int __exit ep93xx_rtc_remove(struct platform_device *pdev)
{
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);
+ sysfs_remove_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files);
+ platform_set_drvdata(pdev, NULL);
rtc_device_unregister(rtc);
-
- iounmap(ep93xx_rtc->mmio_base);
pdev->dev.platform_data = NULL;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(res->start, resource_size(res));
-
- platform_set_drvdata(pdev, NULL);
-
return 0;
}
diff --git a/drivers/rtc/rtc-max8925.c b/drivers/rtc/rtc-max8925.c
new file mode 100644
index 00000000000..acdbb176018
--- /dev/null
+++ b/drivers/rtc/rtc-max8925.c
@@ -0,0 +1,314 @@
+/*
+ * RTC driver for Maxim MAX8925
+ *
+ * Copyright (C) 2009-2010 Marvell International Ltd.
+ * Haojian Zhuang <haojian.zhuang@marvell.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/i2c.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/max8925.h>
+
+enum {
+ RTC_SEC = 0,
+ RTC_MIN,
+ RTC_HOUR,
+ RTC_WEEKDAY,
+ RTC_DATE,
+ RTC_MONTH,
+ RTC_YEAR1,
+ RTC_YEAR2,
+};
+
+#define MAX8925_RTC_SEC 0x00
+#define MAX8925_RTC_MIN 0x01
+#define MAX8925_RTC_HOUR 0x02
+#define MAX8925_RTC_WEEKDAY 0x03
+#define MAX8925_RTC_DATE 0x04
+#define MAX8925_RTC_MONTH 0x05
+#define MAX8925_RTC_YEAR1 0x06
+#define MAX8925_RTC_YEAR2 0x07
+#define MAX8925_ALARM0_SEC 0x08
+#define MAX8925_ALARM0_MIN 0x09
+#define MAX8925_ALARM0_HOUR 0x0a
+#define MAX8925_ALARM0_WEEKDAY 0x0b
+#define MAX8925_ALARM0_DATE 0x0c
+#define MAX8925_ALARM0_MON 0x0d
+#define MAX8925_ALARM0_YEAR1 0x0e
+#define MAX8925_ALARM0_YEAR2 0x0f
+#define MAX8925_ALARM1_SEC 0x10
+#define MAX8925_ALARM1_MIN 0x11
+#define MAX8925_ALARM1_HOUR 0x12
+#define MAX8925_ALARM1_WEEKDAY 0x13
+#define MAX8925_ALARM1_DATE 0x14
+#define MAX8925_ALARM1_MON 0x15
+#define MAX8925_ALARM1_YEAR1 0x16
+#define MAX8925_ALARM1_YEAR2 0x17
+#define MAX8925_RTC_CNTL 0x1b
+#define MAX8925_RTC_STATUS 0x20
+
+#define TIME_NUM 8
+#define ALARM_1SEC (1 << 7)
+#define HOUR_12 (1 << 7)
+#define HOUR_AM_PM (1 << 5)
+#define ALARM0_IRQ (1 << 3)
+#define ALARM1_IRQ (1 << 2)
+#define ALARM0_STATUS (1 << 2)
+#define ALARM1_STATUS (1 << 1)
+
+
+struct max8925_rtc_info {
+ struct rtc_device *rtc_dev;
+ struct max8925_chip *chip;
+ struct i2c_client *rtc;
+ struct device *dev;
+};
+
+static irqreturn_t rtc_update_handler(int irq, void *data)
+{
+ struct max8925_rtc_info *info = (struct max8925_rtc_info *)data;
+
+ /* disable ALARM0 except for 1SEC alarm */
+ max8925_set_bits(info->rtc, MAX8925_ALARM0_CNTL, 0x7f, 0);
+ rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF);
+ return IRQ_HANDLED;
+}
+
+static int tm_calc(struct rtc_time *tm, unsigned char *buf, int len)
+{
+ if (len < TIME_NUM)
+ return -EINVAL;
+ tm->tm_year = (buf[RTC_YEAR2] >> 4) * 1000
+ + (buf[RTC_YEAR2] & 0xf) * 100
+ + (buf[RTC_YEAR1] >> 4) * 10
+ + (buf[RTC_YEAR1] & 0xf);
+ tm->tm_year -= 1900;
+ tm->tm_mon = ((buf[RTC_MONTH] >> 4) & 0x01) * 10
+ + (buf[RTC_MONTH] & 0x0f);
+ tm->tm_mday = ((buf[RTC_DATE] >> 4) & 0x03) * 10
+ + (buf[RTC_DATE] & 0x0f);
+ tm->tm_wday = buf[RTC_WEEKDAY] & 0x07;
+ if (buf[RTC_HOUR] & HOUR_12) {
+ tm->tm_hour = ((buf[RTC_HOUR] >> 4) & 0x1) * 10
+ + (buf[RTC_HOUR] & 0x0f);
+ if (buf[RTC_HOUR] & HOUR_AM_PM)
+ tm->tm_hour += 12;
+ } else
+ tm->tm_hour = ((buf[RTC_HOUR] >> 4) & 0x03) * 10
+ + (buf[RTC_HOUR] & 0x0f);
+ tm->tm_min = ((buf[RTC_MIN] >> 4) & 0x7) * 10
+ + (buf[RTC_MIN] & 0x0f);
+ tm->tm_sec = ((buf[RTC_SEC] >> 4) & 0x7) * 10
+ + (buf[RTC_SEC] & 0x0f);
+ return 0;
+}
+
+static int data_calc(unsigned char *buf, struct rtc_time *tm, int len)
+{
+ unsigned char high, low;
+
+ if (len < TIME_NUM)
+ return -EINVAL;
+
+ high = (tm->tm_year + 1900) / 1000;
+ low = (tm->tm_year + 1900) / 100;
+ low = low - high * 10;
+ buf[RTC_YEAR2] = (high << 4) + low;
+ high = (tm->tm_year + 1900) / 10;
+ low = tm->tm_year + 1900;
+ low = low - high * 10;
+ high = high - (high / 10) * 10;
+ buf[RTC_YEAR1] = (high << 4) + low;
+ high = tm->tm_mon / 10;
+ low = tm->tm_mon;
+ low = low - high * 10;
+ buf[RTC_MONTH] = (high << 4) + low;
+ high = tm->tm_mday / 10;
+ low = tm->tm_mday;
+ low = low - high * 10;
+ buf[RTC_DATE] = (high << 4) + low;
+ buf[RTC_WEEKDAY] = tm->tm_wday;
+ high = tm->tm_hour / 10;
+ low = tm->tm_hour;
+ low = low - high * 10;
+ buf[RTC_HOUR] = (high << 4) + low;
+ high = tm->tm_min / 10;
+ low = tm->tm_min;
+ low = low - high * 10;
+ buf[RTC_MIN] = (high << 4) + low;
+ high = tm->tm_sec / 10;
+ low = tm->tm_sec;
+ low = low - high * 10;
+ buf[RTC_SEC] = (high << 4) + low;
+ return 0;
+}
+
+static int max8925_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct max8925_rtc_info *info = dev_get_drvdata(dev);
+ unsigned char buf[TIME_NUM];
+ int ret;
+
+ ret = max8925_bulk_read(info->rtc, MAX8925_RTC_SEC, TIME_NUM, buf);
+ if (ret < 0)
+ goto out;
+ ret = tm_calc(tm, buf, TIME_NUM);
+out:
+ return ret;
+}
+
+static int max8925_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct max8925_rtc_info *info = dev_get_drvdata(dev);
+ unsigned char buf[TIME_NUM];
+ int ret;
+
+ ret = data_calc(buf, tm, TIME_NUM);
+ if (ret < 0)
+ goto out;
+ ret = max8925_bulk_write(info->rtc, MAX8925_RTC_SEC, TIME_NUM, buf);
+out:
+ return ret;
+}
+
+static int max8925_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct max8925_rtc_info *info = dev_get_drvdata(dev);
+ unsigned char buf[TIME_NUM];
+ int ret;
+
+ ret = max8925_bulk_read(info->rtc, MAX8925_ALARM0_SEC, TIME_NUM, buf);
+ if (ret < 0)
+ goto out;
+ ret = tm_calc(&alrm->time, buf, TIME_NUM);
+ if (ret < 0)
+ goto out;
+ ret = max8925_reg_read(info->rtc, MAX8925_RTC_IRQ_MASK);
+ if (ret < 0)
+ goto out;
+ if ((ret & ALARM0_IRQ) == 0)
+ alrm->enabled = 1;
+ else
+ alrm->enabled = 0;
+ ret = max8925_reg_read(info->rtc, MAX8925_RTC_STATUS);
+ if (ret < 0)
+ goto out;
+ if (ret & ALARM0_STATUS)
+ alrm->pending = 1;
+ else
+ alrm->pending = 0;
+out:
+ return ret;
+}
+
+static int max8925_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct max8925_rtc_info *info = dev_get_drvdata(dev);
+ unsigned char buf[TIME_NUM];
+ int ret;
+
+ ret = data_calc(buf, &alrm->time, TIME_NUM);
+ if (ret < 0)
+ goto out;
+ ret = max8925_bulk_write(info->rtc, MAX8925_ALARM0_SEC, TIME_NUM, buf);
+ if (ret < 0)
+ goto out;
+ /* only enable alarm on year/month/day/hour/min/sec */
+ ret = max8925_reg_write(info->rtc, MAX8925_ALARM0_CNTL, 0x77);
+ if (ret < 0)
+ goto out;
+out:
+ return ret;
+}
+
+static const struct rtc_class_ops max8925_rtc_ops = {
+ .read_time = max8925_rtc_read_time,
+ .set_time = max8925_rtc_set_time,
+ .read_alarm = max8925_rtc_read_alarm,
+ .set_alarm = max8925_rtc_set_alarm,
+};
+
+static int __devinit max8925_rtc_probe(struct platform_device *pdev)
+{
+ struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ struct max8925_rtc_info *info;
+ int irq, ret;
+
+ info = kzalloc(sizeof(struct max8925_rtc_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+ info->chip = chip;
+ info->rtc = chip->rtc;
+ info->dev = &pdev->dev;
+ irq = chip->irq_base + MAX8925_IRQ_RTC_ALARM0;
+
+ ret = request_threaded_irq(irq, NULL, rtc_update_handler,
+ IRQF_ONESHOT, "rtc-alarm0", info);
+ if (ret < 0) {
+ dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
+ irq, ret);
+ goto out_irq;
+ }
+
+ info->rtc_dev = rtc_device_register("max8925-rtc", &pdev->dev,
+ &max8925_rtc_ops, THIS_MODULE);
+ ret = PTR_ERR(info->rtc_dev);
+ if (IS_ERR(info->rtc_dev)) {
+ dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
+ goto out_rtc;
+ }
+
+ dev_set_drvdata(&pdev->dev, info);
+ platform_set_drvdata(pdev, info);
+
+ return 0;
+out_rtc:
+ free_irq(chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info);
+out_irq:
+ kfree(info);
+ return ret;
+}
+
+static int __devexit max8925_rtc_remove(struct platform_device *pdev)
+{
+ struct max8925_rtc_info *info = platform_get_drvdata(pdev);
+
+ if (info) {
+ free_irq(info->chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info);
+ rtc_device_unregister(info->rtc_dev);
+ kfree(info);
+ }
+ return 0;
+}
+
+static struct platform_driver max8925_rtc_driver = {
+ .driver = {
+ .name = "max8925-rtc",
+ .owner = THIS_MODULE,
+ },
+ .probe = max8925_rtc_probe,
+ .remove = __devexit_p(max8925_rtc_remove),
+};
+
+static int __init max8925_rtc_init(void)
+{
+ return platform_driver_register(&max8925_rtc_driver);
+}
+module_init(max8925_rtc_init);
+
+static void __exit max8925_rtc_exit(void)
+{
+ platform_driver_unregister(&max8925_rtc_driver);
+}
+module_exit(max8925_rtc_exit);
+
+MODULE_DESCRIPTION("Maxim MAX8925 RTC driver");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/rtc/rtc-mc13783.c b/drivers/rtc/rtc-mc13783.c
index 850f983c039..d60c81b7b69 100644
--- a/drivers/rtc/rtc-mc13783.c
+++ b/drivers/rtc/rtc-mc13783.c
@@ -28,6 +28,34 @@ struct mc13783_rtc {
int valid;
};
+static int mc13783_rtc_irq_enable_unlocked(struct device *dev,
+ unsigned int enabled, int irq)
+{
+ struct mc13783_rtc *priv = dev_get_drvdata(dev);
+ int (*func)(struct mc13783 *mc13783, int irq);
+
+ if (!priv->valid)
+ return -ENODATA;
+
+ func = enabled ? mc13783_irq_unmask : mc13783_irq_mask;
+ return func(priv->mc13783, irq);
+}
+
+static int mc13783_rtc_irq_enable(struct device *dev,
+ unsigned int enabled, int irq)
+{
+ struct mc13783_rtc *priv = dev_get_drvdata(dev);
+ int ret;
+
+ mc13783_lock(priv->mc13783);
+
+ ret = mc13783_rtc_irq_enable_unlocked(dev, enabled, irq);
+
+ mc13783_unlock(priv->mc13783);
+
+ return ret;
+}
+
static int mc13783_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct mc13783_rtc *priv = dev_get_drvdata(dev);
@@ -78,6 +106,7 @@ static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs)
{
struct mc13783_rtc *priv = dev_get_drvdata(dev);
unsigned int seconds, days;
+ unsigned int alarmseconds;
int ret;
seconds = secs % 86400;
@@ -86,7 +115,22 @@ static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs)
mc13783_lock(priv->mc13783);
/*
- * first write seconds=0 to prevent a day switch between writing days
+ * temporarily invalidate alarm to prevent triggering it when the day is
+ * already updated while the time isn't yet.
+ */
+ ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTODA, &alarmseconds);
+ if (unlikely(ret))
+ goto out;
+
+ if (alarmseconds < 86400) {
+ ret = mc13783_reg_write(priv->mc13783,
+ MC13783_RTCTODA, 0x1ffff);
+ if (unlikely(ret))
+ goto out;
+ }
+
+ /*
+ * write seconds=0 to prevent a day switch between writing days
* and seconds below
*/
ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTOD, 0);
@@ -101,11 +145,19 @@ static int mc13783_rtc_set_mmss(struct device *dev, unsigned long secs)
if (unlikely(ret))
goto out;
- ret = mc13783_ackirq(priv->mc13783, MC13783_IRQ_RTCRST);
+ /* restore alarm */
+ if (alarmseconds < 86400) {
+ ret = mc13783_reg_write(priv->mc13783,
+ MC13783_RTCTODA, alarmseconds);
+ if (unlikely(ret))
+ goto out;
+ }
+
+ ret = mc13783_irq_ack(priv->mc13783, MC13783_IRQ_RTCRST);
if (unlikely(ret))
goto out;
- ret = mc13783_unmask(priv->mc13783, MC13783_IRQ_RTCRST);
+ ret = mc13783_irq_unmask(priv->mc13783, MC13783_IRQ_RTCRST);
out:
priv->valid = !ret;
@@ -114,41 +166,139 @@ out:
return ret;
}
-static irqreturn_t mc13783_rtc_update_handler(int irq, void *dev)
+static int mc13783_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
- struct mc13783_rtc *priv = dev;
- struct mc13783 *mc13783 = priv->mc13783;
+ struct mc13783_rtc *priv = dev_get_drvdata(dev);
+ unsigned seconds, days;
+ unsigned long s1970;
+ int enabled, pending;
+ int ret;
- dev_dbg(&priv->rtc->dev, "1HZ\n");
+ mc13783_lock(priv->mc13783);
- rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF);
+ ret = mc13783_reg_read(priv->mc13783, MC13783_RTCTODA, &seconds);
+ if (unlikely(ret))
+ goto out;
+ if (seconds >= 86400) {
+ ret = -ENODATA;
+ goto out;
+ }
+
+ ret = mc13783_reg_read(priv->mc13783, MC13783_RTCDAY, &days);
+ if (unlikely(ret))
+ goto out;
- mc13783_ackirq(mc13783, irq);
+ ret = mc13783_irq_status(priv->mc13783, MC13783_IRQ_TODA,
+ &enabled, &pending);
- return IRQ_HANDLED;
+out:
+ mc13783_unlock(priv->mc13783);
+
+ if (ret)
+ return ret;
+
+ alarm->enabled = enabled;
+ alarm->pending = pending;
+
+ s1970 = days * 86400 + seconds;
+
+ rtc_time_to_tm(s1970, &alarm->time);
+ dev_dbg(dev, "%s: %lu\n", __func__, s1970);
+
+ return 0;
}
-static int mc13783_rtc_update_irq_enable(struct device *dev,
- unsigned int enabled)
+static int mc13783_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
struct mc13783_rtc *priv = dev_get_drvdata(dev);
- int ret = -ENODATA;
+ unsigned long s1970;
+ unsigned seconds, days;
+ int ret;
mc13783_lock(priv->mc13783);
- if (!priv->valid)
+
+ /* disable alarm to prevent false triggering */
+ ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTODA, 0x1ffff);
+ if (unlikely(ret))
goto out;
- ret = (enabled ? mc13783_unmask : mc13783_mask)(priv->mc13783,
- MC13783_IRQ_1HZ);
+ ret = mc13783_irq_ack(priv->mc13783, MC13783_IRQ_TODA);
+ if (unlikely(ret))
+ goto out;
+
+ ret = rtc_tm_to_time(&alarm->time, &s1970);
+ if (unlikely(ret))
+ goto out;
+
+ dev_dbg(dev, "%s: o%2.s %lu\n", __func__, alarm->enabled ? "n" : "ff",
+ s1970);
+
+ ret = mc13783_rtc_irq_enable_unlocked(dev, alarm->enabled,
+ MC13783_IRQ_TODA);
+ if (unlikely(ret))
+ goto out;
+
+ seconds = s1970 % 86400;
+ days = s1970 / 86400;
+
+ ret = mc13783_reg_write(priv->mc13783, MC13783_RTCDAYA, days);
+ if (unlikely(ret))
+ goto out;
+
+ ret = mc13783_reg_write(priv->mc13783, MC13783_RTCTODA, seconds);
+
out:
mc13783_unlock(priv->mc13783);
return ret;
}
+static irqreturn_t mc13783_rtc_alarm_handler(int irq, void *dev)
+{
+ struct mc13783_rtc *priv = dev;
+ struct mc13783 *mc13783 = priv->mc13783;
+
+ dev_dbg(&priv->rtc->dev, "Alarm\n");
+
+ rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_AF);
+
+ mc13783_irq_ack(mc13783, irq);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mc13783_rtc_update_handler(int irq, void *dev)
+{
+ struct mc13783_rtc *priv = dev;
+ struct mc13783 *mc13783 = priv->mc13783;
+
+ dev_dbg(&priv->rtc->dev, "1HZ\n");
+
+ rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF);
+
+ mc13783_irq_ack(mc13783, irq);
+
+ return IRQ_HANDLED;
+}
+
+static int mc13783_rtc_update_irq_enable(struct device *dev,
+ unsigned int enabled)
+{
+ return mc13783_rtc_irq_enable(dev, enabled, MC13783_IRQ_1HZ);
+}
+
+static int mc13783_rtc_alarm_irq_enable(struct device *dev,
+ unsigned int enabled)
+{
+ return mc13783_rtc_irq_enable(dev, enabled, MC13783_IRQ_TODA);
+}
+
static const struct rtc_class_ops mc13783_rtc_ops = {
.read_time = mc13783_rtc_read_time,
.set_mmss = mc13783_rtc_set_mmss,
+ .read_alarm = mc13783_rtc_read_alarm,
+ .set_alarm = mc13783_rtc_set_alarm,
+ .alarm_irq_enable = mc13783_rtc_alarm_irq_enable,
.update_irq_enable = mc13783_rtc_update_irq_enable,
};
@@ -160,7 +310,7 @@ static irqreturn_t mc13783_rtc_reset_handler(int irq, void *dev)
dev_dbg(&priv->rtc->dev, "RTCRST\n");
priv->valid = 0;
- mc13783_mask(mc13783, irq);
+ mc13783_irq_mask(mc13783, irq);
return IRQ_HANDLED;
}
@@ -169,6 +319,7 @@ static int __devinit mc13783_rtc_probe(struct platform_device *pdev)
{
int ret;
struct mc13783_rtc *priv;
+ int rtcrst_pending;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -177,8 +328,6 @@ static int __devinit mc13783_rtc_probe(struct platform_device *pdev)
priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
platform_set_drvdata(pdev, priv);
- priv->valid = 1;
-
mc13783_lock(priv->mc13783);
ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_RTCRST,
@@ -186,33 +335,45 @@ static int __devinit mc13783_rtc_probe(struct platform_device *pdev)
if (ret)
goto err_reset_irq_request;
+ ret = mc13783_irq_status(priv->mc13783, MC13783_IRQ_RTCRST,
+ NULL, &rtcrst_pending);
+ if (ret)
+ goto err_reset_irq_status;
+
+ priv->valid = !rtcrst_pending;
+
ret = mc13783_irq_request_nounmask(priv->mc13783, MC13783_IRQ_1HZ,
mc13783_rtc_update_handler, DRIVER_NAME, priv);
if (ret)
goto err_update_irq_request;
- mc13783_unlock(priv->mc13783);
+ ret = mc13783_irq_request_nounmask(priv->mc13783, MC13783_IRQ_TODA,
+ mc13783_rtc_alarm_handler, DRIVER_NAME, priv);
+ if (ret)
+ goto err_alarm_irq_request;
priv->rtc = rtc_device_register(pdev->name,
&pdev->dev, &mc13783_rtc_ops, THIS_MODULE);
-
if (IS_ERR(priv->rtc)) {
ret = PTR_ERR(priv->rtc);
- mc13783_lock(priv->mc13783);
+ mc13783_irq_free(priv->mc13783, MC13783_IRQ_TODA, priv);
+err_alarm_irq_request:
mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv);
err_update_irq_request:
+err_reset_irq_status:
+
mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv);
err_reset_irq_request:
- mc13783_unlock(priv->mc13783);
-
platform_set_drvdata(pdev, NULL);
kfree(priv);
}
+ mc13783_unlock(priv->mc13783);
+
return ret;
}
@@ -220,10 +381,11 @@ static int __devexit mc13783_rtc_remove(struct platform_device *pdev)
{
struct mc13783_rtc *priv = platform_get_drvdata(pdev);
- rtc_device_unregister(priv->rtc);
-
mc13783_lock(priv->mc13783);
+ rtc_device_unregister(priv->rtc);
+
+ mc13783_irq_free(priv->mc13783, MC13783_IRQ_TODA, priv);
mc13783_irq_free(priv->mc13783, MC13783_IRQ_1HZ, priv);
mc13783_irq_free(priv->mc13783, MC13783_IRQ_RTCRST, priv);
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c
index 6bd5072d4eb..8710f9415d9 100644
--- a/drivers/rtc/rtc-mxc.c
+++ b/drivers/rtc/rtc-mxc.c
@@ -396,8 +396,11 @@ static int __init mxc_rtc_probe(struct platform_device *pdev)
pdata->ioaddr = ioremap(res->start, resource_size(res));
clk = clk_get(&pdev->dev, "ckil");
- if (IS_ERR(clk))
- return PTR_ERR(clk);
+ if (IS_ERR(clk)) {
+ iounmap(pdata->ioaddr);
+ ret = PTR_ERR(clk);
+ goto exit_free_pdata;
+ }
rate = clk_get_rate(clk);
clk_put(clk);
diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c
index e75df9d50e2..2ceb365533b 100644
--- a/drivers/rtc/rtc-pcf2123.c
+++ b/drivers/rtc/rtc-pcf2123.c
@@ -315,7 +315,7 @@ kfree_exit:
return ret;
}
-static int pcf2123_remove(struct spi_device *spi)
+static int __devexit pcf2123_remove(struct spi_device *spi)
{
struct pcf2123_plat_data *pdata = spi->dev.platform_data;
int i;
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
index c6a83a2a722..ed1b8682812 100644
--- a/drivers/rtc/rtc-twl.c
+++ b/drivers/rtc/rtc-twl.c
@@ -57,7 +57,7 @@ enum {
REG_RTC_COMP_LSB_REG,
REG_RTC_COMP_MSB_REG,
};
-const static u8 twl4030_rtc_reg_map[] = {
+static const u8 twl4030_rtc_reg_map[] = {
[REG_SECONDS_REG] = 0x00,
[REG_MINUTES_REG] = 0x01,
[REG_HOURS_REG] = 0x02,
@@ -80,7 +80,7 @@ const static u8 twl4030_rtc_reg_map[] = {
[REG_RTC_COMP_LSB_REG] = 0x10,
[REG_RTC_COMP_MSB_REG] = 0x11,
};
-const static u8 twl6030_rtc_reg_map[] = {
+static const u8 twl6030_rtc_reg_map[] = {
[REG_SECONDS_REG] = 0x00,
[REG_MINUTES_REG] = 0x01,
[REG_HOURS_REG] = 0x02,
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c
index f1e440521c5..3d0dc76b38a 100644
--- a/drivers/rtc/rtc-wm8350.c
+++ b/drivers/rtc/rtc-wm8350.c
@@ -307,11 +307,18 @@ static int wm8350_rtc_update_irq_enable(struct device *dev,
{
struct wm8350 *wm8350 = dev_get_drvdata(dev);
+ /* Suppress duplicate changes since genirq nests enable and
+ * disable calls. */
+ if (enabled == wm8350->rtc.update_enabled)
+ return 0;
+
if (enabled)
wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC);
else
wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC);
+ wm8350->rtc.update_enabled = enabled;
+
return 0;
}
@@ -478,8 +485,8 @@ static int __devexit wm8350_rtc_remove(struct platform_device *pdev)
struct wm8350 *wm8350 = platform_get_drvdata(pdev);
struct wm8350_rtc *wm_rtc = &wm8350->rtc;
- wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC);
- wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM);
+ wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC, wm8350);
+ wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM, wm8350);
rtc_device_unregister(wm_rtc->rtc);
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 4951aa82e9f..bbea90baf98 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -26,6 +26,7 @@
#include <asm/ebcdic.h>
#include <asm/idals.h>
#include <asm/itcw.h>
+#include <asm/diag.h>
/* This is ugly... */
#define PRINTK_HEADER "dasd:"
@@ -2212,6 +2213,13 @@ static int dasd_open(struct block_device *bdev, fmode_t mode)
goto out;
}
+ if ((mode & FMODE_WRITE) &&
+ (test_bit(DASD_FLAG_DEVICE_RO, &base->flags) ||
+ (base->features & DASD_FEATURE_READONLY))) {
+ rc = -EROFS;
+ goto out;
+ }
+
return 0;
out:
@@ -2289,6 +2297,34 @@ dasd_exit(void)
* SECTION: common functions for ccw_driver use
*/
+/*
+ * Is the device read-only?
+ * Note that this function does not report the setting of the
+ * readonly device attribute, but how it is configured in z/VM.
+ */
+int dasd_device_is_ro(struct dasd_device *device)
+{
+ struct ccw_dev_id dev_id;
+ struct diag210 diag_data;
+ int rc;
+
+ if (!MACHINE_IS_VM)
+ return 0;
+ ccw_device_get_id(device->cdev, &dev_id);
+ memset(&diag_data, 0, sizeof(diag_data));
+ diag_data.vrdcdvno = dev_id.devno;
+ diag_data.vrdclen = sizeof(diag_data);
+ rc = diag210(&diag_data);
+ if (rc == 0 || rc == 2) {
+ return diag_data.vrdcvfla & 0x80;
+ } else {
+ DBF_EVENT(DBF_WARNING, "diag210 failed for dev=%04x with rc=%d",
+ dev_id.devno, rc);
+ return 0;
+ }
+}
+EXPORT_SYMBOL_GPL(dasd_device_is_ro);
+
static void dasd_generic_auto_online(void *data, async_cookie_t cookie)
{
struct ccw_device *cdev = data;
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c
index 44796ba4eb9..51224f76b98 100644
--- a/drivers/s390/block/dasd_3990_erp.c
+++ b/drivers/s390/block/dasd_3990_erp.c
@@ -1045,6 +1045,10 @@ dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense)
erp->retries = 5;
+ } else if (sense[1] & SNS1_WRITE_INHIBITED) {
+ dev_err(&device->cdev->dev, "An I/O request was rejected"
+ " because writing is inhibited\n");
+ erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
} else {
/* fatal error - set status to FAILED
internal error 09 - Command Reject */
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index d49766f3b94..8e23919c870 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -742,6 +742,7 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dasd_devmap *devmap;
+ struct dasd_device *device;
int val;
char *endp;
@@ -758,12 +759,14 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr,
devmap->features |= DASD_FEATURE_READONLY;
else
devmap->features &= ~DASD_FEATURE_READONLY;
- if (devmap->device)
- devmap->device->features = devmap->features;
- if (devmap->device && devmap->device->block
- && devmap->device->block->gdp)
- set_disk_ro(devmap->device->block->gdp, val);
+ device = devmap->device;
+ if (device) {
+ device->features = devmap->features;
+ val = val || test_bit(DASD_FLAG_DEVICE_RO, &device->flags);
+ }
spin_unlock(&dasd_devmap_lock);
+ if (device && device->block && device->block->gdp)
+ set_disk_ro(device->block->gdp, val);
return count;
}
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 6e14863f5c7..687f323cdc3 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -145,12 +145,10 @@ dasd_diag_erp(struct dasd_device *device)
mdsk_term_io(device);
rc = mdsk_init_io(device, device->block->bp_block, 0, NULL);
if (rc == 4) {
- if (!(device->features & DASD_FEATURE_READONLY)) {
+ if (!(test_and_set_bit(DASD_FLAG_DEVICE_RO, &device->flags)))
pr_warning("%s: The access mode of a DIAG device "
"changed to read-only\n",
dev_name(&device->cdev->dev));
- device->features |= DASD_FEATURE_READONLY;
- }
rc = 0;
}
if (rc)
@@ -449,7 +447,7 @@ dasd_diag_check_device(struct dasd_device *device)
rc = -EIO;
} else {
if (rc == 4)
- device->features |= DASD_FEATURE_READONLY;
+ set_bit(DASD_FLAG_DEVICE_RO, &device->flags);
pr_info("%s: New DASD with %ld byte/block, total size %ld "
"KB%s\n", dev_name(&device->cdev->dev),
(unsigned long) block->bp_block,
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 1cca21aafab..01f4e7a34aa 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -1089,6 +1089,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
struct dasd_eckd_private *private;
struct dasd_block *block;
int is_known, rc;
+ int readonly;
if (!ccw_device_is_pathgroup(device->cdev)) {
dev_warn(&device->cdev->dev,
@@ -1182,15 +1183,20 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
else
private->real_cyl = private->rdc_data.no_cyl;
+ readonly = dasd_device_is_ro(device);
+ if (readonly)
+ set_bit(DASD_FLAG_DEVICE_RO, &device->flags);
+
dev_info(&device->cdev->dev, "New DASD %04X/%02X (CU %04X/%02X) "
- "with %d cylinders, %d heads, %d sectors\n",
+ "with %d cylinders, %d heads, %d sectors%s\n",
private->rdc_data.dev_type,
private->rdc_data.dev_model,
private->rdc_data.cu_type,
private->rdc_data.cu_model.model,
private->real_cyl,
private->rdc_data.trk_per_cyl,
- private->rdc_data.sec_per_trk);
+ private->rdc_data.sec_per_trk,
+ readonly ? ", read-only device" : "");
return 0;
out_err3:
@@ -2839,8 +2845,13 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp)
char *psf_data, *rssd_result;
struct dasd_ccw_req *cqr;
struct ccw1 *ccw;
+ char psf0, psf1;
int rc;
+ if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
+ return -EACCES;
+ psf0 = psf1 = 0;
+
/* Copy parms from caller */
rc = -EFAULT;
if (copy_from_user(&usrparm, argp, sizeof(usrparm)))
@@ -2869,12 +2880,8 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp)
(void __user *)(unsigned long) usrparm.psf_data,
usrparm.psf_data_len))
goto out_free;
-
- /* sanity check on syscall header */
- if (psf_data[0] != 0x17 && psf_data[1] != 0xce) {
- rc = -EINVAL;
- goto out_free;
- }
+ psf0 = psf_data[0];
+ psf1 = psf_data[1];
/* setup CCWs for PSF + RSSD */
cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 2 , 0, device);
@@ -2925,7 +2932,9 @@ out_free:
kfree(rssd_result);
kfree(psf_data);
out:
- DBF_DEV_EVENT(DBF_WARNING, device, "Symmetrix ioctl: rc=%d", rc);
+ DBF_DEV_EVENT(DBF_WARNING, device,
+ "Symmetrix ioctl (0x%02x 0x%02x): rc=%d",
+ (int) psf0, (int) psf1, rc);
return rc;
}
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index 0f152444ac7..37282b90eec 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -124,6 +124,7 @@ dasd_fba_check_characteristics(struct dasd_device *device)
struct dasd_fba_private *private;
struct ccw_device *cdev = device->cdev;
int rc;
+ int readonly;
private = (struct dasd_fba_private *) device->private;
if (!private) {
@@ -162,16 +163,21 @@ dasd_fba_check_characteristics(struct dasd_device *device)
return rc;
}
+ readonly = dasd_device_is_ro(device);
+ if (readonly)
+ set_bit(DASD_FLAG_DEVICE_RO, &device->flags);
+
dev_info(&device->cdev->dev,
"New FBA DASD %04X/%02X (CU %04X/%02X) with %d MB "
- "and %d B/blk\n",
+ "and %d B/blk%s\n",
cdev->id.dev_type,
cdev->id.dev_model,
cdev->id.cu_type,
cdev->id.cu_model,
((private->rdc_data.blk_bdsa *
(private->rdc_data.blk_size >> 9)) >> 11),
- private->rdc_data.blk_size);
+ private->rdc_data.blk_size,
+ readonly ? ", read-only device" : "");
return 0;
}
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index 94f92a1247f..30a1ca3d08b 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -70,7 +70,8 @@ int dasd_gendisk_alloc(struct dasd_block *block)
}
len += sprintf(gdp->disk_name + len, "%c", 'a'+(base->devindex%26));
- if (block->base->features & DASD_FEATURE_READONLY)
+ if (base->features & DASD_FEATURE_READONLY ||
+ test_bit(DASD_FLAG_DEVICE_RO, &base->flags))
set_disk_ro(gdp, 1);
gdp->private_data = block;
gdp->queue = block->request_queue;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index ed73ce55082..a91d4a97d4f 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -436,6 +436,10 @@ struct dasd_block {
#define DASD_FLAG_OFFLINE 3 /* device is in offline processing */
#define DASD_FLAG_EER_SNSS 4 /* A SNSS is required */
#define DASD_FLAG_EER_IN_USE 5 /* A SNSS request is running */
+#define DASD_FLAG_DEVICE_RO 6 /* The device itself is read-only. Don't
+ * confuse this with the user specified
+ * read-only feature.
+ */
void dasd_put_device_wake(struct dasd_device *);
@@ -609,6 +613,9 @@ char *dasd_get_sense(struct irb *);
void dasd_device_set_stop_bits(struct dasd_device *, int);
void dasd_device_remove_stop_bits(struct dasd_device *, int);
+int dasd_device_is_ro(struct dasd_device *);
+
+
/* externals in dasd_devmap.c */
extern int dasd_max_devindex;
extern int dasd_probeonly;
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 7039d9cf0fb..3479f8158a1 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -199,7 +199,8 @@ dasd_ioctl_format(struct block_device *bdev, void __user *argp)
if (!argp)
return -EINVAL;
- if (block->base->features & DASD_FEATURE_READONLY)
+ if (block->base->features & DASD_FEATURE_READONLY ||
+ test_bit(DASD_FLAG_DEVICE_RO, &block->base->flags))
return -EROFS;
if (copy_from_user(&fdata, argp, sizeof(struct format_data_t)))
return -EFAULT;
@@ -349,7 +350,8 @@ dasd_ioctl_set_ro(struct block_device *bdev, void __user *argp)
return -EINVAL;
if (get_user(intval, (int __user *)argp))
return -EFAULT;
-
+ if (!intval && test_bit(DASD_FLAG_DEVICE_RO, &block->base->flags))
+ return -EROFS;
set_disk_ro(bdev->bd_disk, intval);
return dasd_set_feature(block->base->cdev, DASD_FEATURE_READONLY, intval);
}
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index c6abb75c461..6d229f3523a 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -764,7 +764,7 @@ static void sch_create_and_recog_new_device(struct subchannel *sch)
static void io_subchannel_register(struct ccw_device *cdev)
{
struct subchannel *sch;
- int ret;
+ int ret, adjust_init_count = 1;
unsigned long flags;
sch = to_subchannel(cdev->dev.parent);
@@ -793,6 +793,7 @@ static void io_subchannel_register(struct ccw_device *cdev)
cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
}
+ adjust_init_count = 0;
goto out;
}
/*
@@ -818,7 +819,7 @@ out:
cdev->private->flags.recog_done = 1;
wake_up(&cdev->private->wait_q);
out_err:
- if (atomic_dec_and_test(&ccw_device_init_count))
+ if (adjust_init_count && atomic_dec_and_test(&ccw_device_init_count))
wake_up(&ccw_device_init_wq);
}
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c
index c94eb2a0fa2..6ce83f56d53 100644
--- a/drivers/s390/cio/qdio_debug.c
+++ b/drivers/s390/cio/qdio_debug.c
@@ -33,7 +33,6 @@ void qdio_allocate_dbf(struct qdio_initialize *init_data,
DBF_HEX(&init_data->input_handler, sizeof(void *));
DBF_HEX(&init_data->output_handler, sizeof(void *));
DBF_HEX(&init_data->int_parm, sizeof(long));
- DBF_HEX(&init_data->flags, sizeof(long));
DBF_HEX(&init_data->input_sbal_addr_array, sizeof(void *));
DBF_HEX(&init_data->output_sbal_addr_array, sizeof(void *));
DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr);
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c
index 232ef047ba3..4f8f7431177 100644
--- a/drivers/s390/cio/qdio_main.c
+++ b/drivers/s390/cio/qdio_main.c
@@ -588,10 +588,11 @@ static void qdio_kick_handler(struct qdio_q *q)
if (q->is_input_q) {
qperf_inc(q, inbound_handler);
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%02x c:%02x", start, count);
- } else
+ } else {
qperf_inc(q, outbound_handler);
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: s:%02x c:%02x",
start, count);
+ }
q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count,
q->irq_ptr->int_parm);
diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index cb909a5b504..977bb4d4ed1 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -43,6 +43,16 @@ config SMSGIUCV
Select this option if you want to be able to receive SMSG messages
from other VM guest systems.
+config SMSGIUCV_EVENT
+ tristate "Deliver IUCV special messages as uevents (VM only)"
+ depends on SMSGIUCV
+ help
+ Select this option to deliver CP special messages (SMSGs) as
+ uevents. The driver handles only those special messages that
+ start with "APP".
+
+ To compile as a module, choose M. The module name is "smsgiucv_app".
+
config CLAW
tristate "CLAW device support"
depends on CCW && NETDEVICES
diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile
index 6cab5a62f99..4dfe8c1092d 100644
--- a/drivers/s390/net/Makefile
+++ b/drivers/s390/net/Makefile
@@ -6,6 +6,7 @@ ctcm-y += ctcm_main.o ctcm_fsms.o ctcm_mpc.o ctcm_sysfs.o ctcm_dbug.o
obj-$(CONFIG_CTCM) += ctcm.o fsm.o
obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
+obj-$(CONFIG_SMSGIUCV_EVENT) += smsgiucv_app.o
obj-$(CONFIG_LCS) += lcs.o
obj-$(CONFIG_CLAW) += claw.o
qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index fa8a519218a..7d25bdd443c 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -3805,9 +3805,6 @@ static int qeth_qdio_establish(struct qeth_card *card)
init_data.input_handler = card->discipline.input_handler;
init_data.output_handler = card->discipline.output_handler;
init_data.int_parm = (unsigned long) card;
- init_data.flags = QDIO_INBOUND_0COPY_SBALS |
- QDIO_OUTBOUND_0COPY_SBALS |
- QDIO_USE_OUTBOUND_PCIS;
init_data.input_sbal_addr_array = (void **) in_sbal_ptrs;
init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c
index 67f2485d237..ecef1edee70 100644
--- a/drivers/s390/net/smsgiucv.c
+++ b/drivers/s390/net/smsgiucv.c
@@ -31,9 +31,9 @@
struct smsg_callback {
struct list_head list;
- char *prefix;
+ const char *prefix;
int len;
- void (*callback)(char *from, char *str);
+ void (*callback)(const char *from, char *str);
};
MODULE_AUTHOR
@@ -100,8 +100,8 @@ static void smsg_message_pending(struct iucv_path *path,
kfree(buffer);
}
-int smsg_register_callback(char *prefix,
- void (*callback)(char *from, char *str))
+int smsg_register_callback(const char *prefix,
+ void (*callback)(const char *from, char *str))
{
struct smsg_callback *cb;
@@ -117,8 +117,9 @@ int smsg_register_callback(char *prefix,
return 0;
}
-void smsg_unregister_callback(char *prefix,
- void (*callback)(char *from, char *str))
+void smsg_unregister_callback(const char *prefix,
+ void (*callback)(const char *from,
+ char *str))
{
struct smsg_callback *cb, *tmp;
@@ -176,7 +177,7 @@ static const struct dev_pm_ops smsg_pm_ops = {
static struct device_driver smsg_driver = {
.owner = THIS_MODULE,
- .name = "SMSGIUCV",
+ .name = SMSGIUCV_DRV_NAME,
.bus = &iucv_bus,
.pm = &smsg_pm_ops,
};
diff --git a/drivers/s390/net/smsgiucv.h b/drivers/s390/net/smsgiucv.h
index 67f5d4f8378..149a1151608 100644
--- a/drivers/s390/net/smsgiucv.h
+++ b/drivers/s390/net/smsgiucv.h
@@ -5,6 +5,10 @@
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
*/
-int smsg_register_callback(char *, void (*)(char *, char *));
-void smsg_unregister_callback(char *, void (*)(char *, char *));
+#define SMSGIUCV_DRV_NAME "SMSGIUCV"
+
+int smsg_register_callback(const char *,
+ void (*)(const char *, char *));
+void smsg_unregister_callback(const char *,
+ void (*)(const char *, char *));
diff --git a/drivers/s390/net/smsgiucv_app.c b/drivers/s390/net/smsgiucv_app.c
new file mode 100644
index 00000000000..91579dc6a2b
--- /dev/null
+++ b/drivers/s390/net/smsgiucv_app.c
@@ -0,0 +1,211 @@
+/*
+ * Deliver z/VM CP special messages (SMSG) as uevents.
+ *
+ * The driver registers for z/VM CP special messages with the
+ * "APP" prefix. Incoming messages are delivered to user space
+ * as uevents.
+ *
+ * Copyright IBM Corp. 2010
+ * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
+ *
+ */
+#define KMSG_COMPONENT "smsgiucv_app"
+#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
+
+#include <linux/ctype.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <net/iucv/iucv.h>
+#include "smsgiucv.h"
+
+/* prefix used for SMSG registration */
+#define SMSG_PREFIX "APP"
+
+/* SMSG related uevent environment variables */
+#define ENV_SENDER_STR "SMSG_SENDER="
+#define ENV_SENDER_LEN (strlen(ENV_SENDER_STR) + 8 + 1)
+#define ENV_PREFIX_STR "SMSG_ID="
+#define ENV_PREFIX_LEN (strlen(ENV_PREFIX_STR) + \
+ strlen(SMSG_PREFIX) + 1)
+#define ENV_TEXT_STR "SMSG_TEXT="
+#define ENV_TEXT_LEN(msg) (strlen(ENV_TEXT_STR) + strlen((msg)) + 1)
+
+/* z/VM user ID which is permitted to send SMSGs
+ * If the value is undefined or empty (""), special messages are
+ * accepted from any z/VM user ID. */
+static char *sender;
+module_param(sender, charp, 0400);
+MODULE_PARM_DESC(sender, "z/VM user ID from which CP SMSGs are accepted");
+
+/* SMSG device representation */
+static struct device *smsg_app_dev;
+
+/* list element for queuing received messages for delivery */
+struct smsg_app_event {
+ struct list_head list;
+ char *buf;
+ char *envp[4];
+};
+
+/* queue for outgoing uevents */
+static LIST_HEAD(smsg_event_queue);
+static DEFINE_SPINLOCK(smsg_event_queue_lock);
+
+static void smsg_app_event_free(struct smsg_app_event *ev)
+{
+ kfree(ev->buf);
+ kfree(ev);
+}
+
+static struct smsg_app_event *smsg_app_event_alloc(const char *from,
+ const char *msg)
+{
+ struct smsg_app_event *ev;
+
+ ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
+ if (!ev)
+ return NULL;
+
+ ev->buf = kzalloc(ENV_SENDER_LEN + ENV_PREFIX_LEN +
+ ENV_TEXT_LEN(msg), GFP_ATOMIC);
+ if (!ev->buf) {
+ kfree(ev);
+ return NULL;
+ }
+
+ /* setting up environment pointers into buf */
+ ev->envp[0] = ev->buf;
+ ev->envp[1] = ev->envp[0] + ENV_SENDER_LEN;
+ ev->envp[2] = ev->envp[1] + ENV_PREFIX_LEN;
+ ev->envp[3] = NULL;
+
+ /* setting up environment: sender, prefix name, and message text */
+ snprintf(ev->envp[0], ENV_SENDER_LEN, ENV_SENDER_STR "%s", from);
+ snprintf(ev->envp[1], ENV_PREFIX_LEN, ENV_PREFIX_STR "%s", SMSG_PREFIX);
+ snprintf(ev->envp[2], ENV_TEXT_LEN(msg), ENV_TEXT_STR "%s", msg);
+
+ return ev;
+}
+
+static void smsg_event_work_fn(struct work_struct *work)
+{
+ LIST_HEAD(event_queue);
+ struct smsg_app_event *p, *n;
+ struct device *dev;
+
+ dev = get_device(smsg_app_dev);
+ if (!dev)
+ return;
+
+ spin_lock_bh(&smsg_event_queue_lock);
+ list_splice_init(&smsg_event_queue, &event_queue);
+ spin_unlock_bh(&smsg_event_queue_lock);
+
+ list_for_each_entry_safe(p, n, &event_queue, list) {
+ list_del(&p->list);
+ kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, p->envp);
+ smsg_app_event_free(p);
+ }
+
+ put_device(dev);
+}
+static DECLARE_WORK(smsg_event_work, smsg_event_work_fn);
+
+static void smsg_app_callback(const char *from, char *msg)
+{
+ struct smsg_app_event *se;
+
+ /* check if the originating z/VM user ID matches
+ * the configured sender. */
+ if (sender && strlen(sender) > 0 && strcmp(from, sender) != 0)
+ return;
+
+ /* get start of message text (skip prefix and leading blanks) */
+ msg += strlen(SMSG_PREFIX);
+ while (*msg && isspace(*msg))
+ msg++;
+ if (*msg == '\0')
+ return;
+
+ /* allocate event list element and its environment */
+ se = smsg_app_event_alloc(from, msg);
+ if (!se)
+ return;
+
+ /* queue event and schedule work function */
+ spin_lock(&smsg_event_queue_lock);
+ list_add_tail(&se->list, &smsg_event_queue);
+ spin_unlock(&smsg_event_queue_lock);
+
+ schedule_work(&smsg_event_work);
+ return;
+}
+
+static int __init smsgiucv_app_init(void)
+{
+ struct device_driver *smsgiucv_drv;
+ int rc;
+
+ if (!MACHINE_IS_VM)
+ return -ENODEV;
+
+ smsg_app_dev = kzalloc(sizeof(*smsg_app_dev), GFP_KERNEL);
+ if (!smsg_app_dev)
+ return -ENOMEM;
+
+ smsgiucv_drv = driver_find(SMSGIUCV_DRV_NAME, &iucv_bus);
+ if (!smsgiucv_drv) {
+ kfree(smsg_app_dev);
+ return -ENODEV;
+ }
+
+ rc = dev_set_name(smsg_app_dev, KMSG_COMPONENT);
+ if (rc) {
+ kfree(smsg_app_dev);
+ goto fail_put_driver;
+ }
+ smsg_app_dev->bus = &iucv_bus;
+ smsg_app_dev->parent = iucv_root;
+ smsg_app_dev->release = (void (*)(struct device *)) kfree;
+ smsg_app_dev->driver = smsgiucv_drv;
+ rc = device_register(smsg_app_dev);
+ if (rc) {
+ put_device(smsg_app_dev);
+ goto fail_put_driver;
+ }
+
+ /* register with the smsgiucv device driver */
+ rc = smsg_register_callback(SMSG_PREFIX, smsg_app_callback);
+ if (rc) {
+ device_unregister(smsg_app_dev);
+ goto fail_put_driver;
+ }
+
+ rc = 0;
+fail_put_driver:
+ put_driver(smsgiucv_drv);
+ return rc;
+}
+module_init(smsgiucv_app_init);
+
+static void __exit smsgiucv_app_exit(void)
+{
+ /* unregister callback */
+ smsg_unregister_callback(SMSG_PREFIX, smsg_app_callback);
+
+ /* cancel pending work and flush any queued event work */
+ cancel_work_sync(&smsg_event_work);
+ smsg_event_work_fn(&smsg_event_work);
+
+ device_unregister(smsg_app_dev);
+}
+module_exit(smsgiucv_app_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Deliver z/VM CP SMSG as uevents");
+MODULE_AUTHOR("Hendrik Brueckner <brueckner@linux.vnet.ibm.com>");
diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c
index 71b97ff77cf..6479273a309 100644
--- a/drivers/s390/scsi/zfcp_qdio.c
+++ b/drivers/s390/scsi/zfcp_qdio.c
@@ -319,8 +319,6 @@ static void zfcp_qdio_setup_init_data(struct qdio_initialize *id,
id->input_handler = zfcp_qdio_int_resp;
id->output_handler = zfcp_qdio_int_req;
id->int_parm = (unsigned long) qdio;
- id->flags = QDIO_INBOUND_0COPY_SBALS |
- QDIO_OUTBOUND_0COPY_SBALS | QDIO_USE_OUTBOUND_PCIS;
id->input_sbal_addr_array = (void **) (qdio->resp_q.sbal);
id->output_sbal_addr_array = (void **) (qdio->req_q.sbal);
diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c
index 0807b260268..fef0e3c75b1 100644
--- a/drivers/scsi/sgiwd93.c
+++ b/drivers/scsi/sgiwd93.c
@@ -226,7 +226,7 @@ static struct scsi_host_template sgiwd93_template = {
.use_clustering = DISABLE_CLUSTERING,
};
-static int __init sgiwd93_probe(struct platform_device *pdev)
+static int __devinit sgiwd93_probe(struct platform_device *pdev)
{
struct sgiwd93_platform_data *pd = pdev->dev.platform_data;
unsigned char *wdregs = pd->wdregs;
diff --git a/drivers/scsi/sni_53c710.c b/drivers/scsi/sni_53c710.c
index 37b3359e863..56cf0bb4ed1 100644
--- a/drivers/scsi/sni_53c710.c
+++ b/drivers/scsi/sni_53c710.c
@@ -64,7 +64,7 @@ static struct scsi_host_template snirm710_template = {
.module = THIS_MODULE,
};
-static int __init snirm710_probe(struct platform_device *dev)
+static int __devinit snirm710_probe(struct platform_device *dev)
{
unsigned long base;
struct NCR_700_Host_Parameters *hostdata;
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 746e07033dc..d6ff7339562 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -1009,6 +1009,10 @@ config SERIAL_SH_SCI_CONSOLE
depends on SERIAL_SH_SCI=y
select SERIAL_CORE_CONSOLE
+config SERIAL_SH_SCI_DMA
+ bool "DMA support"
+ depends on SERIAL_SH_SCI && SH_DMAE && EXPERIMENTAL
+
config SERIAL_PNX8XXX
bool "Enable PNX8XXX SoCs' UART Support"
depends on MIPS && (SOC_PNX8550 || SOC_PNX833X)
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c
index 42f3333c4ad..980f39449ee 100644
--- a/drivers/serial/sh-sci.c
+++ b/drivers/serial/sh-sci.c
@@ -48,6 +48,9 @@
#include <linux/ctype.h>
#include <linux/err.h>
#include <linux/list.h>
+#include <linux/dmaengine.h>
+#include <linux/scatterlist.h>
+#include <linux/timer.h>
#ifdef CONFIG_SUPERH
#include <asm/sh_bios.h>
@@ -84,6 +87,27 @@ struct sci_port {
struct clk *dclk;
struct list_head node;
+ struct dma_chan *chan_tx;
+ struct dma_chan *chan_rx;
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+ struct device *dma_dev;
+ enum sh_dmae_slave_chan_id slave_tx;
+ enum sh_dmae_slave_chan_id slave_rx;
+ struct dma_async_tx_descriptor *desc_tx;
+ struct dma_async_tx_descriptor *desc_rx[2];
+ dma_cookie_t cookie_tx;
+ dma_cookie_t cookie_rx[2];
+ dma_cookie_t active_rx;
+ struct scatterlist sg_tx;
+ unsigned int sg_len_tx;
+ struct scatterlist sg_rx[2];
+ size_t buf_len_rx;
+ struct sh_dmae_slave param_tx;
+ struct sh_dmae_slave param_rx;
+ struct work_struct work_tx;
+ struct work_struct work_rx;
+ struct timer_list rx_timer;
+#endif
};
struct sh_sci_priv {
@@ -269,29 +293,44 @@ static inline void sci_init_pins(struct uart_port *port, unsigned int cflag)
defined(CONFIG_CPU_SUBTYPE_SH7780) || \
defined(CONFIG_CPU_SUBTYPE_SH7785) || \
defined(CONFIG_CPU_SUBTYPE_SH7786)
-static inline int scif_txroom(struct uart_port *port)
+static int scif_txfill(struct uart_port *port)
{
- return SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0xff);
+ return sci_in(port, SCTFDR) & 0xff;
}
-static inline int scif_rxroom(struct uart_port *port)
+static int scif_txroom(struct uart_port *port)
+{
+ return SCIF_TXROOM_MAX - scif_txfill(port);
+}
+
+static int scif_rxfill(struct uart_port *port)
{
return sci_in(port, SCRFDR) & 0xff;
}
#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
-static inline int scif_txroom(struct uart_port *port)
+static int scif_txfill(struct uart_port *port)
{
- if ((port->mapbase == 0xffe00000) ||
- (port->mapbase == 0xffe08000)) {
+ if (port->mapbase == 0xffe00000 ||
+ port->mapbase == 0xffe08000)
/* SCIF0/1*/
- return SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0xff);
- } else {
+ return sci_in(port, SCTFDR) & 0xff;
+ else
/* SCIF2 */
- return SCIF2_TXROOM_MAX - (sci_in(port, SCFDR) >> 8);
- }
+ return sci_in(port, SCFDR) >> 8;
}
-static inline int scif_rxroom(struct uart_port *port)
+static int scif_txroom(struct uart_port *port)
+{
+ if (port->mapbase == 0xffe00000 ||
+ port->mapbase == 0xffe08000)
+ /* SCIF0/1*/
+ return SCIF_TXROOM_MAX - scif_txfill(port);
+ else
+ /* SCIF2 */
+ return SCIF2_TXROOM_MAX - scif_txfill(port);
+}
+
+static int scif_rxfill(struct uart_port *port)
{
if ((port->mapbase == 0xffe00000) ||
(port->mapbase == 0xffe08000)) {
@@ -303,23 +342,33 @@ static inline int scif_rxroom(struct uart_port *port)
}
}
#else
-static inline int scif_txroom(struct uart_port *port)
+static int scif_txfill(struct uart_port *port)
+{
+ return sci_in(port, SCFDR) >> 8;
+}
+
+static int scif_txroom(struct uart_port *port)
{
- return SCIF_TXROOM_MAX - (sci_in(port, SCFDR) >> 8);
+ return SCIF_TXROOM_MAX - scif_txfill(port);
}
-static inline int scif_rxroom(struct uart_port *port)
+static int scif_rxfill(struct uart_port *port)
{
return sci_in(port, SCFDR) & SCIF_RFDC_MASK;
}
#endif
-static inline int sci_txroom(struct uart_port *port)
+static int sci_txfill(struct uart_port *port)
{
- return (sci_in(port, SCxSR) & SCI_TDRE) != 0;
+ return !(sci_in(port, SCxSR) & SCI_TDRE);
}
-static inline int sci_rxroom(struct uart_port *port)
+static int sci_txroom(struct uart_port *port)
+{
+ return !sci_txfill(port);
+}
+
+static int sci_rxfill(struct uart_port *port)
{
return (sci_in(port, SCxSR) & SCxSR_RDxF(port)) != 0;
}
@@ -406,9 +455,9 @@ static inline void sci_receive_chars(struct uart_port *port)
while (1) {
if (port->type == PORT_SCI)
- count = sci_rxroom(port);
+ count = sci_rxfill(port);
else
- count = scif_rxroom(port);
+ count = scif_rxfill(port);
/* Don't copy more bytes than there is room for in the buffer */
count = tty_buffer_request_room(tty, count);
@@ -453,10 +502,10 @@ static inline void sci_receive_chars(struct uart_port *port)
}
/* Store data and status */
- if (status&SCxSR_FER(port)) {
+ if (status & SCxSR_FER(port)) {
flag = TTY_FRAME;
dev_notice(port->dev, "frame error\n");
- } else if (status&SCxSR_PER(port)) {
+ } else if (status & SCxSR_PER(port)) {
flag = TTY_PARITY;
dev_notice(port->dev, "parity error\n");
} else
@@ -618,13 +667,39 @@ static inline int sci_handle_breaks(struct uart_port *port)
return copied;
}
-static irqreturn_t sci_rx_interrupt(int irq, void *port)
+static irqreturn_t sci_rx_interrupt(int irq, void *ptr)
{
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+ struct uart_port *port = ptr;
+ struct sci_port *s = to_sci_port(port);
+
+ if (s->chan_rx) {
+ unsigned long tout;
+ u16 scr = sci_in(port, SCSCR);
+ u16 ssr = sci_in(port, SCxSR);
+
+ /* Disable future Rx interrupts */
+ sci_out(port, SCSCR, scr & ~SCI_CTRL_FLAGS_RIE);
+ /* Clear current interrupt */
+ sci_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port)));
+ /* Calculate delay for 1.5 DMA buffers */
+ tout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 /
+ port->fifosize / 2;
+ dev_dbg(port->dev, "Rx IRQ: setup timeout in %lu ms\n",
+ tout * 1000 / HZ);
+ if (tout < 2)
+ tout = 2;
+ mod_timer(&s->rx_timer, jiffies + tout);
+
+ return IRQ_HANDLED;
+ }
+#endif
+
/* I think sci_receive_chars has to be called irrespective
* of whether the I_IXOFF is set, otherwise, how is the interrupt
* to be disabled?
*/
- sci_receive_chars(port);
+ sci_receive_chars(ptr);
return IRQ_HANDLED;
}
@@ -680,6 +755,7 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
{
unsigned short ssr_status, scr_status, err_enabled;
struct uart_port *port = ptr;
+ struct sci_port *s = to_sci_port(port);
irqreturn_t ret = IRQ_NONE;
ssr_status = sci_in(port, SCxSR);
@@ -687,10 +763,15 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
err_enabled = scr_status & (SCI_CTRL_FLAGS_REIE | SCI_CTRL_FLAGS_RIE);
/* Tx Interrupt */
- if ((ssr_status & SCxSR_TDxE(port)) && (scr_status & SCI_CTRL_FLAGS_TIE))
+ if ((ssr_status & SCxSR_TDxE(port)) && (scr_status & SCI_CTRL_FLAGS_TIE) &&
+ !s->chan_tx)
ret = sci_tx_interrupt(irq, ptr);
- /* Rx Interrupt */
- if ((ssr_status & SCxSR_RDxF(port)) && (scr_status & SCI_CTRL_FLAGS_RIE))
+ /*
+ * Rx Interrupt: if we're using DMA, the DMA controller clears RDF /
+ * DR flags
+ */
+ if (((ssr_status & SCxSR_RDxF(port)) || s->chan_rx) &&
+ (scr_status & SCI_CTRL_FLAGS_RIE))
ret = sci_rx_interrupt(irq, ptr);
/* Error Interrupt */
if ((ssr_status & SCxSR_ERRORS(port)) && err_enabled)
@@ -699,6 +780,10 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
if ((ssr_status & SCxSR_BRK(port)) && err_enabled)
ret = sci_br_interrupt(irq, ptr);
+ WARN_ONCE(ret == IRQ_NONE,
+ "%s: %d IRQ %d, status %x, control %x\n", __func__,
+ irq, port->line, ssr_status, scr_status);
+
return ret;
}
@@ -800,7 +885,9 @@ static void sci_free_irq(struct sci_port *port)
static unsigned int sci_tx_empty(struct uart_port *port)
{
unsigned short status = sci_in(port, SCxSR);
- return status & SCxSR_TEND(port) ? TIOCSER_TEMT : 0;
+ unsigned short in_tx_fifo = scif_txfill(port);
+
+ return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
}
static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
@@ -812,16 +899,297 @@ static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
static unsigned int sci_get_mctrl(struct uart_port *port)
{
- /* This routine is used for geting signals of: DTR, DCD, DSR, RI,
+ /* This routine is used for getting signals of: DTR, DCD, DSR, RI,
and CTS/RTS */
return TIOCM_DTR | TIOCM_RTS | TIOCM_DSR;
}
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+static void sci_dma_tx_complete(void *arg)
+{
+ struct sci_port *s = arg;
+ struct uart_port *port = &s->port;
+ struct circ_buf *xmit = &port->state->xmit;
+ unsigned long flags;
+
+ dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ xmit->tail += s->sg_tx.length;
+ xmit->tail &= UART_XMIT_SIZE - 1;
+
+ port->icount.tx += s->sg_tx.length;
+
+ async_tx_ack(s->desc_tx);
+ s->cookie_tx = -EINVAL;
+ s->desc_tx = NULL;
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ if (uart_circ_chars_pending(xmit))
+ schedule_work(&s->work_tx);
+}
+
+/* Locking: called with port lock held */
+static int sci_dma_rx_push(struct sci_port *s, struct tty_struct *tty,
+ size_t count)
+{
+ struct uart_port *port = &s->port;
+ int i, active, room;
+
+ room = tty_buffer_request_room(tty, count);
+
+ if (s->active_rx == s->cookie_rx[0]) {
+ active = 0;
+ } else if (s->active_rx == s->cookie_rx[1]) {
+ active = 1;
+ } else {
+ dev_err(port->dev, "cookie %d not found!\n", s->active_rx);
+ return 0;
+ }
+
+ if (room < count)
+ dev_warn(port->dev, "Rx overrun: dropping %u bytes\n",
+ count - room);
+ if (!room)
+ return room;
+
+ for (i = 0; i < room; i++)
+ tty_insert_flip_char(tty, ((u8 *)sg_virt(&s->sg_rx[active]))[i],
+ TTY_NORMAL);
+
+ port->icount.rx += room;
+
+ return room;
+}
+
+static void sci_dma_rx_complete(void *arg)
+{
+ struct sci_port *s = arg;
+ struct uart_port *port = &s->port;
+ struct tty_struct *tty = port->state->port.tty;
+ unsigned long flags;
+ int count;
+
+ dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ count = sci_dma_rx_push(s, tty, s->buf_len_rx);
+
+ mod_timer(&s->rx_timer, jiffies + msecs_to_jiffies(5));
+
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ if (count)
+ tty_flip_buffer_push(tty);
+
+ schedule_work(&s->work_rx);
+}
+
+static void sci_start_rx(struct uart_port *port);
+static void sci_start_tx(struct uart_port *port);
+
+static void sci_rx_dma_release(struct sci_port *s, bool enable_pio)
+{
+ struct dma_chan *chan = s->chan_rx;
+ struct uart_port *port = &s->port;
+
+ s->chan_rx = NULL;
+ s->cookie_rx[0] = s->cookie_rx[1] = -EINVAL;
+ dma_release_channel(chan);
+ dma_free_coherent(port->dev, s->buf_len_rx * 2,
+ sg_virt(&s->sg_rx[0]), sg_dma_address(&s->sg_rx[0]));
+ if (enable_pio)
+ sci_start_rx(port);
+}
+
+static void sci_tx_dma_release(struct sci_port *s, bool enable_pio)
+{
+ struct dma_chan *chan = s->chan_tx;
+ struct uart_port *port = &s->port;
+
+ s->chan_tx = NULL;
+ s->cookie_tx = -EINVAL;
+ dma_release_channel(chan);
+ if (enable_pio)
+ sci_start_tx(port);
+}
+
+static void sci_submit_rx(struct sci_port *s)
+{
+ struct dma_chan *chan = s->chan_rx;
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ struct scatterlist *sg = &s->sg_rx[i];
+ struct dma_async_tx_descriptor *desc;
+
+ desc = chan->device->device_prep_slave_sg(chan,
+ sg, 1, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT);
+
+ if (desc) {
+ s->desc_rx[i] = desc;
+ desc->callback = sci_dma_rx_complete;
+ desc->callback_param = s;
+ s->cookie_rx[i] = desc->tx_submit(desc);
+ }
+
+ if (!desc || s->cookie_rx[i] < 0) {
+ if (i) {
+ async_tx_ack(s->desc_rx[0]);
+ s->cookie_rx[0] = -EINVAL;
+ }
+ if (desc) {
+ async_tx_ack(desc);
+ s->cookie_rx[i] = -EINVAL;
+ }
+ dev_warn(s->port.dev,
+ "failed to re-start DMA, using PIO\n");
+ sci_rx_dma_release(s, true);
+ return;
+ }
+ }
+
+ s->active_rx = s->cookie_rx[0];
+
+ dma_async_issue_pending(chan);
+}
+
+static void work_fn_rx(struct work_struct *work)
+{
+ struct sci_port *s = container_of(work, struct sci_port, work_rx);
+ struct uart_port *port = &s->port;
+ struct dma_async_tx_descriptor *desc;
+ int new;
+
+ if (s->active_rx == s->cookie_rx[0]) {
+ new = 0;
+ } else if (s->active_rx == s->cookie_rx[1]) {
+ new = 1;
+ } else {
+ dev_err(port->dev, "cookie %d not found!\n", s->active_rx);
+ return;
+ }
+ desc = s->desc_rx[new];
+
+ if (dma_async_is_tx_complete(s->chan_rx, s->active_rx, NULL, NULL) !=
+ DMA_SUCCESS) {
+ /* Handle incomplete DMA receive */
+ struct tty_struct *tty = port->state->port.tty;
+ struct dma_chan *chan = s->chan_rx;
+ struct sh_desc *sh_desc = container_of(desc, struct sh_desc,
+ async_tx);
+ unsigned long flags;
+ int count;
+
+ chan->device->device_terminate_all(chan);
+ dev_dbg(port->dev, "Read %u bytes with cookie %d\n",
+ sh_desc->partial, sh_desc->cookie);
+
+ spin_lock_irqsave(&port->lock, flags);
+ count = sci_dma_rx_push(s, tty, sh_desc->partial);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ if (count)
+ tty_flip_buffer_push(tty);
+
+ sci_submit_rx(s);
+
+ return;
+ }
+
+ s->cookie_rx[new] = desc->tx_submit(desc);
+ if (s->cookie_rx[new] < 0) {
+ dev_warn(port->dev, "Failed submitting Rx DMA descriptor\n");
+ sci_rx_dma_release(s, true);
+ return;
+ }
+
+ dev_dbg(port->dev, "%s: cookie %d #%d\n", __func__,
+ s->cookie_rx[new], new);
+
+ s->active_rx = s->cookie_rx[!new];
+}
+
+static void work_fn_tx(struct work_struct *work)
+{
+ struct sci_port *s = container_of(work, struct sci_port, work_tx);
+ struct dma_async_tx_descriptor *desc;
+ struct dma_chan *chan = s->chan_tx;
+ struct uart_port *port = &s->port;
+ struct circ_buf *xmit = &port->state->xmit;
+ struct scatterlist *sg = &s->sg_tx;
+
+ /*
+ * DMA is idle now.
+ * Port xmit buffer is already mapped, and it is one page... Just adjust
+ * offsets and lengths. Since it is a circular buffer, we have to
+ * transmit till the end, and then the rest. Take the port lock to get a
+ * consistent xmit buffer state.
+ */
+ spin_lock_irq(&port->lock);
+ sg->offset = xmit->tail & (UART_XMIT_SIZE - 1);
+ sg->dma_address = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) +
+ sg->offset;
+ sg->length = min((int)CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE),
+ CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE));
+ sg->dma_length = sg->length;
+ spin_unlock_irq(&port->lock);
+
+ BUG_ON(!sg->length);
+
+ desc = chan->device->device_prep_slave_sg(chan,
+ sg, s->sg_len_tx, DMA_TO_DEVICE,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!desc) {
+ /* switch to PIO */
+ sci_tx_dma_release(s, true);
+ return;
+ }
+
+ dma_sync_sg_for_device(port->dev, sg, 1, DMA_TO_DEVICE);
+
+ spin_lock_irq(&port->lock);
+ s->desc_tx = desc;
+ desc->callback = sci_dma_tx_complete;
+ desc->callback_param = s;
+ spin_unlock_irq(&port->lock);
+ s->cookie_tx = desc->tx_submit(desc);
+ if (s->cookie_tx < 0) {
+ dev_warn(port->dev, "Failed submitting Tx DMA descriptor\n");
+ /* switch to PIO */
+ sci_tx_dma_release(s, true);
+ return;
+ }
+
+ dev_dbg(port->dev, "%s: %p: %d...%d, cookie %d\n", __func__,
+ xmit->buf, xmit->tail, xmit->head, s->cookie_tx);
+
+ dma_async_issue_pending(chan);
+}
+#endif
+
static void sci_start_tx(struct uart_port *port)
{
unsigned short ctrl;
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+ struct sci_port *s = to_sci_port(port);
+
+ if (s->chan_tx) {
+ if (!uart_circ_empty(&s->port.state->xmit) && s->cookie_tx < 0)
+ schedule_work(&s->work_tx);
+
+ return;
+ }
+#endif
+
/* Set TIE (Transmit Interrupt Enable) bit in SCSCR */
ctrl = sci_in(port, SCSCR);
ctrl |= SCI_CTRL_FLAGS_TIE;
@@ -838,13 +1206,12 @@ static void sci_stop_tx(struct uart_port *port)
sci_out(port, SCSCR, ctrl);
}
-static void sci_start_rx(struct uart_port *port, unsigned int tty_start)
+static void sci_start_rx(struct uart_port *port)
{
- unsigned short ctrl;
+ unsigned short ctrl = SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE;
/* Set RIE (Receive Interrupt Enable) bit in SCSCR */
- ctrl = sci_in(port, SCSCR);
- ctrl |= SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE;
+ ctrl |= sci_in(port, SCSCR);
sci_out(port, SCSCR, ctrl);
}
@@ -868,16 +1235,154 @@ static void sci_break_ctl(struct uart_port *port, int break_state)
/* Nothing here yet .. */
}
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+static bool filter(struct dma_chan *chan, void *slave)
+{
+ struct sh_dmae_slave *param = slave;
+
+ dev_dbg(chan->device->dev, "%s: slave ID %d\n", __func__,
+ param->slave_id);
+
+ if (param->dma_dev == chan->device->dev) {
+ chan->private = param;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static void rx_timer_fn(unsigned long arg)
+{
+ struct sci_port *s = (struct sci_port *)arg;
+ struct uart_port *port = &s->port;
+
+ u16 scr = sci_in(port, SCSCR);
+ sci_out(port, SCSCR, scr | SCI_CTRL_FLAGS_RIE);
+ dev_dbg(port->dev, "DMA Rx timed out\n");
+ schedule_work(&s->work_rx);
+}
+
+static void sci_request_dma(struct uart_port *port)
+{
+ struct sci_port *s = to_sci_port(port);
+ struct sh_dmae_slave *param;
+ struct dma_chan *chan;
+ dma_cap_mask_t mask;
+ int nent;
+
+ dev_dbg(port->dev, "%s: port %d DMA %p\n", __func__,
+ port->line, s->dma_dev);
+
+ if (!s->dma_dev)
+ return;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+ param = &s->param_tx;
+
+ /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_TX */
+ param->slave_id = s->slave_tx;
+ param->dma_dev = s->dma_dev;
+
+ s->cookie_tx = -EINVAL;
+ chan = dma_request_channel(mask, filter, param);
+ dev_dbg(port->dev, "%s: TX: got channel %p\n", __func__, chan);
+ if (chan) {
+ s->chan_tx = chan;
+ sg_init_table(&s->sg_tx, 1);
+ /* UART circular tx buffer is an aligned page. */
+ BUG_ON((int)port->state->xmit.buf & ~PAGE_MASK);
+ sg_set_page(&s->sg_tx, virt_to_page(port->state->xmit.buf),
+ UART_XMIT_SIZE, (int)port->state->xmit.buf & ~PAGE_MASK);
+ nent = dma_map_sg(port->dev, &s->sg_tx, 1, DMA_TO_DEVICE);
+ if (!nent)
+ sci_tx_dma_release(s, false);
+ else
+ dev_dbg(port->dev, "%s: mapped %d@%p to %x\n", __func__,
+ sg_dma_len(&s->sg_tx),
+ port->state->xmit.buf, sg_dma_address(&s->sg_tx));
+
+ s->sg_len_tx = nent;
+
+ INIT_WORK(&s->work_tx, work_fn_tx);
+ }
+
+ param = &s->param_rx;
+
+ /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_RX */
+ param->slave_id = s->slave_rx;
+ param->dma_dev = s->dma_dev;
+
+ chan = dma_request_channel(mask, filter, param);
+ dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan);
+ if (chan) {
+ dma_addr_t dma[2];
+ void *buf[2];
+ int i;
+
+ s->chan_rx = chan;
+
+ s->buf_len_rx = 2 * max(16, (int)port->fifosize);
+ buf[0] = dma_alloc_coherent(port->dev, s->buf_len_rx * 2,
+ &dma[0], GFP_KERNEL);
+
+ if (!buf[0]) {
+ dev_warn(port->dev,
+ "failed to allocate dma buffer, using PIO\n");
+ sci_rx_dma_release(s, true);
+ return;
+ }
+
+ buf[1] = buf[0] + s->buf_len_rx;
+ dma[1] = dma[0] + s->buf_len_rx;
+
+ for (i = 0; i < 2; i++) {
+ struct scatterlist *sg = &s->sg_rx[i];
+
+ sg_init_table(sg, 1);
+ sg_set_page(sg, virt_to_page(buf[i]), s->buf_len_rx,
+ (int)buf[i] & ~PAGE_MASK);
+ sg->dma_address = dma[i];
+ sg->dma_length = sg->length;
+ }
+
+ INIT_WORK(&s->work_rx, work_fn_rx);
+ setup_timer(&s->rx_timer, rx_timer_fn, (unsigned long)s);
+
+ sci_submit_rx(s);
+ }
+}
+
+static void sci_free_dma(struct uart_port *port)
+{
+ struct sci_port *s = to_sci_port(port);
+
+ if (!s->dma_dev)
+ return;
+
+ if (s->chan_tx)
+ sci_tx_dma_release(s, false);
+ if (s->chan_rx)
+ sci_rx_dma_release(s, false);
+}
+#endif
+
static int sci_startup(struct uart_port *port)
{
struct sci_port *s = to_sci_port(port);
+ dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
+
if (s->enable)
s->enable(port);
sci_request_irq(s);
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+ sci_request_dma(port);
+#endif
sci_start_tx(port);
- sci_start_rx(port, 1);
+ sci_start_rx(port);
return 0;
}
@@ -886,8 +1391,13 @@ static void sci_shutdown(struct uart_port *port)
{
struct sci_port *s = to_sci_port(port);
+ dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
+
sci_stop_rx(port);
sci_stop_tx(port);
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+ sci_free_dma(port);
+#endif
sci_free_irq(s);
if (s->disable)
@@ -937,6 +1447,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
sci_out(port, SCSMR, smr_val);
+ dev_dbg(port->dev, "%s: SMR %x, t %x, SCSCR %x\n", __func__, smr_val, t,
+ SCSCR_INIT(port));
+
if (t > 0) {
if (t >= 256) {
sci_out(port, SCSMR, (sci_in(port, SCSMR) & ~3) | 1);
@@ -954,7 +1467,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
sci_out(port, SCSCR, SCSCR_INIT(port));
if ((termios->c_cflag & CREAD) != 0)
- sci_start_rx(port, 0);
+ sci_start_rx(port);
}
static const char *sci_type(struct uart_port *port)
@@ -1049,19 +1562,21 @@ static void __devinit sci_init_single(struct platform_device *dev,
unsigned int index,
struct plat_sci_port *p)
{
- sci_port->port.ops = &sci_uart_ops;
- sci_port->port.iotype = UPIO_MEM;
- sci_port->port.line = index;
+ struct uart_port *port = &sci_port->port;
+
+ port->ops = &sci_uart_ops;
+ port->iotype = UPIO_MEM;
+ port->line = index;
switch (p->type) {
case PORT_SCIFA:
- sci_port->port.fifosize = 64;
+ port->fifosize = 64;
break;
case PORT_SCIF:
- sci_port->port.fifosize = 16;
+ port->fifosize = 16;
break;
default:
- sci_port->port.fifosize = 1;
+ port->fifosize = 1;
break;
}
@@ -1070,19 +1585,28 @@ static void __devinit sci_init_single(struct platform_device *dev,
sci_port->dclk = clk_get(&dev->dev, "peripheral_clk");
sci_port->enable = sci_clk_enable;
sci_port->disable = sci_clk_disable;
- sci_port->port.dev = &dev->dev;
+ port->dev = &dev->dev;
}
sci_port->break_timer.data = (unsigned long)sci_port;
sci_port->break_timer.function = sci_break_timer;
init_timer(&sci_port->break_timer);
- sci_port->port.mapbase = p->mapbase;
- sci_port->port.membase = p->membase;
+ port->mapbase = p->mapbase;
+ port->membase = p->membase;
- sci_port->port.irq = p->irqs[SCIx_TXI_IRQ];
- sci_port->port.flags = p->flags;
- sci_port->type = sci_port->port.type = p->type;
+ port->irq = p->irqs[SCIx_TXI_IRQ];
+ port->flags = p->flags;
+ sci_port->type = port->type = p->type;
+
+#ifdef CONFIG_SERIAL_SH_SCI_DMA
+ sci_port->dma_dev = p->dma_dev;
+ sci_port->slave_tx = p->dma_slave_tx;
+ sci_port->slave_rx = p->dma_slave_rx;
+
+ dev_dbg(port->dev, "%s: DMA device %p, tx %d, rx %d\n", __func__,
+ p->dma_dev, p->dma_slave_tx, p->dma_slave_rx);
+#endif
memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs));
}
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index fc2e963e65e..7696a664f8a 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -71,8 +71,6 @@ source "drivers/staging/asus_oled/Kconfig"
source "drivers/staging/panel/Kconfig"
-source "drivers/staging/altpciechdma/Kconfig"
-
source "drivers/staging/rtl8187se/Kconfig"
source "drivers/staging/rtl8192su/Kconfig"
@@ -81,20 +79,14 @@ source "drivers/staging/rtl8192u/Kconfig"
source "drivers/staging/rtl8192e/Kconfig"
-source "drivers/staging/mimio/Kconfig"
-
source "drivers/staging/frontier/Kconfig"
source "drivers/staging/dream/Kconfig"
source "drivers/staging/pohmelfs/Kconfig"
-source "drivers/staging/b3dfg/Kconfig"
-
source "drivers/staging/phison/Kconfig"
-source "drivers/staging/p9auth/Kconfig"
-
source "drivers/staging/line6/Kconfig"
source "drivers/gpu/drm/vmwgfx/Kconfig"
@@ -117,7 +109,7 @@ source "drivers/staging/hv/Kconfig"
source "drivers/staging/vme/Kconfig"
-source "drivers/staging/rar/Kconfig"
+source "drivers/staging/rar_register/Kconfig"
source "drivers/staging/sep/Kconfig"
@@ -143,5 +135,9 @@ source "drivers/staging/netwave/Kconfig"
source "drivers/staging/sm7xx/Kconfig"
+source "drivers/staging/dt3155/Kconfig"
+
+source "drivers/staging/crystalhd/Kconfig"
+
endif # !STAGING_EXCLUDE_BUILD
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index b5e67b889f6..ea2e70e2fed 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -18,18 +18,14 @@ obj-$(CONFIG_RT2870) += rt2870/
obj-$(CONFIG_COMEDI) += comedi/
obj-$(CONFIG_ASUS_OLED) += asus_oled/
obj-$(CONFIG_PANEL) += panel/
-obj-$(CONFIG_ALTERA_PCIE_CHDMA) += altpciechdma/
obj-$(CONFIG_R8187SE) += rtl8187se/
obj-$(CONFIG_RTL8192SU) += rtl8192su/
obj-$(CONFIG_RTL8192U) += rtl8192u/
obj-$(CONFIG_RTL8192E) += rtl8192e/
-obj-$(CONFIG_INPUT_MIMIO) += mimio/
obj-$(CONFIG_TRANZPORT) += frontier/
obj-$(CONFIG_DREAM) += dream/
obj-$(CONFIG_POHMELFS) += pohmelfs/
-obj-$(CONFIG_B3DFG) += b3dfg/
obj-$(CONFIG_IDE_PHISON) += phison/
-obj-$(CONFIG_PLAN9AUTH) += p9auth/
obj-$(CONFIG_LINE6_USB) += line6/
obj-$(CONFIG_USB_SERIAL_QUATECH2) += serqt_usb2/
obj-$(CONFIG_USB_SERIAL_QUATECH_USB2) += quatech_usb2/
@@ -39,7 +35,7 @@ obj-$(CONFIG_VT6656) += vt6656/
obj-$(CONFIG_FB_UDL) += udlfb/
obj-$(CONFIG_HYPERV) += hv/
obj-$(CONFIG_VME_BUS) += vme/
-obj-$(CONFIG_RAR_REGISTER) += rar/
+obj-$(CONFIG_RAR_REGISTER) += rar_register/
obj-$(CONFIG_DX_SEP) += sep/
obj-$(CONFIG_IIO) += iio/
obj-$(CONFIG_RAMZSWAP) += ramzswap/
@@ -53,3 +49,5 @@ obj-$(CONFIG_WAVELAN) += wavelan/
obj-$(CONFIG_PCMCIA_WAVELAN) += wavelan/
obj-$(CONFIG_PCMCIA_NETWAVE) += netwave/
obj-$(CONFIG_FB_SM7XX) += sm7xx/
+obj-$(CONFIG_DT3155) += dt3155/
+obj-$(CONFIG_CRYSTALHD) += crystalhd/
diff --git a/drivers/staging/altpciechdma/Kconfig b/drivers/staging/altpciechdma/Kconfig
deleted file mode 100644
index 0f4bf92cbbf..00000000000
--- a/drivers/staging/altpciechdma/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-config ALTERA_PCIE_CHDMA
- tristate "Altera PCI Express Chaining DMA driver"
- depends on PCI
- default N
- ---help---
- A reference driver that exercises the Chaining DMA logic reference
- design generated along the Altera FPGA PCI Express soft or hard core,
- only if instantiated using the MegaWizard, not the SOPC builder, of
- Quartus 8.1.
-
diff --git a/drivers/staging/altpciechdma/Makefile b/drivers/staging/altpciechdma/Makefile
deleted file mode 100644
index c08c8437f4d..00000000000
--- a/drivers/staging/altpciechdma/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-obj-$(CONFIG_ALTERA_PCIE_CHDMA) += altpciechdma.o
-
diff --git a/drivers/staging/altpciechdma/TODO b/drivers/staging/altpciechdma/TODO
deleted file mode 100644
index 12c945fd61e..00000000000
--- a/drivers/staging/altpciechdma/TODO
+++ /dev/null
@@ -1,15 +0,0 @@
-DONE:
- - functionality similar to logic testbench
-
-TODO:
- - checkpatch.pl cleanups.
- - keep state of DMA engines.
- - keep data structure that keeps state of each transfer.
- - interrupt handler should iterate over outstanding descriptor tables.
- - complete userspace cdev to read/write using the DMA engines.
- - split off the DMA support functions in a module, re-usable by custom
- drivers.
-
-Please coordinate work with, and send patches to
-Leon Woestenberg <leon@sidebranch.com>
-
diff --git a/drivers/staging/altpciechdma/altpciechdma.c b/drivers/staging/altpciechdma/altpciechdma.c
deleted file mode 100644
index 2f07dd4563a..00000000000
--- a/drivers/staging/altpciechdma/altpciechdma.c
+++ /dev/null
@@ -1,1182 +0,0 @@
-/**
- * Driver for Altera PCIe core chaining DMA reference design.
- *
- * Copyright (C) 2008 Leon Woestenberg <leon.woestenberg@axon.tv>
- * Copyright (C) 2008 Nickolas Heppermann <heppermannwdt@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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- *
- * Rationale: This driver exercises the chaining DMA read and write engine
- * in the reference design. It is meant as a complementary reference
- * driver that can be used for testing early designs as well as a basis to
- * write your custom driver.
- *
- * Status: Test results from Leon Woestenberg <leon.woestenberg@axon.tv>:
- *
- * Sendero Board w/ Cyclone II EP2C35F672C6N, PX1011A PCIe x1 PHY on a
- * Dell Precision 370 PC, x86, kernel 2.6.20 from Ubuntu 7.04.
- *
- * Sendero Board w/ Cyclone II EP2C35F672C6N, PX1011A PCIe x1 PHY on a
- * Freescale MPC8313E-RDB board, PowerPC, 2.6.24 w/ Freescale patches.
- *
- * Driver tests passed with PCIe Compiler 8.1. With PCIe 8.0 the DMA
- * loopback test had reproducable compare errors. I assume a change
- * in the compiler or reference design, but could not find evidence nor
- * documentation on a change or fix in that direction.
- *
- * The reference design does not have readable locations and thus a
- * dummy read, used to flush PCI posted writes, cannot be performed.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/cdev.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/jiffies.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-
-
-/* by default do not build the character device interface */
-/* XXX It is non-functional yet */
-#ifndef ALTPCIECHDMA_CDEV
-# define ALTPCIECHDMA_CDEV 0
-#endif
-
-/* build the character device interface? */
-#if ALTPCIECHDMA_CDEV
-# define MAX_CHDMA_SIZE (8 * 1024 * 1024)
-# include "mapper_user_to_sg.h"
-#endif
-
-/** driver name, mimicks Altera naming of the reference design */
-#define DRV_NAME "altpciechdma"
-/** number of BARs on the device */
-#define APE_BAR_NUM (6)
-/** BAR number where the RCSLAVE memory sits */
-#define APE_BAR_RCSLAVE (0)
-/** BAR number where the Descriptor Header sits */
-#define APE_BAR_HEADER (2)
-
-/** maximum size in bytes of the descriptor table, chdma logic limit */
-#define APE_CHDMA_TABLE_SIZE (4096)
-/* single transfer must not exceed 255 table entries. worst case this can be
- * achieved by 255 scattered pages, with only a single byte in the head and
- * tail pages. 253 * PAGE_SIZE is a safe upper bound for the transfer size.
- */
-#define APE_CHDMA_MAX_TRANSFER_LEN (253 * PAGE_SIZE)
-
-/**
- * Specifies those BARs to be mapped and the length of each mapping.
- *
- * Zero (0) means do not map, otherwise specifies the BAR lengths to be mapped.
- * If the actual BAR length is less, this is considered an error; then
- * reconfigure your PCIe core.
- *
- * @see ug_pci_express 8.0, table 7-2 at page 7-13.
- */
-static const unsigned long bar_min_len[APE_BAR_NUM] =
- { 32768, 0, 256, 0, 32768, 0 };
-
-/**
- * Descriptor Header, controls the DMA read engine or write engine.
- *
- * The descriptor header is the main data structure for starting DMA transfers.
- *
- * It sits in End Point (FPGA) memory BAR[2] for 32-bit or BAR[3:2] for 64-bit.
- * It references a descriptor table which exists in Root Complex (PC) memory.
- * Writing the rclast field starts the DMA operation, thus all other structures
- * and fields must be setup before doing so.
- *
- * @see ug_pci_express 8.0, tables 7-3, 7-4 and 7-5 at page 7-14.
- * @note This header must be written in four 32-bit (PCI DWORD) writes.
- */
-struct ape_chdma_header {
- /**
- * w0 consists of two 16-bit fields:
- * lsb u16 number; number of descriptors in ape_chdma_table
- * msb u16 control; global control flags
- */
- u32 w0;
- /* bus address to ape_chdma_table in Root Complex memory */
- u32 bdt_addr_h;
- u32 bdt_addr_l;
- /**
- * w3 consists of two 16-bit fields:
- * - lsb u16 rclast; last descriptor number available in Root Complex
- * - zero (0) means the first descriptor is ready,
- * - one (1) means two descriptors are ready, etc.
- * - msb u16 reserved;
- *
- * @note writing to this memory location starts the DMA operation!
- */
- u32 w3;
-} __attribute__ ((packed));
-
-/**
- * Descriptor Entry, describing a (non-scattered) single memory block transfer.
- *
- * There is one descriptor for each memory block involved in the transfer, a
- * block being a contiguous address range on the bus.
- *
- * Multiple descriptors are chained by means of the ape_chdma_table data
- * structure.
- *
- * @see ug_pci_express 8.0, tables 7-6, 7-7 and 7-8 at page 7-14 and page 7-15.
- */
-struct ape_chdma_desc {
- /**
- * w0 consists of two 16-bit fields:
- * number of DWORDS to transfer
- * - lsb u16 length;
- * global control
- * - msb u16 control;
- */
- u32 w0;
- /* address of memory in the End Point */
- u32 ep_addr;
- /* bus address of source or destination memory in the Root Complex */
- u32 rc_addr_h;
- u32 rc_addr_l;
-} __attribute__ ((packed));
-
-/**
- * Descriptor Table, an array of descriptors describing a chained transfer.
- *
- * An array of descriptors, preceded by workspace for the End Point.
- * It exists in Root Complex memory.
- *
- * The End Point can update its last completed descriptor number in the
- * eplast field if requested by setting the EPLAST_ENA bit either
- * globally in the header's or locally in any descriptor's control field.
- *
- * @note this structure may not exceed 4096 bytes. This results in a
- * maximum of 4096 / (4 * 4) - 1 = 255 descriptors per chained transfer.
- *
- * @see ug_pci_express 8.0, tables 7-9, 7-10 and 7-11 at page 7-17 and page 7-18.
- */
-struct ape_chdma_table {
- /* workspace 0x00-0x0b, reserved */
- u32 reserved1[3];
- /* workspace 0x0c-0x0f, last descriptor handled by End Point */
- u32 w3;
- /* the actual array of descriptors
- * 0x10-0x1f, 0x20-0x2f, ... 0xff0-0xfff (255 entries)
- */
- struct ape_chdma_desc desc[255];
-} __attribute__ ((packed));
-
-/**
- * Altera PCI Express ('ape') board specific book keeping data
- *
- * Keeps state of the PCIe core and the Chaining DMA controller
- * application.
- */
-struct ape_dev {
- /** the kernel pci device data structure provided by probe() */
- struct pci_dev *pci_dev;
- /**
- * kernel virtual address of the mapped BAR memory and IO regions of
- * the End Point. Used by map_bars()/unmap_bars().
- */
- void * __iomem bar[APE_BAR_NUM];
- /** kernel virtual address for Descriptor Table in Root Complex memory */
- struct ape_chdma_table *table_virt;
- /**
- * bus address for the Descriptor Table in Root Complex memory, in
- * CPU-native endianess
- */
- dma_addr_t table_bus;
- /* if the device regions could not be allocated, assume and remember it
- * is in use by another driver; this driver must not disable the device.
- */
- int in_use;
- /* whether this driver enabled msi for the device */
- int msi_enabled;
- /* whether this driver could obtain the regions */
- int got_regions;
- /* irq line successfully requested by this driver, -1 otherwise */
- int irq_line;
- /* board revision */
- u8 revision;
- /* interrupt count, incremented by the interrupt handler */
- int irq_count;
-#if ALTPCIECHDMA_CDEV
- /* character device */
- dev_t cdevno;
- struct cdev cdev;
- /* user space scatter gather mapper */
- struct sg_mapping_t *sgm;
-#endif
-};
-
-/**
- * Using the subsystem vendor id and subsystem id, it is possible to
- * distinguish between different cards bases around the same
- * (third-party) logic core.
- *
- * Default Altera vendor and device ID's, and some (non-reserved)
- * ID's are now used here that are used amongst the testers/developers.
- */
-static const struct pci_device_id ids[] = {
- { PCI_DEVICE(0x1172, 0xE001), },
- { PCI_DEVICE(0x2071, 0x2071), },
- { 0, }
-};
-MODULE_DEVICE_TABLE(pci, ids);
-
-#if ALTPCIECHDMA_CDEV
-/* prototypes for character device */
-static int sg_init(struct ape_dev *ape);
-static void sg_exit(struct ape_dev *ape);
-#endif
-
-/**
- * altpciechdma_isr() - Interrupt handler
- *
- */
-static irqreturn_t altpciechdma_isr(int irq, void *dev_id)
-{
- struct ape_dev *ape = (struct ape_dev *)dev_id;
- if (!ape)
- return IRQ_NONE;
- ape->irq_count++;
- return IRQ_HANDLED;
-}
-
-static int __devinit scan_bars(struct ape_dev *ape, struct pci_dev *dev)
-{
- int i;
- for (i = 0; i < APE_BAR_NUM; i++) {
- unsigned long bar_start = pci_resource_start(dev, i);
- if (bar_start) {
- unsigned long bar_end = pci_resource_end(dev, i);
- unsigned long bar_flags = pci_resource_flags(dev, i);
- printk(KERN_DEBUG "BAR%d 0x%08lx-0x%08lx flags 0x%08lx\n",
- i, bar_start, bar_end, bar_flags);
- }
- }
- return 0;
-}
-
-/**
- * Unmap the BAR regions that had been mapped earlier using map_bars()
- */
-static void unmap_bars(struct ape_dev *ape, struct pci_dev *dev)
-{
- int i;
- for (i = 0; i < APE_BAR_NUM; i++) {
- /* is this BAR mapped? */
- if (ape->bar[i]) {
- /* unmap BAR */
- pci_iounmap(dev, ape->bar[i]);
- ape->bar[i] = NULL;
- }
- }
-}
-
-/**
- * Map the device memory regions into kernel virtual address space after
- * verifying their sizes respect the minimum sizes needed, given by the
- * bar_min_len[] array.
- */
-static int __devinit map_bars(struct ape_dev *ape, struct pci_dev *dev)
-{
- int rc;
- int i;
- /* iterate through all the BARs */
- for (i = 0; i < APE_BAR_NUM; i++) {
- unsigned long bar_start = pci_resource_start(dev, i);
- unsigned long bar_end = pci_resource_end(dev, i);
- unsigned long bar_length = bar_end - bar_start + 1;
- ape->bar[i] = NULL;
- /* do not map, and skip, BARs with length 0 */
- if (!bar_min_len[i])
- continue;
- /* do not map BARs with address 0 */
- if (!bar_start || !bar_end) {
- printk(KERN_DEBUG "BAR #%d is not present?!\n", i);
- rc = -1;
- goto fail;
- }
- bar_length = bar_end - bar_start + 1;
- /* BAR length is less than driver requires? */
- if (bar_length < bar_min_len[i]) {
- printk(KERN_DEBUG "BAR #%d length = %lu bytes but driver "
- "requires at least %lu bytes\n",
- i, bar_length, bar_min_len[i]);
- rc = -1;
- goto fail;
- }
- /* map the device memory or IO region into kernel virtual
- * address space */
- ape->bar[i] = pci_iomap(dev, i, bar_min_len[i]);
- if (!ape->bar[i]) {
- printk(KERN_DEBUG "Could not map BAR #%d.\n", i);
- rc = -1;
- goto fail;
- }
- printk(KERN_DEBUG "BAR[%d] mapped at 0x%p with length %lu(/%lu).\n", i,
- ape->bar[i], bar_min_len[i], bar_length);
- }
- /* successfully mapped all required BAR regions */
- rc = 0;
- goto success;
-fail:
- /* unmap any BARs that we did map */
- unmap_bars(ape, dev);
-success:
- return rc;
-}
-
-#if 0 /* not yet implemented fully FIXME add opcode */
-static void __devinit rcslave_test(struct ape_dev *ape, struct pci_dev *dev)
-{
- u32 *rcslave_mem = (u32 *)ape->bar[APE_BAR_RCSLAVE];
- u32 result = 0;
- /** this number is assumed to be different each time this test runs */
- u32 seed = (u32)jiffies;
- u32 value = seed;
- int i;
-
- /* write loop */
- value = seed;
- for (i = 1024; i < 32768 / 4 ; i++) {
- printk(KERN_DEBUG "Writing 0x%08x to 0x%p.\n",
- (u32)value, (void *)rcslave_mem + i);
- iowrite32(value, rcslave_mem + i);
- value++;
- }
- /* read-back loop */
- value = seed;
- for (i = 1024; i < 32768 / 4; i++) {
- result = ioread32(rcslave_mem + i);
- if (result != value) {
- printk(KERN_DEBUG "Wrote 0x%08x to 0x%p, but read back 0x%08x.\n",
- (u32)value, (void *)rcslave_mem + i, (u32)result);
- break;
- }
- value++;
- }
-}
-#endif
-
-/* obtain the 32 most significant (high) bits of a 32-bit or 64-bit address */
-#define pci_dma_h(addr) ((addr >> 16) >> 16)
-/* obtain the 32 least significant (low) bits of a 32-bit or 64-bit address */
-#define pci_dma_l(addr) (addr & 0xffffffffUL)
-
-/* ape_fill_chdma_desc() - Fill a Altera PCI Express Chaining DMA descriptor
- *
- * @desc pointer to descriptor to be filled
- * @addr root complex address
- * @ep_addr end point address
- * @len number of bytes, must be a multiple of 4.
- */
-static inline void ape_chdma_desc_set(struct ape_chdma_desc *desc, dma_addr_t addr, u32 ep_addr, int len)
-{
- BUG_ON(len & 3);
- desc->w0 = cpu_to_le32(len / 4);
- desc->ep_addr = cpu_to_le32(ep_addr);
- desc->rc_addr_h = cpu_to_le32(pci_dma_h(addr));
- desc->rc_addr_l = cpu_to_le32(pci_dma_l(addr));
-}
-
-#if ALTPCIECHDMA_CDEV
-/*
- * ape_sg_to_chdma_table() - Create a device descriptor table from a scatterlist.
- *
- * The scatterlist must have been mapped by pci_map_sg(sgm->sgl).
- *
- * @sgl scatterlist.
- * @nents Number of entries in the scatterlist.
- * @first Start index in the scatterlist sgm->sgl.
- * @ep_addr End Point address for the scatter/gather transfer.
- * @desc pointer to first descriptor
- *
- * Returns Number of entries in the table on success, -1 on error.
- */
-static int ape_sg_to_chdma_table(struct scatterlist *sgl, int nents, int first, struct ape_chdma_desc *desc, u32 ep_addr)
-{
- int i = first, j = 0;
- /* inspect first entry */
- dma_addr_t addr = sg_dma_address(&sgl[i]);
- unsigned int len = sg_dma_len(&sgl[i]);
- /* contiguous block */
- dma_addr_t cont_addr = addr;
- unsigned int cont_len = len;
- /* iterate over remaining entries */
- for (; j < 25 && i < nents - 1; i++) {
- /* bus address of next entry i + 1 */
- dma_addr_t next = sg_dma_address(&sgl[i + 1]);
- /* length of this entry i */
- len = sg_dma_len(&sgl[i]);
- printk(KERN_DEBUG "%04d: addr=0x%Lx length=0x%08x\n", i,
- (unsigned long long)addr, len);
- /* entry i + 1 is non-contiguous with entry i? */
- if (next != addr + len) {
- /* TODO create entry here (we could overwrite i) */
- printk(KERN_DEBUG "%4d: cont_addr=0x%Lx cont_len=0x%08x\n", j,
- (unsigned long long)cont_addr, cont_len);
- /* set descriptor for contiguous transfer */
- ape_chdma_desc_set(&desc[j], cont_addr, ep_addr, cont_len);
- /* next end point memory address */
- ep_addr += cont_len;
- /* start new contiguous block */
- cont_addr = next;
- cont_len = 0;
- j++;
- }
- /* add entry i + 1 to current contiguous block */
- cont_len += len;
- /* goto entry i + 1 */
- addr = next;
- }
- /* TODO create entry here (we could overwrite i) */
- printk(KERN_DEBUG "%04d: addr=0x%Lx length=0x%08x\n", i,
- (unsigned long long)addr, len);
- printk(KERN_DEBUG "%4d: cont_addr=0x%Lx length=0x%08x\n", j,
- (unsigned long long)cont_addr, cont_len);
- j++;
- return j;
-}
-#endif
-
-/* compare buffers */
-static inline int compare(u32 *p, u32 *q, int len)
-{
- int result = -1;
- int fail = 0;
- int i;
- for (i = 0; i < len / 4; i++) {
- if (*p == *q) {
- /* every so many u32 words, show equals */
- if ((i & 255) == 0)
- printk(KERN_DEBUG "[%p] = 0x%08x [%p] = 0x%08x\n", p, *p, q, *q);
- } else {
- fail++;
- /* show the first few miscompares */
- if (fail < 10)
- printk(KERN_DEBUG "[%p] = 0x%08x != [%p] = 0x%08x ?!\n", p, *p, q, *q);
- /* but stop after a while */
- else if (fail == 10)
- printk(KERN_DEBUG "---more errors follow! not printed---\n");
- else
- /* stop compare after this many errors */
- break;
- }
- p++;
- q++;
- }
- if (!fail)
- result = 0;
- return result;
-}
-
-/* dma_test() - Perform DMA loop back test to end point and back to root complex.
- *
- * Allocate a cache-coherent buffer in host memory, consisting of four pages.
- *
- * Fill the four memory pages such that each 32-bit word contains its own address.
- *
- * Now perform a loop back test, have the end point device copy the first buffer
- * half to end point memory, then have it copy back into the second half.
- *
- * Create a descriptor table to copy the first buffer half into End Point
- * memory. Instruct the End Point to do a DMA read using that table.
- *
- * Create a descriptor table to copy End Point memory to the second buffer
- * half. Instruct the End Point to do a DMA write using that table.
- *
- * Compare results, fail or pass.
- *
- */
-static int __devinit dma_test(struct ape_dev *ape, struct pci_dev *dev)
-{
- /* test result; guilty until proven innocent */
- int result = -1;
- /* the DMA read header sits at address 0x00 of the DMA engine BAR */
- struct ape_chdma_header *write_header = (struct ape_chdma_header *)ape->bar[APE_BAR_HEADER];
- /* the write DMA header sits after the read header at address 0x10 */
- struct ape_chdma_header *read_header = write_header + 1;
- /* virtual address of the allocated buffer */
- u8 *buffer_virt = 0;
- /* bus address of the allocated buffer */
- dma_addr_t buffer_bus = 0;
- int i, n = 0, irq_count;
-
- /* temporary value used to construct 32-bit data words */
- u32 w;
-
- printk(KERN_DEBUG "bar_tests(), PAGE_SIZE = 0x%0x\n", (int)PAGE_SIZE);
- printk(KERN_DEBUG "write_header = 0x%p.\n", write_header);
- printk(KERN_DEBUG "read_header = 0x%p.\n", read_header);
- printk(KERN_DEBUG "&write_header->w3 = 0x%p\n", &write_header->w3);
- printk(KERN_DEBUG "&read_header->w3 = 0x%p\n", &read_header->w3);
- printk(KERN_DEBUG "ape->table_virt = 0x%p.\n", ape->table_virt);
-
- if (!write_header || !read_header || !ape->table_virt)
- goto fail;
-
- /* allocate and map coherently-cached memory for a DMA-able buffer */
- /* @see Documentation/PCI/PCI-DMA-mapping.txt, near line 318 */
- buffer_virt = (u8 *)pci_alloc_consistent(dev, PAGE_SIZE * 4, &buffer_bus);
- if (!buffer_virt) {
- printk(KERN_DEBUG "Could not allocate coherent DMA buffer.\n");
- goto fail;
- }
- printk(KERN_DEBUG "Allocated cache-coherent DMA buffer (virtual address = %p, bus address = 0x%016llx).\n",
- buffer_virt, (u64)buffer_bus);
-
- /* fill first half of buffer with its virtual address as data */
- for (i = 0; i < 4 * PAGE_SIZE; i += 4)
-#if 0
- *(u32 *)(buffer_virt + i) = i / PAGE_SIZE + 1;
-#else
- *(u32 *)(buffer_virt + i) = (u32)(unsigned long)(buffer_virt + i);
-#endif
-#if 0
- compare((u32 *)buffer_virt, (u32 *)(buffer_virt + 2 * PAGE_SIZE), 8192);
-#endif
-
-#if 0
- /* fill second half of buffer with zeroes */
- for (i = 2 * PAGE_SIZE; i < 4 * PAGE_SIZE; i += 4)
- *(u32 *)(buffer_virt + i) = 0;
-#endif
-
- /* invalidate EPLAST, outside 0-255, 0xFADE is from the testbench */
- ape->table_virt->w3 = cpu_to_le32(0x0000FADE);
-
- /* fill in first descriptor */
- n = 0;
- /* read 8192 bytes from RC buffer to EP address 4096 */
- ape_chdma_desc_set(&ape->table_virt->desc[n], buffer_bus, 4096, 2 * PAGE_SIZE);
-#if 1
- for (i = 0; i < 255; i++)
- ape_chdma_desc_set(&ape->table_virt->desc[i], buffer_bus, 4096, 2 * PAGE_SIZE);
- /* index of last descriptor */
- n = i - 1;
-#endif
-#if 0
- /* fill in next descriptor */
- n++;
- /* read 1024 bytes from RC buffer to EP address 4096 + 1024 */
- ape_chdma_desc_set(&ape->table_virt->desc[n], buffer_bus + 1024, 4096 + 1024, 1024);
-#endif
-
-#if 1
- /* enable MSI after the last descriptor is completed */
- if (ape->msi_enabled)
- ape->table_virt->desc[n].w0 |= cpu_to_le32(1UL << 16)/*local MSI*/;
-#endif
-#if 0
- /* dump descriptor table for debugging */
- printk(KERN_DEBUG "Descriptor Table (Read, in Root Complex Memory, # = %d)\n", n + 1);
- for (i = 0; i < 4 + (n + 1) * 4; i += 4) {
- u32 *p = (u32 *)ape->table_virt;
- p += i;
- printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (LEN=0x%x)\n", (u32)p, (u32)p & 15, *p, 4 * le32_to_cpu(*p));
- p++;
- printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (EPA=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
- p++;
- printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (RCH=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
- p++;
- printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (RCL=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
- }
-#endif
- /* set available number of descriptors in table */
- w = (u32)(n + 1);
- w |= (1UL << 18)/*global EPLAST_EN*/;
-#if 0
- if (ape->msi_enabled)
- w |= (1UL << 17)/*global MSI*/;
-#endif
- printk(KERN_DEBUG "writing 0x%08x to 0x%p\n", w, (void *)&read_header->w0);
- iowrite32(w, &read_header->w0);
-
- /* write table address (higher 32-bits) */
- printk(KERN_DEBUG "writing 0x%08x to 0x%p\n", (u32)((ape->table_bus >> 16) >> 16), (void *)&read_header->bdt_addr_h);
- iowrite32(pci_dma_h(ape->table_bus), &read_header->bdt_addr_h);
-
- /* write table address (lower 32-bits) */
- printk(KERN_DEBUG "writing 0x%08x to 0x%p\n", (u32)(ape->table_bus & 0xffffffffUL), (void *)&read_header->bdt_addr_l);
- iowrite32(pci_dma_l(ape->table_bus), &read_header->bdt_addr_l);
-
- /* memory write barrier */
- wmb();
- printk(KERN_DEBUG "Flush posted writes\n");
- /** FIXME Add dummy read to flush posted writes but need a readable location! */
-#if 0
- (void)ioread32();
-#endif
-
- /* remember IRQ count before the transfer */
- irq_count = ape->irq_count;
- /* write number of descriptors - this starts the DMA */
- printk(KERN_DEBUG "\nStart DMA read\n");
- printk(KERN_DEBUG "writing 0x%08x to 0x%p\n", (u32)n, (void *)&read_header->w3);
- iowrite32(n, &read_header->w3);
- printk(KERN_DEBUG "EPLAST = %lu\n", le32_to_cpu(*(u32 *)&ape->table_virt->w3) & 0xffffUL);
-
- /** memory write barrier */
- wmb();
- /* dummy read to flush posted writes */
- /* FIXME Need a readable location! */
-#if 0
- (void)ioread32();
-#endif
- printk(KERN_DEBUG "POLL FOR READ:\n");
- /* poll for chain completion, 1000 times 1 millisecond */
- for (i = 0; i < 100; i++) {
- volatile u32 *p = &ape->table_virt->w3;
- u32 eplast = le32_to_cpu(*p) & 0xffffUL;
- printk(KERN_DEBUG "EPLAST = %u, n = %d\n", eplast, n);
- if (eplast == n) {
- printk(KERN_DEBUG "DONE\n");
- /* print IRQ count before the transfer */
- printk(KERN_DEBUG "#IRQs during transfer: %d\n", ape->irq_count - irq_count);
- break;
- }
- udelay(100);
- }
-
- /* invalidate EPLAST, outside 0-255, 0xFADE is from the testbench */
- ape->table_virt->w3 = cpu_to_le32(0x0000FADE);
-
- /* setup first descriptor */
- n = 0;
- ape_chdma_desc_set(&ape->table_virt->desc[n], buffer_bus + 8192, 4096, 2 * PAGE_SIZE);
-#if 1
- for (i = 0; i < 255; i++)
- ape_chdma_desc_set(&ape->table_virt->desc[i], buffer_bus + 8192, 4096, 2 * PAGE_SIZE);
-
- /* index of last descriptor */
- n = i - 1;
-#endif
-#if 1 /* test variable, make a module option later */
- if (ape->msi_enabled)
- ape->table_virt->desc[n].w0 |= cpu_to_le32(1UL << 16)/*local MSI*/;
-#endif
-#if 0
- /* dump descriptor table for debugging */
- printk(KERN_DEBUG "Descriptor Table (Write, in Root Complex Memory, # = %d)\n", n + 1);
- for (i = 0; i < 4 + (n + 1) * 4; i += 4) {
- u32 *p = (u32 *)ape->table_virt;
- p += i;
- printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (LEN=0x%x)\n", (u32)p, (u32)p & 15, *p, 4 * le32_to_cpu(*p));
- p++;
- printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (EPA=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
- p++;
- printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (RCH=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
- p++;
- printk(KERN_DEBUG "0x%08x/0x%02x: 0x%08x (RCL=0x%x)\n", (u32)p, (u32)p & 15, *p, le32_to_cpu(*p));
- }
-#endif
-
- /* set number of available descriptors in the table */
- w = (u32)(n + 1);
- /* enable updates of eplast for each descriptor completion */
- w |= (u32)(1UL << 18)/*global EPLAST_EN*/;
-#if 0 /* test variable, make a module option later */
- /* enable MSI for each descriptor completion */
- if (ape->msi_enabled)
- w |= (1UL << 17)/*global MSI*/;
-#endif
- iowrite32(w, &write_header->w0);
- iowrite32(pci_dma_h(ape->table_bus), &write_header->bdt_addr_h);
- iowrite32(pci_dma_l(ape->table_bus), &write_header->bdt_addr_l);
-
- /** memory write barrier and flush posted writes */
- wmb();
- /* dummy read to flush posted writes */
- /* FIXME Need a readable location! */
-#if 0
- (void)ioread32();
-#endif
- irq_count = ape->irq_count;
-
- printk(KERN_DEBUG "\nStart DMA write\n");
- iowrite32(n, &write_header->w3);
-
- /** memory write barrier */
- wmb();
- /** dummy read to flush posted writes */
- /* (void) ioread32(); */
-
- printk(KERN_DEBUG "POLL FOR WRITE:\n");
- /* poll for completion, 1000 times 1 millisecond */
- for (i = 0; i < 100; i++) {
- volatile u32 *p = &ape->table_virt->w3;
- u32 eplast = le32_to_cpu(*p) & 0xffffUL;
- printk(KERN_DEBUG "EPLAST = %u, n = %d\n", eplast, n);
- if (eplast == n) {
- printk(KERN_DEBUG "DONE\n");
- /* print IRQ count before the transfer */
- printk(KERN_DEBUG "#IRQs during transfer: %d\n", ape->irq_count - irq_count);
- break;
- }
- udelay(100);
- }
- /* soft-reset DMA write engine */
- iowrite32(0x0000ffffUL, &write_header->w0);
- /* soft-reset DMA read engine */
- iowrite32(0x0000ffffUL, &read_header->w0);
-
- /** memory write barrier */
- wmb();
- /* dummy read to flush posted writes */
- /* FIXME Need a readable location! */
-#if 0
- (void)ioread32();
-#endif
- /* compare first half of buffer with second half, should be identical */
- result = compare((u32 *)buffer_virt, (u32 *)(buffer_virt + 2 * PAGE_SIZE), 8192);
- printk(KERN_DEBUG "DMA loop back test %s.\n", result ? "FAILED" : "PASSED");
-
- pci_free_consistent(dev, 4 * PAGE_SIZE, buffer_virt, buffer_bus);
-fail:
- printk(KERN_DEBUG "bar_tests() end, result %d\n", result);
- return result;
-}
-
-/* Called when the PCI sub system thinks we can control the given device.
- * Inspect if we can support the device and if so take control of it.
- *
- * Return 0 when we have taken control of the given device.
- *
- * - allocate board specific bookkeeping
- * - allocate coherently-mapped memory for the descriptor table
- * - enable the board
- * - verify board revision
- * - request regions
- * - query DMA mask
- * - obtain and request irq
- * - map regions into kernel address space
- */
-static int __devinit probe(struct pci_dev *dev, const struct pci_device_id *id)
-{
- int rc = 0;
- struct ape_dev *ape = NULL;
- u8 irq_pin, irq_line;
- printk(KERN_DEBUG "probe(dev = 0x%p, pciid = 0x%p)\n", dev, id);
-
- /* allocate memory for per-board book keeping */
- ape = kzalloc(sizeof(struct ape_dev), GFP_KERNEL);
- if (!ape) {
- printk(KERN_DEBUG "Could not kzalloc()ate memory.\n");
- goto err_ape;
- }
- ape->pci_dev = dev;
- dev_set_drvdata(&dev->dev, ape);
- printk(KERN_DEBUG "probe() ape = 0x%p\n", ape);
-
- printk(KERN_DEBUG "sizeof(struct ape_chdma_table) = %d.\n",
- (int)sizeof(struct ape_chdma_table));
- /* the reference design has a size restriction on the table size */
- BUG_ON(sizeof(struct ape_chdma_table) > APE_CHDMA_TABLE_SIZE);
-
- /* allocate and map coherently-cached memory for a descriptor table */
- /* @see LDD3 page 446 */
- ape->table_virt = (struct ape_chdma_table *)pci_alloc_consistent(dev,
- APE_CHDMA_TABLE_SIZE, &ape->table_bus);
- /* could not allocate table? */
- if (!ape->table_virt) {
- printk(KERN_DEBUG "Could not dma_alloc()ate_coherent memory.\n");
- goto err_table;
- }
-
- printk(KERN_DEBUG "table_virt = %p, table_bus = 0x%16llx.\n",
- ape->table_virt, (u64)ape->table_bus);
-
- /* enable device */
- rc = pci_enable_device(dev);
- if (rc) {
- printk(KERN_DEBUG "pci_enable_device() failed\n");
- goto err_enable;
- }
-
- /* enable bus master capability on device */
- pci_set_master(dev);
- /* enable message signaled interrupts */
- rc = pci_enable_msi(dev);
- /* could not use MSI? */
- if (rc) {
- /* resort to legacy interrupts */
- printk(KERN_DEBUG "Could not enable MSI interrupting.\n");
- ape->msi_enabled = 0;
- /* MSI enabled, remember for cleanup */
- } else {
- printk(KERN_DEBUG "Enabled MSI interrupting.\n");
- ape->msi_enabled = 1;
- }
-
- pci_read_config_byte(dev, PCI_REVISION_ID, &ape->revision);
-#if 0 /* example */
- /* (for example) this driver does not support revision 0x42 */
- if (ape->revision == 0x42) {
- printk(KERN_DEBUG "Revision 0x42 is not supported by this driver.\n");
- rc = -ENODEV;
- goto err_rev;
- }
-#endif
- /** XXX check for native or legacy PCIe endpoint? */
-
- rc = pci_request_regions(dev, DRV_NAME);
- /* could not request all regions? */
- if (rc) {
- /* assume device is in use (and do not disable it later!) */
- ape->in_use = 1;
- goto err_regions;
- }
- ape->got_regions = 1;
-
-#if 1 /* @todo For now, disable 64-bit, because I do not understand the implications (DAC!) */
- /* query for DMA transfer */
- /* @see Documentation/PCI/PCI-DMA-mapping.txt */
- if (!pci_set_dma_mask(dev, DMA_BIT_MASK(64))) {
- pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(64));
- /* use 64-bit DMA */
- printk(KERN_DEBUG "Using a 64-bit DMA mask.\n");
- } else
-#endif
- if (!pci_set_dma_mask(dev, DMA_BIT_MASK(32))) {
- printk(KERN_DEBUG "Could not set 64-bit DMA mask.\n");
- pci_set_consistent_dma_mask(dev, DMA_BIT_MASK(32));
- /* use 32-bit DMA */
- printk(KERN_DEBUG "Using a 32-bit DMA mask.\n");
- } else {
- printk(KERN_DEBUG "No suitable DMA possible.\n");
- /** @todo Choose proper error return code */
- rc = -1;
- goto err_mask;
- }
-
- rc = pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin);
- /* could not read? */
- if (rc)
- goto err_irq;
- printk(KERN_DEBUG "IRQ pin #%d (0=none, 1=INTA#...4=INTD#).\n", irq_pin);
-
- /* @see LDD3, page 318 */
- rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq_line);
- /* could not read? */
- if (rc) {
- printk(KERN_DEBUG "Could not query PCI_INTERRUPT_LINE, error %d\n", rc);
- goto err_irq;
- }
- printk(KERN_DEBUG "IRQ line #%d.\n", irq_line);
-#if 1
- irq_line = dev->irq;
- /* @see LDD3, page 259 */
- rc = request_irq(irq_line, altpciechdma_isr, IRQF_SHARED, DRV_NAME, (void *)ape);
- if (rc) {
- printk(KERN_DEBUG "Could not request IRQ #%d, error %d\n", irq_line, rc);
- ape->irq_line = -1;
- goto err_irq;
- }
- /* remember which irq we allocated */
- ape->irq_line = (int)irq_line;
- printk(KERN_DEBUG "Succesfully requested IRQ #%d with dev_id 0x%p\n", irq_line, ape);
-#endif
- /* show BARs */
- scan_bars(ape, dev);
- /* map BARs */
- rc = map_bars(ape, dev);
- if (rc)
- goto err_map;
-#if ALTPCIECHDMA_CDEV
- /* initialize character device */
- rc = sg_init(ape);
- if (rc)
- goto err_cdev;
-#endif
- /* perform DMA engines loop back test */
- rc = dma_test(ape, dev);
- (void)rc;
- /* successfully took the device */
- rc = 0;
- printk(KERN_DEBUG "probe() successful.\n");
- goto end;
-#if ALTPCIECHDMA_CDEV
-err_cdev:
- /* unmap the BARs */
- unmap_bars(ape, dev);
-#endif
-err_map:
- /* free allocated irq */
- if (ape->irq_line >= 0)
- free_irq(ape->irq_line, (void *)ape);
-err_irq:
- if (ape->msi_enabled)
- pci_disable_msi(dev);
- /* disable the device iff it is not in use */
- if (!ape->in_use)
- pci_disable_device(dev);
- if (ape->got_regions)
- pci_release_regions(dev);
-err_mask:
-err_regions:
-/*err_rev:*/
-/* clean up everything before device enable() */
-err_enable:
- if (ape->table_virt)
- pci_free_consistent(dev, APE_CHDMA_TABLE_SIZE, ape->table_virt, ape->table_bus);
-/* clean up everything before allocating descriptor table */
-err_table:
- if (ape)
- kfree(ape);
-err_ape:
-end:
- return rc;
-}
-
-static void __devexit remove(struct pci_dev *dev)
-{
- struct ape_dev *ape = dev_get_drvdata(&dev->dev);
-
- printk(KERN_DEBUG "remove(0x%p)\n", dev);
- printk(KERN_DEBUG "remove(dev = 0x%p) where ape = 0x%p\n", dev, ape);
-
- /* remove character device */
-#if ALTPCIECHDMA_CDEV
- sg_exit(ape);
-#endif
-
- if (ape->table_virt)
- pci_free_consistent(dev, APE_CHDMA_TABLE_SIZE, ape->table_virt, ape->table_bus);
-
- /* free IRQ
- * @see LDD3 page 279
- */
- if (ape->irq_line >= 0) {
- printk(KERN_DEBUG "Freeing IRQ #%d for dev_id 0x%08lx.\n",
- ape->irq_line, (unsigned long)ape);
- free_irq(ape->irq_line, (void *)ape);
- }
- /* MSI was enabled? */
- if (ape->msi_enabled) {
- /* Disable MSI @see Documentation/MSI-HOWTO.txt */
- pci_disable_msi(dev);
- ape->msi_enabled = 0;
- }
- /* unmap the BARs */
- unmap_bars(ape, dev);
- if (!ape->in_use)
- pci_disable_device(dev);
- if (ape->got_regions)
- /* to be called after device disable */
- pci_release_regions(dev);
-}
-
-#if ALTPCIECHDMA_CDEV
-
-/*
- * Called when the device goes from unused to used.
- */
-static int sg_open(struct inode *inode, struct file *file)
-{
- struct ape_dev *ape;
- printk(KERN_DEBUG DRV_NAME "_open()\n");
- /* pointer to containing data structure of the character device inode */
- ape = container_of(inode->i_cdev, struct ape_dev, cdev);
- /* create a reference to our device state in the opened file */
- file->private_data = ape;
- /* create virtual memory mapper */
- ape->sgm = sg_create_mapper(MAX_CHDMA_SIZE);
- return 0;
-}
-
-/*
- * Called when the device goes from used to unused.
- */
-static int sg_close(struct inode *inode, struct file *file)
-{
- /* fetch device specific data stored earlier during open */
- struct ape_dev *ape = (struct ape_dev *)file->private_data;
- printk(KERN_DEBUG DRV_NAME "_close()\n");
- /* destroy virtual memory mapper */
- sg_destroy_mapper(ape->sgm);
- return 0;
-}
-
-static ssize_t sg_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
-{
- /* fetch device specific data stored earlier during open */
- struct ape_dev *ape = (struct ape_dev *)file->private_data;
- (void)ape;
- printk(KERN_DEBUG DRV_NAME "_read(buf=0x%p, count=%lld, pos=%llu)\n", buf, (s64)count, (u64)*pos);
- return count;
-}
-
-/* sg_write() - Write to the device
- *
- * @buf userspace buffer
- * @count number of bytes in the userspace buffer
- *
- * Iterate over the userspace buffer, taking at most 255 * PAGE_SIZE bytes for
- * each DMA transfer.
- * For each transfer, get the user pages, build a sglist, map, build a
- * descriptor table. submit the transfer. wait for the interrupt handler
- * to wake us on completion.
- */
-static ssize_t sg_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
-{
- int hwnents, tents;
- size_t transfer_len, remaining = count, done = 0;
- u64 transfer_addr = (u64)buf;
- /* fetch device specific data stored earlier during open */
- struct ape_dev *ape = (struct ape_dev *)file->private_data;
- printk(KERN_DEBUG DRV_NAME "_write(buf=0x%p, count=%lld, pos=%llu)\n",
- buf, (s64)count, (u64)*pos);
- /* TODO transfer boundaries at PAGE_SIZE granularity */
- while (remaining > 0) {
- /* limit DMA transfer size */
- transfer_len = (remaining < APE_CHDMA_MAX_TRANSFER_LEN) ? remaining :
- APE_CHDMA_MAX_TRANSFER_LEN;
- /* get all user space buffer pages and create a scattergather list */
- sgm_map_user_pages(ape->sgm, transfer_addr, transfer_len, 0/*read from userspace*/);
- printk(KERN_DEBUG DRV_NAME "mapped_pages=%d\n", ape->sgm->mapped_pages);
- /* map all entries in the scattergather list */
- hwnents = pci_map_sg(ape->pci_dev, ape->sgm->sgl, ape->sgm->mapped_pages, DMA_TO_DEVICE);
- printk(KERN_DEBUG DRV_NAME "hwnents=%d\n", hwnents);
- /* build device descriptor tables and submit them to the DMA engine */
- tents = ape_sg_to_chdma_table(ape->sgm->sgl, hwnents, 0, &ape->table_virt->desc[0], 4096);
- printk(KERN_DEBUG DRV_NAME "tents=%d\n", hwnents);
-#if 0
- while (tables) {
- /* TODO build table */
- /* TODO submit table to the device */
- /* if engine stopped and unfinished work then start engine */
- }
- put ourselves on wait queue
-#endif
-
- dma_unmap_sg(NULL, ape->sgm->sgl, ape->sgm->mapped_pages, DMA_TO_DEVICE);
- /* dirty and free the pages */
- sgm_unmap_user_pages(ape->sgm, 1/*dirtied*/);
- /* book keeping */
- transfer_addr += transfer_len;
- remaining -= transfer_len;
- done += transfer_len;
- }
- return done;
-}
-
-/*
- * character device file operations
- */
-static const struct file_operations sg_fops = {
- .owner = THIS_MODULE,
- .open = sg_open,
- .release = sg_close,
- .read = sg_read,
- .write = sg_write,
-};
-
-/* sg_init() - Initialize character device
- *
- * XXX Should ideally be tied to the device, on device probe, not module init.
- */
-static int sg_init(struct ape_dev *ape)
-{
- int rc;
- printk(KERN_DEBUG DRV_NAME " sg_init()\n");
- /* allocate a dynamically allocated character device node */
- rc = alloc_chrdev_region(&ape->cdevno, 0/*requested minor*/, 1/*count*/, DRV_NAME);
- /* allocation failed? */
- if (rc < 0) {
- printk("alloc_chrdev_region() = %d\n", rc);
- goto fail_alloc;
- }
- /* couple the device file operations to the character device */
- cdev_init(&ape->cdev, &sg_fops);
- ape->cdev.owner = THIS_MODULE;
- /* bring character device live */
- rc = cdev_add(&ape->cdev, ape->cdevno, 1/*count*/);
- if (rc < 0) {
- printk("cdev_add() = %d\n", rc);
- goto fail_add;
- }
- printk(KERN_DEBUG "altpciechdma = %d:%d\n", MAJOR(ape->cdevno), MINOR(ape->cdevno));
- return 0;
-fail_add:
- /* free the dynamically allocated character device node */
- unregister_chrdev_region(ape->cdevno, 1/*count*/);
-fail_alloc:
- return -1;
-}
-
-/* sg_exit() - Cleanup character device
- *
- * XXX Should ideally be tied to the device, on device remove, not module exit.
- */
-
-static void sg_exit(struct ape_dev *ape)
-{
- printk(KERN_DEBUG DRV_NAME " sg_exit()\n");
- /* remove the character device */
- cdev_del(&ape->cdev);
- /* free the dynamically allocated character device node */
- unregister_chrdev_region(ape->cdevno, 1/*count*/);
-}
-
-#endif /* ALTPCIECHDMA_CDEV */
-
-/* used to register the driver with the PCI kernel sub system
- * @see LDD3 page 311
- */
-static struct pci_driver pci_driver = {
- .name = DRV_NAME,
- .id_table = ids,
- .probe = probe,
- .remove = __devexit_p(remove),
- /* resume, suspend are optional */
-};
-
-/**
- * alterapciechdma_init() - Module initialization, registers devices.
- */
-static int __init alterapciechdma_init(void)
-{
- int rc = 0;
- printk(KERN_DEBUG DRV_NAME " init(), built at " __DATE__ " " __TIME__ "\n");
- /* register this driver with the PCI bus driver */
- rc = pci_register_driver(&pci_driver);
- if (rc < 0)
- return rc;
- return 0;
-}
-
-/**
- * alterapciechdma_init() - Module cleanup, unregisters devices.
- */
-static void __exit alterapciechdma_exit(void)
-{
- printk(KERN_DEBUG DRV_NAME " exit(), built at " __DATE__ " " __TIME__ "\n");
- /* unregister this driver from the PCI bus driver */
- pci_unregister_driver(&pci_driver);
-}
-
-MODULE_LICENSE("GPL");
-
-module_init(alterapciechdma_init);
-module_exit(alterapciechdma_exit);
-
diff --git a/drivers/staging/arlan/Makefile b/drivers/staging/arlan/Makefile
index 9e58e5fae7b..5a84d4402f2 100644
--- a/drivers/staging/arlan/Makefile
+++ b/drivers/staging/arlan/Makefile
@@ -1,3 +1,3 @@
-obj-$(CONFIG_ARLAN) += arlan.o
+obj-$(CONFIG_ARLAN) += arlan.o
arlan-objs := arlan-main.o arlan-proc.o
diff --git a/drivers/staging/arlan/arlan.h b/drivers/staging/arlan/arlan.h
index fb3ad51a1ca..ffcd3ea048a 100644
--- a/drivers/staging/arlan/arlan.h
+++ b/drivers/staging/arlan/arlan.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1997 Cullen Jennings
- * Copyright (C) 1998 Elmer.Joandi@ut.ee, +37-255-13500
+ * Copyright (C) 1998 Elmer.Joandi@ut.ee, +37-255-13500
* GNU General Public License applies
*/
@@ -20,14 +20,14 @@
#include <linux/init.h>
#include <linux/bitops.h>
#include <asm/system.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
-//#define ARLAN_DEBUGGING 1
+/* #define ARLAN_DEBUGGING 1 */
#define ARLAN_PROC_INTERFACE
#define MAX_ARLANS 4 /* not more than 4 ! */
@@ -51,8 +51,8 @@ extern int arlan_debug;
extern int arlan_entry_debug;
extern int arlan_exit_debug;
extern int testMemory;
-extern int arlan_command(struct net_device * dev, int command);
-
+extern int arlan_command(struct net_device *dev, int command);
+
#define SIDUNKNOWN -1
#define radioNodeIdUNKNOWN -1
#define irqUNKNOWN 0
@@ -65,22 +65,21 @@ extern int arlan_command(struct net_device * dev, int command);
#define registrationModeUNKNOWN -1
-#define IFDEBUG( L ) if ( (L) & arlan_debug )
-#define ARLAN_FAKE_HDR_LEN 12
+#define IFDEBUG(L) if ((L) & arlan_debug)
+#define ARLAN_FAKE_HDR_LEN 12
#ifdef ARLAN_DEBUGGING
#define DEBUG 1
#define ARLAN_ENTRY_EXIT_DEBUGGING 1
- #define ARLAN_DEBUG(a,b) printk(KERN_DEBUG a, b)
+ #define ARLAN_DEBUG(a, b) printk(KERN_DEBUG a, b)
#else
- #define ARLAN_DEBUG(a,b)
+ #define ARLAN_DEBUG(a, b)
#endif
#define ARLAN_SHMEM_SIZE 0x2000
-struct arlan_shmem
-{
- /* Header Signature */
+struct arlan_shmem {
+ /* Header Signature */
volatile char textRegion[48];
volatile u_char resetFlag;
volatile u_char diagnosticInfo;
@@ -91,10 +90,10 @@ struct arlan_shmem
volatile u_char hardwareType;
volatile u_char majorHardwareVersion;
volatile u_char minorHardwareVersion;
- volatile u_char radioModule;// shows EEPROM, can be overridden at 0x111
- volatile u_char defaultChannelSet; // shows EEProm, can be overriiden at 0x10A
+ volatile u_char radioModule;/* shows EEPROM, can be overridden at 0x111 */
+ volatile u_char defaultChannelSet; /* shows EEProm, can be overriiden at 0x10A */
volatile u_char _2[47];
-
+
/* Control/Status Block - 0x0080 */
volatile u_char interruptInProgress; /* not used by lancpu */
volatile u_char cntrlRegImage; /* not used by lancpu */
@@ -113,7 +112,7 @@ struct arlan_shmem
volatile u_char rxQuality;
volatile u_char scrambled;
volatile u_char _4[1];
-
+
/* Transmit Status - 0x00b0 */
volatile u_char txStatus;
volatile u_char txAckQuality;
@@ -151,7 +150,7 @@ struct arlan_shmem
volatile u_short routerId;
volatile u_char _10[9];
volatile u_char txAttenuation;
- volatile u_char systemId[4];
+ volatile u_char systemId[4];
volatile u_short globalChecksum;
volatile u_char _11[4];
volatile u_short maxDatagramSize;
@@ -207,19 +206,19 @@ struct arlan_shmem
volatile u_char hostcpuLock;
volatile u_char lancpuLock;
volatile u_char resetTime[18];
-
+
volatile u_char numDatagramsTransmitted[4];
volatile u_char numReTransmissions[4];
volatile u_char numFramesDiscarded[4];
volatile u_char numDatagramsReceived[4];
volatile u_char numDuplicateReceivedFrames[4];
volatile u_char numDatagramsDiscarded[4];
-
+
volatile u_short maxNumReTransmitDatagram;
volatile u_short maxNumReTransmitFrames;
volatile u_short maxNumConsecutiveDuplicateFrames;
/* misaligned here so we have to go to characters */
-
+
volatile u_char numBytesTransmitted[4];
volatile u_char numBytesReceived[4];
volatile u_char numCRCErrors[4];
@@ -259,7 +258,7 @@ struct arlan_conf_stru {
int channelNumber;
int scramblingDisable;
int txAttenuation;
- int systemId;
+ int systemId;
int maxDatagramSize;
int maxFrameSize;
int maxRetries;
@@ -316,8 +315,7 @@ struct arlan_conf_stru {
extern struct arlan_conf_stru arlan_conf[MAX_ARLANS];
-struct TxParam
-{
+struct TxParam {
volatile short offset;
volatile short length;
volatile u_char dest[6];
@@ -330,12 +328,12 @@ struct TxParam
#define TX_RING_SIZE 2
/* Information that need to be kept for each board. */
struct arlan_private {
- struct arlan_shmem __iomem * card;
- struct arlan_shmem * conf;
+ struct arlan_shmem __iomem *card;
+ struct arlan_shmem *conf;
- struct arlan_conf_stru * Conf;
+ struct arlan_conf_stru *Conf;
int bad;
- int reset;
+ int reset;
unsigned long lastReset;
struct timer_list timer;
struct timer_list tx_delay_timer;
@@ -407,38 +405,38 @@ struct arlan_private {
#define TXBuffStart(dev) offsetof(struct arlan_shmem, txBuffer)
#define TXBuffEnd(dev) offsetof(struct arlan_shmem, xxBuffer)
-
-#define READSHM(to,from,atype) {\
+
+#define READSHM(to, from, atype) {\
atype tmp;\
- memcpy_fromio(&(tmp),&(from),sizeof(atype));\
+ memcpy_fromio(&(tmp), &(from), sizeof(atype));\
to = tmp;\
}
-#define READSHMEM(from,atype)\
+#define READSHMEM(from, atype)\
atype from; \
READSHM(from, arlan->from, atype);
-#define WRITESHM(to,from,atype) \
+#define WRITESHM(to, from, atype) \
{ atype tmpSHM = from;\
- memcpy_toio(&(to),&tmpSHM,sizeof(atype));\
+ memcpy_toio(&(to), &tmpSHM, sizeof(atype));\
}
-#define DEBUGSHM(levelSHM,stringSHM,stuff,atype) \
+#define DEBUGSHM(levelSHM, stringSHM, stuff, atype) \
{ atype tmpSHM; \
- memcpy_fromio(&tmpSHM,&(stuff),sizeof(atype));\
- IFDEBUG(levelSHM) printk(stringSHM,tmpSHM);\
+ memcpy_fromio(&tmpSHM, &(stuff), sizeof(atype));\
+ IFDEBUG(levelSHM) printk(stringSHM, tmpSHM);\
}
#define WRITESHMB(to, val) \
- writeb(val,&(to))
+ writeb(val, &(to))
#define READSHMB(to) \
readb(&(to))
#define WRITESHMS(to, val) \
- writew(val,&(to))
+ writew(val, &(to))
#define READSHMS(to) \
readw(&(to))
#define WRITESHMI(to, val) \
- writel(val,&(to))
+ writel(val, &(to))
#define READSHMI(to) \
readl(&(to))
@@ -447,51 +445,51 @@ struct arlan_private {
#define registrationBad(dev)\
- ( ( READSHMB(((struct arlan_private *)netdev_priv(dev))->card->registrationMode) > 0) && \
- ( READSHMB(((struct arlan_private *)netdev_priv(dev))->card->registrationStatus) == 0) )
+ (( READSHMB(((struct arlan_private *)netdev_priv(dev))->card->registrationMode) > 0) && \
+ ( READSHMB(((struct arlan_private *)netdev_priv(dev))->card->registrationStatus) == 0))
#define readControlRegister(dev)\
- READSHMB(((struct arlan_private *)netdev_priv(dev))->card->cntrlRegImage)
+ READSHMB(((struct arlan_private *)netdev_priv(dev))->card->cntrlRegImage)
-#define writeControlRegister(dev, v){\
- WRITESHMB(((struct arlan_private *)netdev_priv(dev))->card->cntrlRegImage ,((v) &0xF) );\
- WRITESHMB(((struct arlan_private *)netdev_priv(dev))->card->controlRegister ,(v) );}
+#define writeControlRegister(dev, v) {\
+ WRITESHMB(((struct arlan_private *)netdev_priv(dev))->card->cntrlRegImage, ((v) & 0xF));\
+ WRITESHMB(((struct arlan_private *)netdev_priv(dev))->card->controlRegister, (v)); }
#define arlan_interrupt_lancpu(dev) {\
int cr; \
\
cr = readControlRegister(dev);\
- if (cr & ARLAN_CHANNEL_ATTENTION){ \
+ if (cr & ARLAN_CHANNEL_ATTENTION) { \
writeControlRegister(dev, (cr & ~ARLAN_CHANNEL_ATTENTION));\
- }else \
+ } else \
writeControlRegister(dev, (cr | ARLAN_CHANNEL_ATTENTION));\
}
-#define clearChannelAttention(dev){ \
- writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_CHANNEL_ATTENTION);}
+#define clearChannelAttention(dev) { \
+ writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_CHANNEL_ATTENTION); }
#define setHardwareReset(dev) {\
- writeControlRegister(dev,readControlRegister(dev) | ARLAN_RESET);}
+ writeControlRegister(dev, readControlRegister(dev) | ARLAN_RESET); }
#define clearHardwareReset(dev) {\
- writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_RESET);}
-#define setInterruptEnable(dev){\
- writeControlRegister(dev,readControlRegister(dev) | ARLAN_INTERRUPT_ENABLE) ;}
-#define clearInterruptEnable(dev){\
- writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_INTERRUPT_ENABLE) ;}
-#define setClearInterrupt(dev){\
- writeControlRegister(dev,readControlRegister(dev) | ARLAN_CLEAR_INTERRUPT) ;}
-#define clearClearInterrupt(dev){\
- writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_CLEAR_INTERRUPT);}
-#define setPowerOff(dev){\
- writeControlRegister(dev,readControlRegister(dev) | (ARLAN_POWER && ARLAN_ACCESS));\
- writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_ACCESS);}
-#define setPowerOn(dev){\
- writeControlRegister(dev,readControlRegister(dev) & ~(ARLAN_POWER)); }
-#define arlan_lock_card_access(dev){\
- writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_ACCESS);}
-#define arlan_unlock_card_access(dev){\
- writeControlRegister(dev,readControlRegister(dev) | ARLAN_ACCESS ); }
+ writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_RESET); }
+#define setInterruptEnable(dev) {\
+ writeControlRegister(dev, readControlRegister(dev) | ARLAN_INTERRUPT_ENABLE) ; }
+#define clearInterruptEnable(dev) {\
+ writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_INTERRUPT_ENABLE) ; }
+#define setClearInterrupt(dev) {\
+ writeControlRegister(dev, readControlRegister(dev) | ARLAN_CLEAR_INTERRUPT) ; }
+#define clearClearInterrupt(dev) {\
+ writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_CLEAR_INTERRUPT); }
+#define setPowerOff(dev) {\
+ writeControlRegister(dev, readControlRegister(dev) | (ARLAN_POWER && ARLAN_ACCESS));\
+ writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_ACCESS); }
+#define setPowerOn(dev) {\
+ writeControlRegister(dev, readControlRegister(dev) & ~(ARLAN_POWER)); }
+#define arlan_lock_card_access(dev) {\
+ writeControlRegister(dev, readControlRegister(dev) & ~ARLAN_ACCESS); }
+#define arlan_unlock_card_access(dev) {\
+ writeControlRegister(dev, readControlRegister(dev) | ARLAN_ACCESS); }
@@ -525,7 +523,6 @@ struct arlan_private {
| ARLAN_COMMAND_RESET)
-
#define ARLAN_DEBUG_CHAIN_LOCKS 0x00001
#define ARLAN_DEBUG_RESET 0x00002
#define ARLAN_DEBUG_TIMING 0x00004
@@ -536,4 +533,3 @@ struct arlan_private {
#define ARLAN_DEBUG_INTERRUPT 0x00080
#define ARLAN_DEBUG_STARTUP 0x00100
#define ARLAN_DEBUG_SHUTDOWN 0x00200
-
diff --git a/drivers/staging/asus_oled/asus_oled.c b/drivers/staging/asus_oled/asus_oled.c
index 43c57b7688a..7ebecc92c61 100644
--- a/drivers/staging/asus_oled/asus_oled.c
+++ b/drivers/staging/asus_oled/asus_oled.c
@@ -52,6 +52,10 @@
#define ASUS_OLED_DISP_HEIGHT 32
#define ASUS_OLED_PACKET_BUF_SIZE 256
+#define USB_VENDOR_ID_ASUS 0x0b05
+#define USB_DEVICE_ID_ASUS_LCM 0x1726
+#define USB_DEVICE_ID_ASUS_LCM2 0x175b
+
MODULE_AUTHOR("Jakub Schmidtke, sjakub@gmail.com");
MODULE_DESCRIPTION("Asus OLED Driver v" ASUS_OLED_VERSION);
MODULE_LICENSE("GPL");
@@ -83,18 +87,20 @@ struct oled_dev_desc_str {
};
/* table of devices that work with this driver */
-static struct usb_device_id id_table[] = {
+static const struct usb_device_id id_table[] = {
/* Asus G1/G2 (and variants)*/
- { USB_DEVICE(0x0b05, 0x1726) },
+ { USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM) },
/* Asus G50V (and possibly others - G70? G71?)*/
- { USB_DEVICE(0x0b05, 0x175b) },
+ { USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2) },
{ },
};
/* parameters of specific devices */
static struct oled_dev_desc_str oled_dev_desc_table[] = {
- { 0x0b05, 0x1726, 128, PACK_MODE_G1, "G1/G2" },
- { 0x0b05, 0x175b, 256, PACK_MODE_G50, "G50" },
+ { USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM, 128, PACK_MODE_G1,
+ "G1/G2" },
+ { USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_LCM2, 256, PACK_MODE_G50,
+ "G50" },
{ },
};
@@ -424,6 +430,11 @@ static ssize_t odev_set_picture(struct asus_oled_dev *odev,
kfree(odev->buf);
odev->buf = kmalloc(odev->buf_size, GFP_KERNEL);
+ if (odev->buf == NULL) {
+ odev->buf_size = 0;
+ printk(ASUS_OLED_ERROR "Out of memory!\n");
+ return -ENOMEM;
+ }
memset(odev->buf, 0xff, odev->buf_size);
@@ -759,13 +770,8 @@ static struct usb_driver oled_driver = {
.id_table = id_table,
};
-static ssize_t version_show(struct class *dev, char *buf)
-{
- return sprintf(buf, ASUS_OLED_UNDERSCORE_NAME " %s\n",
- ASUS_OLED_VERSION);
-}
-
-static CLASS_ATTR(version, S_IRUGO, version_show, NULL);
+static CLASS_ATTR_STRING(version, S_IRUGO,
+ ASUS_OLED_UNDERSCORE_NAME " " ASUS_OLED_VERSION);
static int __init asus_oled_init(void)
{
@@ -777,7 +783,7 @@ static int __init asus_oled_init(void)
return PTR_ERR(oled_class);
}
- retval = class_create_file(oled_class, &class_attr_version);
+ retval = class_create_file(oled_class, &class_attr_version.attr);
if (retval) {
err("Error creating class version file");
goto error;
@@ -799,7 +805,7 @@ error:
static void __exit asus_oled_exit(void)
{
- class_remove_file(oled_class, &class_attr_version);
+ class_remove_file(oled_class, &class_attr_version.attr);
class_destroy(oled_class);
usb_deregister(&oled_driver);
diff --git a/drivers/staging/b3dfg/Kconfig b/drivers/staging/b3dfg/Kconfig
deleted file mode 100644
index 9e6573cf97d..00000000000
--- a/drivers/staging/b3dfg/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-config B3DFG
- tristate "Brontes 3d Frame Framegrabber"
- depends on PCI
- default n
- ---help---
- This driver provides support for the Brontes 3d Framegrabber
- PCI card.
-
- To compile this driver as a module, choose M here. The module
- will be called b3dfg.
diff --git a/drivers/staging/b3dfg/Makefile b/drivers/staging/b3dfg/Makefile
deleted file mode 100644
index 91f439ffc17..00000000000
--- a/drivers/staging/b3dfg/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_B3DFG) += b3dfg.o
diff --git a/drivers/staging/b3dfg/TODO b/drivers/staging/b3dfg/TODO
deleted file mode 100644
index f5a9298b9ac..00000000000
--- a/drivers/staging/b3dfg/TODO
+++ /dev/null
@@ -1,4 +0,0 @@
-
- - queue/wait buffer presents filltime results for each frame?
- - counting of dropped frames
- - review endianness
diff --git a/drivers/staging/b3dfg/b3dfg.c b/drivers/staging/b3dfg/b3dfg.c
deleted file mode 100644
index 4a43c51c172..00000000000
--- a/drivers/staging/b3dfg/b3dfg.c
+++ /dev/null
@@ -1,1100 +0,0 @@
- /*
- * Brontes PCI frame grabber driver
- *
- * Copyright (C) 2008 3M Company
- * Contact: Justin Bronder <jsbronder@brontes3d.com>
- * Original Authors: Daniel Drake <ddrake@brontes3d.com>
- * Duane Griffin <duaneg@dghda.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/device.h>
-#include <linux/fs.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/ioctl.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/types.h>
-#include <linux/cdev.h>
-#include <linux/list.h>
-#include <linux/poll.h>
-#include <linux/wait.h>
-#include <linux/mm.h>
-#include <linux/uaccess.h>
-#include <linux/sched.h>
-
-static unsigned int b3dfg_nbuf = 2;
-
-module_param_named(buffer_count, b3dfg_nbuf, uint, 0444);
-
-MODULE_PARM_DESC(buffer_count, "Number of buffers (min 2, default 2)");
-
-MODULE_AUTHOR("Daniel Drake <ddrake@brontes3d.com>");
-MODULE_DESCRIPTION("Brontes frame grabber driver");
-MODULE_LICENSE("GPL");
-
-#define DRIVER_NAME "b3dfg"
-#define B3DFG_MAX_DEVS 4
-#define B3DFG_FRAMES_PER_BUFFER 3
-
-#define B3DFG_BAR_REGS 0
-#define B3DFG_REGS_LENGTH 0x10000
-
-#define B3DFG_IOC_MAGIC 0xb3 /* dfg :-) */
-#define B3DFG_IOCGFRMSZ _IOR(B3DFG_IOC_MAGIC, 1, int)
-#define B3DFG_IOCTNUMBUFS _IO(B3DFG_IOC_MAGIC, 2)
-#define B3DFG_IOCTTRANS _IO(B3DFG_IOC_MAGIC, 3)
-#define B3DFG_IOCTQUEUEBUF _IO(B3DFG_IOC_MAGIC, 4)
-#define B3DFG_IOCTPOLLBUF _IOWR(B3DFG_IOC_MAGIC, 5, struct b3dfg_poll)
-#define B3DFG_IOCTWAITBUF _IOWR(B3DFG_IOC_MAGIC, 6, struct b3dfg_wait)
-#define B3DFG_IOCGWANDSTAT _IOR(B3DFG_IOC_MAGIC, 7, int)
-
-enum {
- /* number of 4kb pages per frame */
- B3D_REG_FRM_SIZE = 0x0,
-
- /* bit 0: set to enable interrupts
- * bit 1: set to enable cable status change interrupts */
- B3D_REG_HW_CTRL = 0x4,
-
- /* bit 0-1 - 1-based ID of next pending frame transfer (0 = none)
- * bit 2 indicates the previous DMA transfer has completed
- * bit 3 indicates wand cable status change
- * bit 8:15 - counter of number of discarded triplets */
- B3D_REG_DMA_STS = 0x8,
-
- /* bit 0: wand status (1 = present, 0 = disconnected) */
- B3D_REG_WAND_STS = 0xc,
-
- /* bus address for DMA transfers. lower 2 bits must be zero because DMA
- * works with 32 bit word size. */
- B3D_REG_EC220_DMA_ADDR = 0x8000,
-
- /* bit 20:0 - number of 32 bit words to be transferred
- * bit 21:31 - reserved */
- B3D_REG_EC220_TRF_SIZE = 0x8004,
-
- /* bit 0 - error bit
- * bit 1 - interrupt bit (set to generate interrupt at end of transfer)
- * bit 2 - start bit (set to start transfer)
- * bit 3 - direction (0 = DMA_TO_DEVICE, 1 = DMA_FROM_DEVICE
- * bit 4:31 - reserved */
- B3D_REG_EC220_DMA_STS = 0x8008,
-};
-
-enum b3dfg_buffer_state {
- B3DFG_BUFFER_POLLED = 0,
- B3DFG_BUFFER_PENDING,
- B3DFG_BUFFER_POPULATED,
-};
-
-struct b3dfg_buffer {
- unsigned char *frame[B3DFG_FRAMES_PER_BUFFER];
- struct list_head list;
- u8 state;
-};
-
-struct b3dfg_dev {
-
- /* no protection needed: all finalized at initialization time */
- struct pci_dev *pdev;
- struct cdev chardev;
- struct device *dev;
- void __iomem *regs;
- unsigned int frame_size;
-
- /*
- * Protects buffer state, including buffer_queue, triplet_ready,
- * cur_dma_frame_idx & cur_dma_frame_addr.
- */
- spinlock_t buffer_lock;
- struct b3dfg_buffer *buffers;
- struct list_head buffer_queue;
-
- /* Last frame in triplet transferred (-1 if none). */
- int cur_dma_frame_idx;
-
- /* Current frame's address for DMA. */
- dma_addr_t cur_dma_frame_addr;
-
- /*
- * Protects cstate_tstamp.
- * Nests inside buffer_lock.
- */
- spinlock_t cstate_lock;
- unsigned long cstate_tstamp;
-
- /*
- * Protects triplets_dropped.
- * Nests inside buffers_lock.
- */
- spinlock_t triplets_dropped_lock;
- unsigned int triplets_dropped;
-
- wait_queue_head_t buffer_waitqueue;
-
- unsigned int transmission_enabled:1;
- unsigned int triplet_ready:1;
-};
-
-static u8 b3dfg_devices[B3DFG_MAX_DEVS];
-
-static struct class *b3dfg_class;
-static dev_t b3dfg_devt;
-
-static const struct pci_device_id b3dfg_ids[] __devinitdata = {
- { PCI_DEVICE(0x0b3d, 0x0001) },
- { },
-};
-
-MODULE_DEVICE_TABLE(pci, b3dfg_ids);
-
-/***** user-visible types *****/
-
-struct b3dfg_poll {
- int buffer_idx;
- unsigned int triplets_dropped;
-};
-
-struct b3dfg_wait {
- int buffer_idx;
- unsigned int timeout;
- unsigned int triplets_dropped;
-};
-
-/**** register I/O ****/
-
-static u32 b3dfg_read32(struct b3dfg_dev *fgdev, u16 reg)
-{
- return ioread32(fgdev->regs + reg);
-}
-
-static void b3dfg_write32(struct b3dfg_dev *fgdev, u16 reg, u32 value)
-{
- iowrite32(value, fgdev->regs + reg);
-}
-
-/**** buffer management ****/
-
-/*
- * Program EC220 for transfer of a specific frame.
- * Called with buffer_lock held.
- */
-static int setup_frame_transfer(struct b3dfg_dev *fgdev,
- struct b3dfg_buffer *buf, int frame)
-{
- unsigned char *frm_addr;
- dma_addr_t frm_addr_dma;
- unsigned int frm_size = fgdev->frame_size;
-
- frm_addr = buf->frame[frame];
- frm_addr_dma = pci_map_single(fgdev->pdev, frm_addr,
- frm_size, PCI_DMA_FROMDEVICE);
- if (pci_dma_mapping_error(fgdev->pdev, frm_addr_dma))
- return -ENOMEM;
-
- fgdev->cur_dma_frame_addr = frm_addr_dma;
- fgdev->cur_dma_frame_idx = frame;
-
- b3dfg_write32(fgdev, B3D_REG_EC220_DMA_ADDR,
- cpu_to_le32(frm_addr_dma));
- b3dfg_write32(fgdev, B3D_REG_EC220_TRF_SIZE,
- cpu_to_le32(frm_size >> 2));
- b3dfg_write32(fgdev, B3D_REG_EC220_DMA_STS, 0xf);
-
- return 0;
-}
-
-/* Caller should hold buffer lock */
-static void dequeue_all_buffers(struct b3dfg_dev *fgdev)
-{
- int i;
- for (i = 0; i < b3dfg_nbuf; i++) {
- struct b3dfg_buffer *buf = &fgdev->buffers[i];
- buf->state = B3DFG_BUFFER_POLLED;
- list_del_init(&buf->list);
- }
-}
-
-/* queue a buffer to receive data */
-static int queue_buffer(struct b3dfg_dev *fgdev, int bufidx)
-{
- struct device *dev = &fgdev->pdev->dev;
- struct b3dfg_buffer *buf;
- unsigned long flags;
- int r = 0;
-
- spin_lock_irqsave(&fgdev->buffer_lock, flags);
- if (bufidx < 0 || bufidx >= b3dfg_nbuf) {
- dev_dbg(dev, "Invalid buffer index, %d\n", bufidx);
- r = -ENOENT;
- goto out;
- }
- buf = &fgdev->buffers[bufidx];
-
- if (unlikely(buf->state == B3DFG_BUFFER_PENDING)) {
- dev_dbg(dev, "buffer %d is already queued\n", bufidx);
- r = -EINVAL;
- goto out;
- }
-
- buf->state = B3DFG_BUFFER_PENDING;
- list_add_tail(&buf->list, &fgdev->buffer_queue);
-
- if (fgdev->transmission_enabled && fgdev->triplet_ready) {
- dev_dbg(dev, "triplet is ready, pushing immediately\n");
- fgdev->triplet_ready = 0;
- r = setup_frame_transfer(fgdev, buf, 0);
- if (r)
- dev_err(dev, "unable to map DMA buffer\n");
- }
-
-out:
- spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
- return r;
-}
-
-/* non-blocking buffer poll. returns 1 if data is present in the buffer,
- * 0 otherwise */
-static int poll_buffer(struct b3dfg_dev *fgdev, void __user *arg)
-{
- struct device *dev = &fgdev->pdev->dev;
- struct b3dfg_poll p;
- struct b3dfg_buffer *buf;
- unsigned long flags;
- int r = 1;
- int arg_out = 0;
-
- if (copy_from_user(&p, arg, sizeof(p)))
- return -EFAULT;
-
- if (unlikely(!fgdev->transmission_enabled)) {
- dev_dbg(dev, "cannot poll, transmission disabled\n");
- return -EINVAL;
- }
-
- if (p.buffer_idx < 0 || p.buffer_idx >= b3dfg_nbuf)
- return -ENOENT;
-
- buf = &fgdev->buffers[p.buffer_idx];
-
- spin_lock_irqsave(&fgdev->buffer_lock, flags);
-
- if (likely(buf->state == B3DFG_BUFFER_POPULATED)) {
- arg_out = 1;
- buf->state = B3DFG_BUFFER_POLLED;
-
- /* IRQs already disabled by spin_lock_irqsave above. */
- spin_lock(&fgdev->triplets_dropped_lock);
- p.triplets_dropped = fgdev->triplets_dropped;
- fgdev->triplets_dropped = 0;
- spin_unlock(&fgdev->triplets_dropped_lock);
- } else {
- r = 0;
- }
-
- spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-
- if (arg_out && copy_to_user(arg, &p, sizeof(p)))
- r = -EFAULT;
-
- return r;
-}
-
-static unsigned long get_cstate_change(struct b3dfg_dev *fgdev)
-{
- unsigned long flags, when;
-
- spin_lock_irqsave(&fgdev->cstate_lock, flags);
- when = fgdev->cstate_tstamp;
- spin_unlock_irqrestore(&fgdev->cstate_lock, flags);
- return when;
-}
-
-static int is_event_ready(struct b3dfg_dev *fgdev, struct b3dfg_buffer *buf,
- unsigned long when)
-{
- int result;
- unsigned long flags;
-
- spin_lock_irqsave(&fgdev->buffer_lock, flags);
- spin_lock(&fgdev->cstate_lock);
- result = (!fgdev->transmission_enabled ||
- buf->state == B3DFG_BUFFER_POPULATED ||
- when != fgdev->cstate_tstamp);
- spin_unlock(&fgdev->cstate_lock);
- spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-
- return result;
-}
-
-/* sleep until a specific buffer becomes populated */
-static int wait_buffer(struct b3dfg_dev *fgdev, void __user *arg)
-{
- struct device *dev = &fgdev->pdev->dev;
- struct b3dfg_wait w;
- struct b3dfg_buffer *buf;
- unsigned long flags, when;
- int r;
-
- if (copy_from_user(&w, arg, sizeof(w)))
- return -EFAULT;
-
- if (!fgdev->transmission_enabled) {
- dev_dbg(dev, "cannot wait, transmission disabled\n");
- return -EINVAL;
- }
-
- if (w.buffer_idx < 0 || w.buffer_idx >= b3dfg_nbuf)
- return -ENOENT;
-
- buf = &fgdev->buffers[w.buffer_idx];
-
- spin_lock_irqsave(&fgdev->buffer_lock, flags);
-
- if (buf->state == B3DFG_BUFFER_POPULATED) {
- r = w.timeout;
- goto out_triplets_dropped;
- }
-
- spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-
- when = get_cstate_change(fgdev);
- if (w.timeout > 0) {
- r = wait_event_interruptible_timeout(fgdev->buffer_waitqueue,
- is_event_ready(fgdev, buf, when),
- (w.timeout * HZ) / 1000);
-
- if (unlikely(r < 0))
- goto out;
-
- w.timeout = r * 1000 / HZ;
- } else {
- r = wait_event_interruptible(fgdev->buffer_waitqueue,
- is_event_ready(fgdev, buf, when));
-
- if (unlikely(r)) {
- r = -ERESTARTSYS;
- goto out;
- }
- }
-
- /* TODO: Inform the user via field(s) in w? */
- if (!fgdev->transmission_enabled || when != get_cstate_change(fgdev)) {
- r = -EINVAL;
- goto out;
- }
-
- spin_lock_irqsave(&fgdev->buffer_lock, flags);
-
- if (buf->state != B3DFG_BUFFER_POPULATED) {
- r = -ETIMEDOUT;
- goto out_unlock;
- }
-
- buf->state = B3DFG_BUFFER_POLLED;
-
-out_triplets_dropped:
-
- /* IRQs already disabled by spin_lock_irqsave above. */
- spin_lock(&fgdev->triplets_dropped_lock);
- w.triplets_dropped = fgdev->triplets_dropped;
- fgdev->triplets_dropped = 0;
- spin_unlock(&fgdev->triplets_dropped_lock);
-
-out_unlock:
- spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
- if (copy_to_user(arg, &w, sizeof(w)))
- r = -EFAULT;
-out:
- return r;
-}
-
-/* mmap page fault handler */
-static int b3dfg_vma_fault(struct vm_area_struct *vma,
- struct vm_fault *vmf)
-{
- struct b3dfg_dev *fgdev = vma->vm_file->private_data;
- unsigned long off = vmf->pgoff << PAGE_SHIFT;
- unsigned int frame_size = fgdev->frame_size;
- unsigned int buf_size = frame_size * B3DFG_FRAMES_PER_BUFFER;
- unsigned char *addr;
-
- /* determine which buffer the offset lies within */
- unsigned int buf_idx = off / buf_size;
- /* and the offset into the buffer */
- unsigned int buf_off = off % buf_size;
-
- /* determine which frame inside the buffer the offset lies in */
- unsigned int frm_idx = buf_off / frame_size;
- /* and the offset into the frame */
- unsigned int frm_off = buf_off % frame_size;
-
- if (unlikely(buf_idx >= b3dfg_nbuf))
- return VM_FAULT_SIGBUS;
-
- addr = fgdev->buffers[buf_idx].frame[frm_idx] + frm_off;
- vm_insert_pfn(vma, (unsigned long)vmf->virtual_address,
- virt_to_phys(addr) >> PAGE_SHIFT);
-
- return VM_FAULT_NOPAGE;
-}
-
-static struct vm_operations_struct b3dfg_vm_ops = {
- .fault = b3dfg_vma_fault,
-};
-
-static int get_wand_status(struct b3dfg_dev *fgdev, int __user *arg)
-{
- u32 wndstat = b3dfg_read32(fgdev, B3D_REG_WAND_STS);
- dev_dbg(&fgdev->pdev->dev, "wand status %x\n", wndstat);
- return __put_user(wndstat & 0x1, arg);
-}
-
-static int enable_transmission(struct b3dfg_dev *fgdev)
-{
- unsigned long flags;
- struct device *dev = &fgdev->pdev->dev;
-
- dev_dbg(dev, "enable transmission\n");
-
- /* check the cable is plugged in. */
- if (!b3dfg_read32(fgdev, B3D_REG_WAND_STS)) {
- dev_dbg(dev, "cannot start transmission without wand\n");
- return -EINVAL;
- }
-
- spin_lock_irqsave(&fgdev->buffer_lock, flags);
-
- /* Handle racing enable_transmission calls. */
- if (fgdev->transmission_enabled) {
- spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
- goto out;
- }
-
- spin_lock(&fgdev->triplets_dropped_lock);
- fgdev->triplets_dropped = 0;
- spin_unlock(&fgdev->triplets_dropped_lock);
-
- fgdev->triplet_ready = 0;
- fgdev->cur_dma_frame_idx = -1;
- fgdev->transmission_enabled = 1;
-
- spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-
- /* Enable DMA and cable status interrupts. */
- b3dfg_write32(fgdev, B3D_REG_HW_CTRL, 0x03);
-
-out:
- return 0;
-}
-
-static void disable_transmission(struct b3dfg_dev *fgdev)
-{
- struct device *dev = &fgdev->pdev->dev;
- unsigned long flags;
- u32 tmp;
-
- dev_dbg(dev, "disable transmission\n");
-
- /* guarantee that no more interrupts will be serviced */
- spin_lock_irqsave(&fgdev->buffer_lock, flags);
- fgdev->transmission_enabled = 0;
-
- b3dfg_write32(fgdev, B3D_REG_HW_CTRL, 0);
-
- /* FIXME: temporary debugging only. if the board stops transmitting,
- * hitting ctrl+c and seeing this message is useful for determining
- * the state of the board. */
- tmp = b3dfg_read32(fgdev, B3D_REG_DMA_STS);
- dev_dbg(dev, "DMA_STS reads %x after TX stopped\n", tmp);
-
- dequeue_all_buffers(fgdev);
- spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-
- wake_up_interruptible(&fgdev->buffer_waitqueue);
-}
-
-static int set_transmission(struct b3dfg_dev *fgdev, int enabled)
-{
- int res = 0;
-
- if (enabled && !fgdev->transmission_enabled)
- res = enable_transmission(fgdev);
- else if (!enabled && fgdev->transmission_enabled)
- disable_transmission(fgdev);
-
- return res;
-}
-
-/* Called in interrupt context. */
-static void handle_cstate_unplug(struct b3dfg_dev *fgdev)
-{
- /* Disable all interrupts. */
- b3dfg_write32(fgdev, B3D_REG_HW_CTRL, 0);
-
- /* Stop transmission. */
- spin_lock(&fgdev->buffer_lock);
- fgdev->transmission_enabled = 0;
-
- fgdev->cur_dma_frame_idx = -1;
- fgdev->triplet_ready = 0;
- if (fgdev->cur_dma_frame_addr) {
- pci_unmap_single(fgdev->pdev, fgdev->cur_dma_frame_addr,
- fgdev->frame_size, PCI_DMA_FROMDEVICE);
- fgdev->cur_dma_frame_addr = 0;
- }
- dequeue_all_buffers(fgdev);
- spin_unlock(&fgdev->buffer_lock);
-}
-
-/* Called in interrupt context. */
-static void handle_cstate_change(struct b3dfg_dev *fgdev)
-{
- u32 cstate = b3dfg_read32(fgdev, B3D_REG_WAND_STS);
- unsigned long when;
- struct device *dev = &fgdev->pdev->dev;
-
- dev_dbg(dev, "cable state change: %u\n", cstate);
-
- /*
- * When the wand is unplugged we reset our state. The hardware will
- * have done the same internally.
- *
- * Note we should never see a cable *plugged* event, as interrupts
- * should only be enabled when transmitting, which requires the cable
- * to be plugged. If we do see one it probably means the cable has been
- * unplugged and re-plugged very rapidly. Possibly because it has a
- * broken wire and is momentarily losing contact.
- *
- * TODO: At the moment if you plug in the cable then enable transmission
- * the hardware will raise a couple of spurious interrupts, so
- * just ignore them for now.
- *
- * Once the hardware is fixed we should complain and treat it as an
- * unplug. Or at least track how frequently it is happening and do
- * so if too many come in.
- */
- if (cstate) {
- dev_warn(dev, "ignoring unexpected plug event\n");
- return;
- }
- handle_cstate_unplug(fgdev);
-
- /*
- * Record cable state change timestamp & wake anyone waiting
- * on a cable state change. Be paranoid about ensuring events
- * are not missed if we somehow get two interrupts in a jiffy.
- */
- spin_lock(&fgdev->cstate_lock);
- when = jiffies_64;
- if (when <= fgdev->cstate_tstamp)
- when = fgdev->cstate_tstamp + 1;
- fgdev->cstate_tstamp = when;
- wake_up_interruptible(&fgdev->buffer_waitqueue);
- spin_unlock(&fgdev->cstate_lock);
-}
-
-/* Called with buffer_lock held. */
-static void transfer_complete(struct b3dfg_dev *fgdev)
-{
- struct b3dfg_buffer *buf;
- struct device *dev = &fgdev->pdev->dev;
-
- pci_unmap_single(fgdev->pdev, fgdev->cur_dma_frame_addr,
- fgdev->frame_size, PCI_DMA_FROMDEVICE);
- fgdev->cur_dma_frame_addr = 0;
-
- buf = list_entry(fgdev->buffer_queue.next, struct b3dfg_buffer, list);
-
- dev_dbg(dev, "handle frame completion\n");
- if (fgdev->cur_dma_frame_idx == B3DFG_FRAMES_PER_BUFFER - 1) {
-
- /* last frame of that triplet completed */
- dev_dbg(dev, "triplet completed\n");
- buf->state = B3DFG_BUFFER_POPULATED;
- list_del_init(&buf->list);
- wake_up_interruptible(&fgdev->buffer_waitqueue);
- }
-}
-
-/*
- * Called with buffer_lock held.
- *
- * Note that idx is the (1-based) *next* frame to be transferred, while
- * cur_dma_frame_idx is the (0-based) *last* frame to have been transferred (or
- * -1 if none). Thus there should be a difference of 2 between them.
- */
-static bool setup_next_frame_transfer(struct b3dfg_dev *fgdev, int idx)
-{
- struct b3dfg_buffer *buf;
- struct device *dev = &fgdev->pdev->dev;
- bool need_ack = 1;
-
- dev_dbg(dev, "program DMA transfer for next frame: %d\n", idx);
-
- buf = list_entry(fgdev->buffer_queue.next, struct b3dfg_buffer, list);
- if (idx == fgdev->cur_dma_frame_idx + 2) {
- if (setup_frame_transfer(fgdev, buf, idx - 1))
- dev_err(dev, "unable to map DMA buffer\n");
- need_ack = 0;
- } else {
- dev_err(dev, "frame mismatch, got %d, expected %d\n",
- idx, fgdev->cur_dma_frame_idx + 2);
-
- /* FIXME: handle dropped triplets here */
- }
-
- return need_ack;
-}
-
-static irqreturn_t b3dfg_intr(int irq, void *dev_id)
-{
- struct b3dfg_dev *fgdev = dev_id;
- struct device *dev = &fgdev->pdev->dev;
- u32 sts;
- u8 dropped;
- bool need_ack = 1;
- irqreturn_t res = IRQ_HANDLED;
-
- sts = b3dfg_read32(fgdev, B3D_REG_DMA_STS);
- if (unlikely(sts == 0)) {
- dev_warn(dev, "ignore interrupt, DMA status is 0\n");
- res = IRQ_NONE;
- goto out;
- }
-
- if (unlikely(!fgdev->transmission_enabled)) {
- dev_warn(dev, "ignore interrupt, TX disabled\n");
- res = IRQ_HANDLED;
- goto out;
- }
-
- /* Handle dropped frames, as reported by the hardware. */
- dropped = (sts >> 8) & 0xff;
- dev_dbg(dev, "intr: DMA_STS=%08x (drop=%d comp=%d next=%d)\n",
- sts, dropped, !!(sts & 0x4), sts & 0x3);
- if (unlikely(dropped > 0)) {
- spin_lock(&fgdev->triplets_dropped_lock);
- fgdev->triplets_dropped += dropped;
- spin_unlock(&fgdev->triplets_dropped_lock);
- }
-
- /* Handle a cable state change (i.e. the wand being unplugged). */
- if (sts & 0x08) {
- handle_cstate_change(fgdev);
- goto out;
- }
-
- spin_lock(&fgdev->buffer_lock);
- if (unlikely(list_empty(&fgdev->buffer_queue))) {
-
- /* FIXME need more sanity checking here */
- dev_info(dev, "buffer not ready for next transfer\n");
- fgdev->triplet_ready = 1;
- goto out_unlock;
- }
-
- /* Has a frame transfer been completed? */
- if (sts & 0x4) {
- u32 dma_status = b3dfg_read32(fgdev, B3D_REG_EC220_DMA_STS);
-
- /* Check for DMA errors reported by the hardware. */
- if (unlikely(dma_status & 0x1)) {
- dev_err(dev, "EC220 error: %08x\n", dma_status);
-
- /* FIXME flesh out error handling */
- goto out_unlock;
- }
-
- /* Sanity check, we should have a frame index at this point. */
- if (unlikely(fgdev->cur_dma_frame_idx == -1)) {
- dev_err(dev, "completed but no last idx?\n");
-
- /* FIXME flesh out error handling */
- goto out_unlock;
- }
-
- transfer_complete(fgdev);
- }
-
- /* Is there another frame transfer pending? */
- if (sts & 0x3)
- need_ack = setup_next_frame_transfer(fgdev, sts & 0x3);
- else
- fgdev->cur_dma_frame_idx = -1;
-
-out_unlock:
- spin_unlock(&fgdev->buffer_lock);
-out:
- if (need_ack) {
- dev_dbg(dev, "acknowledging interrupt\n");
- b3dfg_write32(fgdev, B3D_REG_EC220_DMA_STS, 0x0b);
- }
- return res;
-}
-
-static int b3dfg_open(struct inode *inode, struct file *filp)
-{
- struct b3dfg_dev *fgdev =
- container_of(inode->i_cdev, struct b3dfg_dev, chardev);
-
- dev_dbg(&fgdev->pdev->dev, "open\n");
- filp->private_data = fgdev;
- return 0;
-}
-
-static int b3dfg_release(struct inode *inode, struct file *filp)
-{
- struct b3dfg_dev *fgdev = filp->private_data;
- dev_dbg(&fgdev->pdev->dev, "release\n");
- disable_transmission(fgdev);
- return 0;
-}
-
-static long b3dfg_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
- struct b3dfg_dev *fgdev = filp->private_data;
-
- switch (cmd) {
- case B3DFG_IOCGFRMSZ:
- return __put_user(fgdev->frame_size, (int __user *) arg);
- case B3DFG_IOCGWANDSTAT:
- return get_wand_status(fgdev, (int __user *) arg);
- case B3DFG_IOCTTRANS:
- return set_transmission(fgdev, (int) arg);
- case B3DFG_IOCTQUEUEBUF:
- return queue_buffer(fgdev, (int) arg);
- case B3DFG_IOCTPOLLBUF:
- return poll_buffer(fgdev, (void __user *) arg);
- case B3DFG_IOCTWAITBUF:
- return wait_buffer(fgdev, (void __user *) arg);
- default:
- dev_dbg(&fgdev->pdev->dev, "unrecognised ioctl %x\n", cmd);
- return -EINVAL;
- }
-}
-
-static unsigned int b3dfg_poll(struct file *filp, poll_table *poll_table)
-{
- struct b3dfg_dev *fgdev = filp->private_data;
- unsigned long flags, when;
- int i;
- int r = 0;
-
- when = get_cstate_change(fgdev);
- poll_wait(filp, &fgdev->buffer_waitqueue, poll_table);
-
- spin_lock_irqsave(&fgdev->buffer_lock, flags);
- for (i = 0; i < b3dfg_nbuf; i++) {
- if (fgdev->buffers[i].state == B3DFG_BUFFER_POPULATED) {
- r = POLLIN | POLLRDNORM;
- break;
- }
- }
- spin_unlock_irqrestore(&fgdev->buffer_lock, flags);
-
- /* TODO: Confirm this is how we want to communicate the change. */
- if (!fgdev->transmission_enabled || when != get_cstate_change(fgdev))
- r = POLLERR;
-
- return r;
-}
-
-static int b3dfg_mmap(struct file *filp, struct vm_area_struct *vma)
-{
- struct b3dfg_dev *fgdev = filp->private_data;
- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
- unsigned long vsize = vma->vm_end - vma->vm_start;
- unsigned long bufdatalen = b3dfg_nbuf * fgdev->frame_size * 3;
- unsigned long psize = bufdatalen - offset;
- int r = 0;
-
- if (vsize <= psize) {
- vma->vm_flags |= VM_IO | VM_RESERVED | VM_CAN_NONLINEAR |
- VM_PFNMAP;
- vma->vm_ops = &b3dfg_vm_ops;
- } else {
- r = -EINVAL;
- }
-
- return r;
-}
-
-static struct file_operations b3dfg_fops = {
- .owner = THIS_MODULE,
- .open = b3dfg_open,
- .release = b3dfg_release,
- .unlocked_ioctl = b3dfg_ioctl,
- .poll = b3dfg_poll,
- .mmap = b3dfg_mmap,
-};
-
-static void free_all_frame_buffers(struct b3dfg_dev *fgdev)
-{
- int i, j;
- for (i = 0; i < b3dfg_nbuf; i++)
- for (j = 0; j < B3DFG_FRAMES_PER_BUFFER; j++)
- kfree(fgdev->buffers[i].frame[j]);
- kfree(fgdev->buffers);
-}
-
-/* initialize device and any data structures. called before any interrupts
- * are enabled. */
-static int b3dfg_init_dev(struct b3dfg_dev *fgdev)
-{
- int i, j;
- u32 frm_size = b3dfg_read32(fgdev, B3D_REG_FRM_SIZE);
-
- /* Disable interrupts. In abnormal circumstances (e.g. after a crash)
- * the board may still be transmitting from the previous session. If we
- * ensure that interrupts are disabled before we later enable them, we
- * are sure to capture a triplet from the start, rather than starting
- * from frame 2 or 3. Disabling interrupts causes the FG to throw away
- * all buffered data and stop buffering more until interrupts are
- * enabled again.
- */
- b3dfg_write32(fgdev, B3D_REG_HW_CTRL, 0);
-
- fgdev->frame_size = frm_size * 4096;
- fgdev->buffers = kzalloc(sizeof(struct b3dfg_buffer) * b3dfg_nbuf,
- GFP_KERNEL);
- if (!fgdev->buffers)
- goto err_no_buf;
- for (i = 0; i < b3dfg_nbuf; i++) {
- struct b3dfg_buffer *buf = &fgdev->buffers[i];
- for (j = 0; j < B3DFG_FRAMES_PER_BUFFER; j++) {
- buf->frame[j] = kmalloc(fgdev->frame_size, GFP_KERNEL);
- if (!buf->frame[j])
- goto err_no_mem;
- }
- INIT_LIST_HEAD(&buf->list);
- }
-
- INIT_LIST_HEAD(&fgdev->buffer_queue);
- init_waitqueue_head(&fgdev->buffer_waitqueue);
- spin_lock_init(&fgdev->buffer_lock);
- spin_lock_init(&fgdev->cstate_lock);
- spin_lock_init(&fgdev->triplets_dropped_lock);
- return 0;
-
-err_no_mem:
- free_all_frame_buffers(fgdev);
-err_no_buf:
- return -ENOMEM;
-}
-
-/* find next free minor number, returns -1 if none are availabile */
-static int get_free_minor(void)
-{
- int i;
- for (i = 0; i < B3DFG_MAX_DEVS; i++) {
- if (b3dfg_devices[i] == 0)
- return i;
- }
- return -1;
-}
-
-static int __devinit b3dfg_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
-{
- struct b3dfg_dev *fgdev = kzalloc(sizeof(*fgdev), GFP_KERNEL);
- int r = 0;
- int minor = get_free_minor();
- dev_t devno = MKDEV(MAJOR(b3dfg_devt), minor);
- unsigned long res_len;
- resource_size_t res_base;
-
- if (fgdev == NULL)
- return -ENOMEM;
-
- if (minor < 0) {
- dev_err(&pdev->dev, "too many devices found!\n");
- r = -EIO;
- goto err_free;
- }
-
- b3dfg_devices[minor] = 1;
- dev_info(&pdev->dev, "probe device with IRQ %d\n", pdev->irq);
-
- cdev_init(&fgdev->chardev, &b3dfg_fops);
- fgdev->chardev.owner = THIS_MODULE;
-
- r = cdev_add(&fgdev->chardev, devno, 1);
- if (r) {
- dev_err(&pdev->dev, "cannot add char device\n");
- goto err_release_minor;
- }
-
- fgdev->dev = device_create(
- b3dfg_class,
- &pdev->dev,
- devno,
- dev_get_drvdata(&pdev->dev),
- DRIVER_NAME "%d", minor);
-
- if (IS_ERR(fgdev->dev)) {
- dev_err(&pdev->dev, "cannot create device\n");
- r = PTR_ERR(fgdev->dev);
- goto err_del_cdev;
- }
-
- r = pci_enable_device(pdev);
- if (r) {
- dev_err(&pdev->dev, "cannot enable PCI device\n");
- goto err_dev_unreg;
- }
-
- res_len = pci_resource_len(pdev, B3DFG_BAR_REGS);
- if (res_len != B3DFG_REGS_LENGTH) {
- dev_err(&pdev->dev, "invalid register resource size\n");
- r = -EIO;
- goto err_disable;
- }
-
- if (pci_resource_flags(pdev, B3DFG_BAR_REGS)
- != (IORESOURCE_MEM | IORESOURCE_SIZEALIGN)) {
- dev_err(&pdev->dev, "invalid resource flags\n");
- r = -EIO;
- goto err_disable;
- }
- r = pci_request_regions(pdev, DRIVER_NAME);
- if (r) {
- dev_err(&pdev->dev, "cannot obtain PCI resources\n");
- goto err_disable;
- }
-
- pci_set_master(pdev);
-
- 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;
- }
-
- res_base = pci_resource_start(pdev, B3DFG_BAR_REGS);
- fgdev->regs = ioremap_nocache(res_base, res_len);
- if (!fgdev->regs) {
- dev_err(&pdev->dev, "regs ioremap failed\n");
- r = -EIO;
- goto err_free_res;
- }
-
- fgdev->pdev = pdev;
- pci_set_drvdata(pdev, fgdev);
- r = b3dfg_init_dev(fgdev);
- if (r < 0) {
- dev_err(&pdev->dev, "failed to initalize device\n");
- goto err_unmap;
- }
-
- r = request_irq(pdev->irq, b3dfg_intr, IRQF_SHARED, DRIVER_NAME, fgdev);
- if (r) {
- dev_err(&pdev->dev, "couldn't request irq %d\n", pdev->irq);
- goto err_free_bufs;
- }
-
- return 0;
-
-err_free_bufs:
- free_all_frame_buffers(fgdev);
-err_unmap:
- iounmap(fgdev->regs);
-err_free_res:
- pci_release_regions(pdev);
-err_disable:
- pci_disable_device(pdev);
-err_dev_unreg:
- device_destroy(b3dfg_class, devno);
-err_del_cdev:
- cdev_del(&fgdev->chardev);
-err_release_minor:
- b3dfg_devices[minor] = 0;
-err_free:
- kfree(fgdev);
- return r;
-}
-
-static void __devexit b3dfg_remove(struct pci_dev *pdev)
-{
- struct b3dfg_dev *fgdev = pci_get_drvdata(pdev);
- unsigned int minor = MINOR(fgdev->chardev.dev);
-
- dev_dbg(&pdev->dev, "remove\n");
-
- free_irq(pdev->irq, fgdev);
- iounmap(fgdev->regs);
- pci_release_regions(pdev);
- pci_disable_device(pdev);
- device_destroy(b3dfg_class, MKDEV(MAJOR(b3dfg_devt), minor));
- cdev_del(&fgdev->chardev);
- free_all_frame_buffers(fgdev);
- kfree(fgdev);
- b3dfg_devices[minor] = 0;
-}
-
-static struct pci_driver b3dfg_driver = {
- .name = DRIVER_NAME,
- .id_table = b3dfg_ids,
- .probe = b3dfg_probe,
- .remove = __devexit_p(b3dfg_remove),
-};
-
-static int __init b3dfg_module_init(void)
-{
- int r;
-
- if (b3dfg_nbuf < 2) {
- printk(KERN_ERR DRIVER_NAME
- ": buffer_count is out of range (must be >= 2)");
- return -EINVAL;
- }
-
- printk(KERN_INFO DRIVER_NAME ": loaded\n");
-
- b3dfg_class = class_create(THIS_MODULE, DRIVER_NAME);
- if (IS_ERR(b3dfg_class))
- return PTR_ERR(b3dfg_class);
-
- r = alloc_chrdev_region(&b3dfg_devt, 0, B3DFG_MAX_DEVS, DRIVER_NAME);
- if (r)
- goto err1;
-
- r = pci_register_driver(&b3dfg_driver);
- if (r)
- goto err2;
-
- return r;
-
-err2:
- unregister_chrdev_region(b3dfg_devt, B3DFG_MAX_DEVS);
-err1:
- class_destroy(b3dfg_class);
- return r;
-}
-
-static void __exit b3dfg_module_exit(void)
-{
- printk(KERN_INFO DRIVER_NAME ": unloaded\n");
- pci_unregister_driver(&b3dfg_driver);
- unregister_chrdev_region(b3dfg_devt, B3DFG_MAX_DEVS);
- class_destroy(b3dfg_class);
-}
-
-module_init(b3dfg_module_init);
-module_exit(b3dfg_module_exit);
diff --git a/drivers/staging/batman-adv/Kconfig b/drivers/staging/batman-adv/Kconfig
index 1d74dabf951..1e7e0a8dbc8 100644
--- a/drivers/staging/batman-adv/Kconfig
+++ b/drivers/staging/batman-adv/Kconfig
@@ -4,7 +4,7 @@
config BATMAN_ADV
tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
- depends on PROC_FS && PACKET
+ depends on PROC_FS && NET
default n
---help---
@@ -14,10 +14,10 @@ config BATMAN_ADV
http://www.open-mesh.org/ for more information and user space
tools.
-config BATMAN_DEBUG
+config BATMAN_ADV_DEBUG
bool "B.A.T.M.A.N. debugging"
depends on BATMAN_ADV != n
- help
+ ---help---
This is an option for use by developers; most people should
say N here. This enables compilation of support for
diff --git a/drivers/staging/batman-adv/Makefile b/drivers/staging/batman-adv/Makefile
index 02da87134fc..42b4e637026 100644
--- a/drivers/staging/batman-adv/Makefile
+++ b/drivers/staging/batman-adv/Makefile
@@ -19,4 +19,4 @@
#
obj-m += batman-adv.o
-batman-adv-objs := main.o proc.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o log.o
+batman-adv-objs := main.o proc.o send.o routing.o soft-interface.o device.o translation-table.o bitarray.o hash.o ring_buffer.o vis.o hard-interface.o aggregation.o originator.o
diff --git a/drivers/staging/batman-adv/README b/drivers/staging/batman-adv/README
index 3aaf393ebaa..7d666ad0435 100644
--- a/drivers/staging/batman-adv/README
+++ b/drivers/staging/batman-adv/README
@@ -1,4 +1,4 @@
-[state: 07-11-2009]
+[state: 06-01-2010]
BATMAN-ADV
----------
@@ -15,19 +15,6 @@ above B.A.T.M.A.N. Advanced, prominent examples are: IPv4, IPv6, DHCP, IPX.
This is batman-advanced implemented as Linux kernel driver. It does not depend
on any network (other) driver, and can be used on wifi as well as ethernet,
vpn, etc ... (anything with ethernet-style layer 2).
-It compiles against and should work with Linux 2.6.20 - 2.6.31. Supporting older
-versions is not planned, but it's probably easy to backport it. If you work on a
-backport, feel free to contact us. :-)
-
-COMPILE
--------
-To compile against your currently installed kernel, just type:
-
-# make
-
-if you want to compile against some other kernel, use:
-
-# make KERNELPATH=/path/to/kernel
USAGE
-----
@@ -73,16 +60,9 @@ When configured as server, you can get a topology snapshot of your mesh:
# cat /proc/net/batman-adv/vis
-This output format is a graphviz formatted text file which can be
-processed with graphviz-tools like dot.
-The labels are similar/compatible to the ETX metric, 1.0 means perfect
-connection (100%), 2.0 means 50%, 3.0 means 33% and so on.
-
-Alternatively, a JSON output format is available. The format can be set
-using by writing either "dot_draw" or "json" into the vis_format file.
-"dot_draw" is selected by default.
-
-echo "json" > /proc/net/batman-adv/vis_format
+The output is in a generic raw format. Use the batctl tool (See below)
+to convert this to other formats more suitable for graphing, eg
+graphviz dot, or JSON data-interchange format.
In very mobile scenarios, you might want to adjust the originator
interval to a lower value. This will make the mesh more responsive to
@@ -96,15 +76,59 @@ To deactivate batman, do:
# echo "" > /proc/net/batman-adv/interfaces
+LOGGING/DEBUGGING
+-----------------
+
+All error messages, warnings and information messages are sent to the
+kernel log. Depending on your operating system distribution this can be
+read in one of a number of ways. Try using the commands: dmesg,
+logread, or looking in the files /var/log/kern.log or
+/var/log/syslog. All batman-adv messages are prefixed with
+"batman-adv:" So to see just these messages try
+
+dmesg | grep batman-adv
+
+When investigating problems with your mesh network it is sometimes
+necessary to see more detail debug messages. This must be enabled when
+compiling the batman-adv module. Use "make menuconfig" and enable the
+option "B.A.T.M.A.N. debugging".
+
+The additional debug output is by default disabled. It can be enabled
+either at kernel module load time or during run time. To enable debug
+output at module load time, add the module parameter debug=<value>.
+<value> can take one of four values.
+
+0 - All debug output disabled
+1 - Enable messages related to routing / flooding / broadcasting
+2 - Enable route or hna added / changed / deleted
+3 - Enable all messages
+
+e.g.
+
+modprobe batman-adv debug=2
+
+will load the module and enable debug messages for when routes or HNAs
+change.
+
+The debug output can also be changed at runtime using the file
+/sys/module/batman-adv/parameters/debug. e.g.
+
+echo 2 > /sys/module/batman-adv/parameters/debug
+
+enables debug messages for when routes or HNAs
+
+The debug output is sent to the kernel logs. So try dmesg, logread etc
+to see the debug messages.
+
BATCTL
------
-B.A.T.M.A.N. advanced operates on layer 2 and thus all hosts partici-
-pating in the virtual switch are completely transparent for all proto-
-cols above layer 2. Therefore the common diagnosis tools do not work as
-expected. To overcome these problems batctl was created. At the moment
-the batctl contains ping, traceroute, tcpdump and interfaces to the
-kernel module settings.
+B.A.T.M.A.N. advanced operates on layer 2 and thus all hosts
+participating in the virtual switch are completely transparent for all
+protocols above layer 2. Therefore the common diagnosis tools do not
+work as expected. To overcome these problems batctl was created. At
+the moment the batctl contains ping, traceroute, tcpdump and
+interfaces to the kernel module settings.
For more information, please see the manpage (man batctl).
diff --git a/drivers/staging/batman-adv/TODO b/drivers/staging/batman-adv/TODO
index ea6dcf94d66..2f15136b18e 100644
--- a/drivers/staging/batman-adv/TODO
+++ b/drivers/staging/batman-adv/TODO
@@ -17,30 +17,6 @@
-> transtable_global (read-only) [outputs the global translation table]
-> transtable_local (read-only) [outputs the local translation table]
-=> vis "raw" data output
-* the raw format shall replace dot draw / json to offer a neutral that can
-* be converted
-* the format (comma seperated entries):
--> "mac" -> mac address of an originator (each line begins with it)
--> "TQ mac value" -> src mac's link quality towards mac address
--> "HNA mac" -> HNA announced by source mac
--> "PRIMARY" -> this is a primary interface
--> "SEC mac" -> secondary mac address of source (requires preceeding
--> PRIMARY)
-
-=> logging
-* the log level LOG_TYPE_CRIT, LOG_TYPE_WARN & LOG_TYPE_NOTICE will be
-* unified to use printk
-* LOG_TYPE_BATMAN & LOG_TYPE_ROUTES will also use printk but only after the
-* internal debug level has been raised
-* the internal debug level can be modified using a module parameter (debug)
-* or at run time via /sys/module/batman-adv/parameters/debug
-* make use of printk %pM support instead of converting mac addresses
-* manually
-
-=> strip out all backward compatibility support to older kernels
- (only found in compat.h)
-
=> fix checkpatch.pl errors
Please send all patches to:
diff --git a/drivers/staging/batman-adv/aggregation.c b/drivers/staging/batman-adv/aggregation.c
index 9c6e681f6fb..7917322a7e2 100644
--- a/drivers/staging/batman-adv/aggregation.c
+++ b/drivers/staging/batman-adv/aggregation.c
@@ -96,6 +96,7 @@ static void new_aggregated_packet(unsigned char *packet_buff,
int own_packet)
{
struct forw_packet *forw_packet_aggr;
+ unsigned long flags;
forw_packet_aggr = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC);
if (!forw_packet_aggr)
@@ -115,6 +116,7 @@ static void new_aggregated_packet(unsigned char *packet_buff,
packet_buff,
forw_packet_aggr->packet_len);
+ forw_packet_aggr->skb = NULL;
forw_packet_aggr->own = own_packet;
forw_packet_aggr->if_incoming = if_incoming;
forw_packet_aggr->num_packets = 0;
@@ -126,9 +128,9 @@ static void new_aggregated_packet(unsigned char *packet_buff,
forw_packet_aggr->direct_link_flags |= 1;
/* add new packet to packet list */
- spin_lock(&forw_bat_list_lock);
+ spin_lock_irqsave(&forw_bat_list_lock, flags);
hlist_add_head(&forw_packet_aggr->list, &forw_bat_list);
- spin_unlock(&forw_bat_list_lock);
+ spin_unlock_irqrestore(&forw_bat_list_lock, flags);
/* start timer for this packet */
INIT_DELAYED_WORK(&forw_packet_aggr->delayed_work,
@@ -168,9 +170,10 @@ void add_bat_packet_to_list(unsigned char *packet_buff, int packet_len,
struct batman_packet *batman_packet =
(struct batman_packet *)packet_buff;
bool direct_link = batman_packet->flags & DIRECTLINK ? 1 : 0;
+ unsigned long flags;
/* find position for the packet in the forward queue */
- spin_lock(&forw_bat_list_lock);
+ spin_lock_irqsave(&forw_bat_list_lock, flags);
/* own packets are not to be aggregated */
if ((atomic_read(&aggregation_enabled)) && (!own_packet)) {
hlist_for_each_entry(forw_packet_pos, tmp_node, &forw_bat_list,
@@ -191,7 +194,7 @@ void add_bat_packet_to_list(unsigned char *packet_buff, int packet_len,
* suitable aggregation packet found */
if (forw_packet_aggr == NULL) {
/* the following section can run without the lock */
- spin_unlock(&forw_bat_list_lock);
+ spin_unlock_irqrestore(&forw_bat_list_lock, flags);
new_aggregated_packet(packet_buff, packet_len,
send_time, direct_link,
if_incoming, own_packet);
@@ -199,7 +202,7 @@ void add_bat_packet_to_list(unsigned char *packet_buff, int packet_len,
aggregate(forw_packet_aggr,
packet_buff, packet_len,
direct_link);
- spin_unlock(&forw_bat_list_lock);
+ spin_unlock_irqrestore(&forw_bat_list_lock, flags);
}
}
diff --git a/drivers/staging/batman-adv/bitarray.c b/drivers/staging/batman-adv/bitarray.c
index 3c67f5f42b2..212eef93afe 100644
--- a/drivers/staging/batman-adv/bitarray.c
+++ b/drivers/staging/batman-adv/bitarray.c
@@ -21,7 +21,6 @@
#include "main.h"
#include "bitarray.h"
-#include "log.h"
/* returns true if the corresponding bit in the given seq_bits indicates true
* and curr_seqno is within range of last_seqno */
@@ -80,8 +79,8 @@ void bit_shift(TYPE_OF_WORD *seq_bits, int32_t n)
* from.
*
* left is high, right is low: FEDC BA98 7654 3210
- * ^^ ^^
- * vvvv
+ * ^^ ^^
+ * vvvv
* ^^^^ = from, vvvvv =to, we'd have word_num==1 and
* word_offset==WORD_BIT_SIZE/2 ????? in this example.
* (=24 bits)
@@ -133,13 +132,13 @@ char bit_get_packet(TYPE_OF_WORD *seq_bits, int16_t seq_num_diff,
(seq_num_diff < -TQ_LOCAL_WINDOW_SIZE)) {
if (seq_num_diff > TQ_LOCAL_WINDOW_SIZE)
- debug_log(LOG_TYPE_BATMAN,
- "We missed a lot of packets (%i) !\n",
- seq_num_diff-1);
+ bat_dbg(DBG_BATMAN,
+ "We missed a lot of packets (%i) !\n",
+ seq_num_diff-1);
if (-seq_num_diff > TQ_LOCAL_WINDOW_SIZE)
- debug_log(LOG_TYPE_BATMAN,
- "Other host probably restarted !\n");
+ bat_dbg(DBG_BATMAN,
+ "Other host probably restarted !\n");
for (i = 0; i < NUM_WORDS; i++)
seq_bits[i] = 0;
diff --git a/drivers/staging/batman-adv/compat.h b/drivers/staging/batman-adv/compat.h
deleted file mode 100644
index f4e0a4564ba..00000000000
--- a/drivers/staging/batman-adv/compat.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
- *
- * Marek Lindner, Simon Wunderlich
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- *
- *
- * This file contains macros for maintaining compatibility with older versions
- * of the Linux kernel.
- */
-
-#include <linux/version.h> /* LINUX_VERSION_CODE */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
-
-#define skb_set_network_header(_skb, _offset) \
- do { (_skb)->nh.raw = (_skb)->data + (_offset); } while (0)
-
-#define skb_reset_mac_header(_skb) \
- do { (_skb)->mac.raw = (_skb)->data; } while (0)
-
-#define list_first_entry(ptr, type, member) \
- list_entry((ptr)->next, type, member)
-
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22) */
-
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
-
-#define device_create(_cls, _parent, _devt, _device, _fmt) \
- class_device_create(_cls, _parent, _devt, _device, _fmt)
-
-#define device_destroy(_cls, _device) \
- class_device_destroy(_cls, _device)
-
-#else
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
-
-#define device_create(_cls, _parent, _devt, _device, _fmt) \
- device_create_drvdata(_cls, _parent, _devt, _device, _fmt)
-
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27) */
-
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26) */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
-
-#define cancel_delayed_work_sync(wq) cancel_rearming_delayed_work(wq)
-
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23) */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25)
-#define strict_strtoul(cp, base, res) \
- ({ \
- int ret = 0; \
- char *endp; \
- *res = simple_strtoul(cp, &endp, base); \
- if (cp == endp) \
- ret = -EINVAL; \
- ret; \
-})
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 25) */
diff --git a/drivers/staging/batman-adv/device.c b/drivers/staging/batman-adv/device.c
index 1e7d1f88674..e7f44215b5f 100644
--- a/drivers/staging/batman-adv/device.c
+++ b/drivers/staging/batman-adv/device.c
@@ -19,14 +19,13 @@
*
*/
+#include <linux/device.h>
#include "main.h"
#include "device.h"
-#include "log.h"
#include "send.h"
#include "types.h"
#include "hash.h"
-
-#include "compat.h"
+#include "hard-interface.h"
static struct class *batman_class;
@@ -60,7 +59,7 @@ int bat_device_setup(void)
/* register our device - kernel assigns a free major number */
tmp_major = register_chrdev(0, DRIVER_DEVICE, &fops);
if (tmp_major < 0) {
- debug_log(LOG_TYPE_WARN, "Registering the character device failed with %d\n",
+ printk(KERN_ERR "batman-adv:Registering the character device failed with %d\n",
tmp_major);
return 0;
}
@@ -68,7 +67,7 @@ int bat_device_setup(void)
batman_class = class_create(THIS_MODULE, "batman-adv");
if (IS_ERR(batman_class)) {
- debug_log(LOG_TYPE_WARN, "Could not register class 'batman-adv' \n");
+ printk(KERN_ERR "batman-adv:Could not register class 'batman-adv' \n");
return 0;
}
@@ -111,7 +110,7 @@ int bat_device_open(struct inode *inode, struct file *file)
}
if (device_client_hash[i] != device_client) {
- debug_log(LOG_TYPE_WARN, "Error - can't add another packet client: maximum number of clients reached \n");
+ printk(KERN_ERR "batman-adv:Error - can't add another packet client: maximum number of clients reached \n");
kfree(device_client);
return -EXFULL;
}
@@ -119,7 +118,7 @@ int bat_device_open(struct inode *inode, struct file *file)
INIT_LIST_HEAD(&device_client->queue_list);
device_client->queue_len = 0;
device_client->index = i;
- device_client->lock = __SPIN_LOCK_UNLOCKED(device_client->lock);
+ spin_lock_init(&device_client->lock);
init_waitqueue_head(&device_client->queue_wait);
file->private_data = device_client;
@@ -134,8 +133,9 @@ int bat_device_release(struct inode *inode, struct file *file)
(struct device_client *)file->private_data;
struct device_packet *device_packet;
struct list_head *list_pos, *list_pos_tmp;
+ unsigned long flags;
- spin_lock(&device_client->lock);
+ spin_lock_irqsave(&device_client->lock, flags);
/* for all packets in the queue ... */
list_for_each_safe(list_pos, list_pos_tmp, &device_client->queue_list) {
@@ -147,7 +147,7 @@ int bat_device_release(struct inode *inode, struct file *file)
}
device_client_hash[device_client->index] = NULL;
- spin_unlock(&device_client->lock);
+ spin_unlock_irqrestore(&device_client->lock, flags);
kfree(device_client);
dec_module_count();
@@ -162,6 +162,7 @@ ssize_t bat_device_read(struct file *file, char __user *buf, size_t count,
(struct device_client *)file->private_data;
struct device_packet *device_packet;
int error;
+ unsigned long flags;
if ((file->f_flags & O_NONBLOCK) && (device_client->queue_len == 0))
return -EAGAIN;
@@ -178,14 +179,14 @@ ssize_t bat_device_read(struct file *file, char __user *buf, size_t count,
if (error)
return error;
- spin_lock(&device_client->lock);
+ spin_lock_irqsave(&device_client->lock, flags);
device_packet = list_first_entry(&device_client->queue_list,
struct device_packet, list);
list_del(&device_packet->list);
device_client->queue_len--;
- spin_unlock(&device_client->lock);
+ spin_unlock_irqrestore(&device_client->lock, flags);
error = __copy_to_user(buf, &device_packet->icmp_packet,
sizeof(struct icmp_packet));
@@ -206,9 +207,11 @@ ssize_t bat_device_write(struct file *file, const char __user *buff,
struct icmp_packet icmp_packet;
struct orig_node *orig_node;
struct batman_if *batman_if;
+ uint8_t dstaddr[ETH_ALEN];
+ unsigned long flags;
if (len < sizeof(struct icmp_packet)) {
- debug_log(LOG_TYPE_NOTICE, "Error - can't send packet from char device: invalid packet size\n");
+ bat_dbg(DBG_BATMAN, "batman-adv:Error - can't send packet from char device: invalid packet size\n");
return -EINVAL;
}
@@ -219,12 +222,12 @@ ssize_t bat_device_write(struct file *file, const char __user *buff,
return -EFAULT;
if (icmp_packet.packet_type != BAT_ICMP) {
- debug_log(LOG_TYPE_NOTICE, "Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n");
+ bat_dbg(DBG_BATMAN, "batman-adv:Error - can't send packet from char device: got bogus packet type (expected: BAT_ICMP)\n");
return -EINVAL;
}
if (icmp_packet.msg_type != ECHO_REQUEST) {
- debug_log(LOG_TYPE_NOTICE, "Error - can't send packet from char device: got bogus message type (expected: ECHO_REQUEST)\n");
+ bat_dbg(DBG_BATMAN, "batman-adv:Error - can't send packet from char device: got bogus message type (expected: ECHO_REQUEST)\n");
return -EINVAL;
}
@@ -240,7 +243,7 @@ ssize_t bat_device_write(struct file *file, const char __user *buff,
if (atomic_read(&module_state) != MODULE_ACTIVE)
goto dst_unreach;
- spin_lock(&orig_hash_lock);
+ spin_lock_irqsave(&orig_hash_lock, flags);
orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet.dst));
if (!orig_node)
@@ -250,9 +253,15 @@ ssize_t bat_device_write(struct file *file, const char __user *buff,
goto unlock;
batman_if = orig_node->batman_if;
+ memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
+
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
if (!batman_if)
- goto unlock;
+ goto dst_unreach;
+
+ if (batman_if->if_active != IF_ACTIVE)
+ goto dst_unreach;
memcpy(icmp_packet.orig,
batman_if->net_dev->dev_addr,
@@ -260,13 +269,12 @@ ssize_t bat_device_write(struct file *file, const char __user *buff,
send_raw_packet((unsigned char *)&icmp_packet,
sizeof(struct icmp_packet),
- batman_if, orig_node->router->addr);
+ batman_if, dstaddr);
- spin_unlock(&orig_hash_lock);
goto out;
unlock:
- spin_unlock(&orig_hash_lock);
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
dst_unreach:
icmp_packet.msg_type = DESTINATION_UNREACHABLE;
bat_device_add_packet(device_client, &icmp_packet);
@@ -291,6 +299,7 @@ void bat_device_add_packet(struct device_client *device_client,
struct icmp_packet *icmp_packet)
{
struct device_packet *device_packet;
+ unsigned long flags;
device_packet = kmalloc(sizeof(struct device_packet), GFP_KERNEL);
@@ -301,12 +310,12 @@ void bat_device_add_packet(struct device_client *device_client,
memcpy(&device_packet->icmp_packet, icmp_packet,
sizeof(struct icmp_packet));
- spin_lock(&device_client->lock);
+ spin_lock_irqsave(&device_client->lock, flags);
/* while waiting for the lock the device_client could have been
* deleted */
if (!device_client_hash[icmp_packet->uid]) {
- spin_unlock(&device_client->lock);
+ spin_unlock_irqrestore(&device_client->lock, flags);
kfree(device_packet);
return;
}
@@ -323,7 +332,7 @@ void bat_device_add_packet(struct device_client *device_client,
device_client->queue_len--;
}
- spin_unlock(&device_client->lock);
+ spin_unlock_irqrestore(&device_client->lock, flags);
wake_up(&device_client->queue_wait);
}
diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c
index 5ea35da5ee7..befd4883951 100644
--- a/drivers/staging/batman-adv/hard-interface.c
+++ b/drivers/staging/batman-adv/hard-interface.c
@@ -21,13 +21,11 @@
#include "main.h"
#include "hard-interface.h"
-#include "log.h"
#include "soft-interface.h"
#include "send.h"
#include "translation-table.h"
#include "routing.h"
#include "hash.h"
-#include "compat.h"
#define MIN(x, y) ((x) < (y) ? (x) : (y))
@@ -75,7 +73,6 @@ int hardif_min_mtu(void)
static void check_known_mac_addr(uint8_t *addr)
{
struct batman_if *batman_if;
- char mac_string[ETH_STR_LEN];
rcu_read_lock();
list_for_each_entry_rcu(batman_if, &if_list, list) {
@@ -86,10 +83,9 @@ static void check_known_mac_addr(uint8_t *addr)
if (!compare_orig(batman_if->net_dev->dev_addr, addr))
continue;
- addr_to_string(mac_string, addr);
- debug_log(LOG_TYPE_WARN, "The newly added mac address (%s) already exists on: %s\n",
- mac_string, batman_if->dev);
- debug_log(LOG_TYPE_WARN, "It is strongly recommended to keep mac addresses unique to avoid problems!\n");
+ printk(KERN_WARNING "batman-adv:The newly added mac address (%pM) already exists on: %s\n",
+ addr, batman_if->dev);
+ printk(KERN_WARNING "batman-adv:It is strongly recommended to keep mac addresses unique to avoid problems!\n");
}
rcu_read_unlock();
}
@@ -154,9 +150,6 @@ void hardif_deactivate_interface(struct batman_if *batman_if)
if (batman_if->if_active != IF_ACTIVE)
return;
- if (batman_if->raw_sock)
- sock_release(batman_if->raw_sock);
-
/**
* batman_if->net_dev has been acquired by dev_get_by_name() in
* proc_interfaces_write() and has to be unreferenced.
@@ -165,22 +158,16 @@ void hardif_deactivate_interface(struct batman_if *batman_if)
if (batman_if->net_dev)
dev_put(batman_if->net_dev);
- batman_if->raw_sock = NULL;
- batman_if->net_dev = NULL;
-
batman_if->if_active = IF_INACTIVE;
active_ifs--;
- debug_log(LOG_TYPE_NOTICE, "Interface deactivated: %s\n",
- batman_if->dev);
+ printk(KERN_INFO "batman-adv:Interface deactivated: %s\n",
+ batman_if->dev);
}
/* (re)activate given interface. */
static void hardif_activate_interface(struct batman_if *batman_if)
{
- struct sockaddr_ll bind_addr;
- int retval;
-
if (batman_if->if_active != IF_INACTIVE)
return;
@@ -192,35 +179,8 @@ static void hardif_activate_interface(struct batman_if *batman_if)
if (!batman_if->net_dev)
goto dev_err;
- retval = sock_create_kern(PF_PACKET, SOCK_RAW,
- __constant_htons(ETH_P_BATMAN),
- &batman_if->raw_sock);
-
- if (retval < 0) {
- debug_log(LOG_TYPE_WARN, "Can't create raw socket: %i\n",
- retval);
- goto sock_err;
- }
-
- bind_addr.sll_family = AF_PACKET;
- bind_addr.sll_ifindex = batman_if->net_dev->ifindex;
- bind_addr.sll_protocol = 0; /* is set by the kernel */
-
- retval = kernel_bind(batman_if->raw_sock,
- (struct sockaddr *)&bind_addr, sizeof(bind_addr));
-
- if (retval < 0) {
- debug_log(LOG_TYPE_WARN, "Can't create bind raw socket: %i\n",
- retval);
- goto bind_err;
- }
-
check_known_mac_addr(batman_if->net_dev->dev_addr);
- batman_if->raw_sock->sk->sk_user_data =
- batman_if->raw_sock->sk->sk_data_ready;
- batman_if->raw_sock->sk->sk_data_ready = batman_data_ready;
-
addr_to_string(batman_if->addr_str, batman_if->net_dev->dev_addr);
memcpy(((struct batman_packet *)(batman_if->packet_buff))->orig,
@@ -235,17 +195,12 @@ static void hardif_activate_interface(struct batman_if *batman_if)
if (batman_if->if_num == 0)
set_main_if_addr(batman_if->net_dev->dev_addr);
- debug_log(LOG_TYPE_NOTICE, "Interface activated: %s\n",
- batman_if->dev);
+ printk(KERN_INFO "batman-adv:Interface activated: %s\n",
+ batman_if->dev);
return;
-bind_err:
- sock_release(batman_if->raw_sock);
-sock_err:
- dev_put(batman_if->net_dev);
dev_err:
- batman_if->raw_sock = NULL;
batman_if->net_dev = NULL;
}
@@ -290,7 +245,7 @@ static int resize_orig(struct orig_node *orig_node, int if_num)
data_ptr = kmalloc((if_num + 1) * sizeof(TYPE_OF_WORD) * NUM_WORDS,
GFP_ATOMIC);
if (!data_ptr) {
- debug_log(LOG_TYPE_WARN, "Can't resize orig: out of memory\n");
+ printk(KERN_ERR "batman-adv:Can't resize orig: out of memory\n");
return -1;
}
@@ -301,7 +256,7 @@ static int resize_orig(struct orig_node *orig_node, int if_num)
data_ptr = kmalloc((if_num + 1) * sizeof(uint8_t), GFP_ATOMIC);
if (!data_ptr) {
- debug_log(LOG_TYPE_WARN, "Can't resize orig: out of memory\n");
+ printk(KERN_ERR "batman-adv:Can't resize orig: out of memory\n");
return -1;
}
@@ -319,16 +274,16 @@ int hardif_add_interface(char *dev, int if_num)
struct batman_if *batman_if;
struct batman_packet *batman_packet;
struct orig_node *orig_node;
- struct hash_it_t *hashit = NULL;
+ unsigned long flags;
+ HASHIT(hashit);
batman_if = kmalloc(sizeof(struct batman_if), GFP_KERNEL);
if (!batman_if) {
- debug_log(LOG_TYPE_WARN, "Can't add interface (%s): out of memory\n", dev);
+ printk(KERN_ERR "batman-adv:Can't add interface (%s): out of memory\n", dev);
return -1;
}
- batman_if->raw_sock = NULL;
batman_if->net_dev = NULL;
if ((if_num == 0) && (num_hna > 0))
@@ -339,7 +294,7 @@ int hardif_add_interface(char *dev, int if_num)
batman_if->packet_buff = kmalloc(batman_if->packet_len, GFP_KERNEL);
if (!batman_if->packet_buff) {
- debug_log(LOG_TYPE_WARN, "Can't add interface packet (%s): out of memory\n", dev);
+ printk(KERN_ERR "batman-adv:Can't add interface packet (%s): out of memory\n", dev);
goto out;
}
@@ -348,7 +303,7 @@ int hardif_add_interface(char *dev, int if_num)
batman_if->if_active = IF_INACTIVE;
INIT_RCU_HEAD(&batman_if->rcu);
- debug_log(LOG_TYPE_NOTICE, "Adding interface: %s\n", dev);
+ printk(KERN_INFO "batman-adv:Adding interface: %s\n", dev);
avail_ifs++;
INIT_LIST_HEAD(&batman_if->list);
@@ -376,20 +331,20 @@ int hardif_add_interface(char *dev, int if_num)
/* resize all orig nodes because orig_node->bcast_own(_sum) depend on
* if_num */
- spin_lock(&orig_hash_lock);
+ spin_lock_irqsave(&orig_hash_lock, flags);
- while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
- orig_node = hashit->bucket->data;
+ while (hash_iterate(orig_hash, &hashit)) {
+ orig_node = hashit.bucket->data;
if (resize_orig(orig_node, if_num) == -1) {
- spin_unlock(&orig_hash_lock);
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
goto out;
}
}
- spin_unlock(&orig_hash_lock);
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
if (!hardif_is_interface_up(batman_if->dev))
- debug_log(LOG_TYPE_WARN, "Not using interface %s (retrying later): interface not active\n", batman_if->dev);
+ printk(KERN_ERR "batman-adv:Not using interface %s (retrying later): interface not active\n", batman_if->dev);
else
hardif_activate_interface(batman_if);
@@ -400,8 +355,7 @@ int hardif_add_interface(char *dev, int if_num)
return 1;
out:
- if (batman_if->packet_buff)
- kfree(batman_if->packet_buff);
+ kfree(batman_if->packet_buff);
kfree(batman_if);
kfree(dev);
return -1;
@@ -413,7 +367,7 @@ char hardif_get_active_if_num(void)
}
static int hard_if_event(struct notifier_block *this,
- unsigned long event, void *ptr)
+ unsigned long event, void *ptr)
{
struct net_device *dev = (struct net_device *)ptr;
struct batman_if *batman_if = get_batman_if_by_name(dev->name);
@@ -436,7 +390,6 @@ static int hard_if_event(struct notifier_block *this,
break;
/* NETDEV_CHANGEADDR - mac address change - what are we doing here ? */
default:
- /* debug_log(LOG_TYPE_CRIT, "hard_if_event: %s %i\n", dev->name, event); */
break;
};
@@ -446,6 +399,122 @@ out:
return NOTIFY_DONE;
}
+/* find batman interface by netdev. assumes rcu_read_lock on */
+static struct batman_if *find_batman_if(struct net_device *dev)
+{
+ struct batman_if *batman_if;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(batman_if, &if_list, list) {
+ if (batman_if->net_dev == dev) {
+ rcu_read_unlock();
+ return batman_if;
+ }
+ }
+ rcu_read_unlock();
+ return NULL;
+}
+
+
+/* receive a packet with the batman ethertype coming on a hard
+ * interface */
+int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *ptype, struct net_device *orig_dev)
+{
+ struct batman_packet *batman_packet;
+ struct batman_if *batman_if;
+ struct net_device_stats *stats;
+ int ret;
+
+ skb = skb_share_check(skb, GFP_ATOMIC);
+
+ /* skb was released by skb_share_check() */
+ if (!skb)
+ goto err_out;
+
+ if (atomic_read(&module_state) != MODULE_ACTIVE)
+ goto err_free;
+
+ /* packet should hold at least type and version */
+ if (unlikely(skb_headlen(skb) < 2))
+ goto err_free;
+
+ /* expect a valid ethernet header here. */
+ if (unlikely(skb->mac_len != sizeof(struct ethhdr)
+ || !skb_mac_header(skb)))
+ goto err_free;
+
+ batman_if = find_batman_if(skb->dev);
+ if (!batman_if)
+ goto err_free;
+
+ /* discard frames on not active interfaces */
+ if (batman_if->if_active != IF_ACTIVE)
+ goto err_free;
+
+ stats = (struct net_device_stats *)dev_get_stats(skb->dev);
+ if (stats) {
+ stats->rx_packets++;
+ stats->rx_bytes += skb->len;
+ }
+
+ batman_packet = (struct batman_packet *)skb->data;
+
+ if (batman_packet->version != COMPAT_VERSION) {
+ bat_dbg(DBG_BATMAN,
+ "Drop packet: incompatible batman version (%i)\n",
+ batman_packet->version);
+ goto err_free;
+ }
+
+ /* all receive handlers return whether they received or reused
+ * the supplied skb. if not, we have to free the skb. */
+
+ switch (batman_packet->packet_type) {
+ /* batman originator packet */
+ case BAT_PACKET:
+ ret = recv_bat_packet(skb, batman_if);
+ break;
+
+ /* batman icmp packet */
+ case BAT_ICMP:
+ ret = recv_icmp_packet(skb);
+ break;
+
+ /* unicast packet */
+ case BAT_UNICAST:
+ ret = recv_unicast_packet(skb);
+ break;
+
+ /* broadcast packet */
+ case BAT_BCAST:
+ ret = recv_bcast_packet(skb);
+ break;
+
+ /* vis packet */
+ case BAT_VIS:
+ ret = recv_vis_packet(skb);
+ break;
+ default:
+ ret = NET_RX_DROP;
+ }
+
+ if (ret == NET_RX_DROP)
+ kfree_skb(skb);
+
+ /* return NET_RX_SUCCESS in any case as we
+ * most probably dropped the packet for
+ * routing-logical reasons. */
+
+ return NET_RX_SUCCESS;
+
+err_free:
+ kfree_skb(skb);
+err_out:
+ return NET_RX_DROP;
+}
+
+
struct notifier_block hard_if_notifier = {
- .notifier_call = hard_if_event,
+ .notifier_call = hard_if_event,
};
diff --git a/drivers/staging/batman-adv/hard-interface.h b/drivers/staging/batman-adv/hard-interface.h
index 742358c00c0..97c6ecb9e08 100644
--- a/drivers/staging/batman-adv/hard-interface.h
+++ b/drivers/staging/batman-adv/hard-interface.h
@@ -32,5 +32,9 @@ void hardif_deactivate_interface(struct batman_if *batman_if);
char hardif_get_active_if_num(void);
void hardif_check_interfaces_status(void);
void hardif_check_interfaces_status_wq(struct work_struct *work);
+int batman_skb_recv(struct sk_buff *skb,
+ struct net_device *dev,
+ struct packet_type *ptype,
+ struct net_device *orig_dev);
int hardif_min_mtu(void);
void update_min_mtu(void);
diff --git a/drivers/staging/batman-adv/hash.c b/drivers/staging/batman-adv/hash.c
index 61cb4a20ebc..5a2018de3ff 100644
--- a/drivers/staging/batman-adv/hash.c
+++ b/drivers/staging/batman-adv/hash.c
@@ -64,24 +64,18 @@ void hash_destroy(struct hashtable_t *hash)
kfree(hash);
}
-/* iterate though the hash. first element is selected with iter_in NULL. use
- * the returned iterator to access the elements until hash_it_t returns NULL. */
+/* iterate though the hash. First element is selected if an iterator
+ * initialized with HASHIT() is supplied as iter. Use the returned
+ * (or supplied) iterator to access the elements until hash_iterate returns
+ * NULL. */
+
struct hash_it_t *hash_iterate(struct hashtable_t *hash,
- struct hash_it_t *iter_in)
+ struct hash_it_t *iter)
{
- struct hash_it_t *iter;
-
if (!hash)
return NULL;
-
- if (iter_in == NULL) {
- iter = kmalloc(sizeof(struct hash_it_t), GFP_ATOMIC);
- iter->index = -1;
- iter->bucket = NULL;
- iter->prev_bucket = NULL;
- } else {
- iter = iter_in;
- }
+ if (!iter)
+ return NULL;
/* sanity checks first (if our bucket got deleted in the last
* iteration): */
@@ -139,7 +133,6 @@ struct hash_it_t *hash_iterate(struct hashtable_t *hash,
}
/* nothing to iterate over anymore */
- kfree(iter);
return NULL;
}
diff --git a/drivers/staging/batman-adv/hash.h b/drivers/staging/batman-adv/hash.h
index bb60f082be6..a70d6d6e1c7 100644
--- a/drivers/staging/batman-adv/hash.h
+++ b/drivers/staging/batman-adv/hash.h
@@ -21,6 +21,11 @@
#ifndef _BATMAN_HASH_H
#define _BATMAN_HASH_H
+#define HASHIT(name) struct hash_it_t name = { \
+ .index = -1, .bucket = NULL, \
+ .prev_bucket = NULL, \
+ .first_bucket = NULL }
+
typedef int (*hashdata_compare_cb)(void *, void *);
typedef int (*hashdata_choose_cb)(void *, int);
diff --git a/drivers/staging/batman-adv/log.c b/drivers/staging/batman-adv/log.c
deleted file mode 100644
index f37c7f01a9f..00000000000
--- a/drivers/staging/batman-adv/log.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2007-2009 B.A.T.M.A.N. contributors:
- *
- * Marek Lindner, Simon Wunderlich
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA
- *
- */
-
-#include "main.h"
-#include "log.h"
-
-#define LOG_BUF_MASK (log_buf_len-1)
-#define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK])
-
-static char log_buf[LOG_BUF_LEN];
-static int log_buf_len = LOG_BUF_LEN;
-static unsigned long log_start;
-static unsigned long log_end;
-uint8_t log_level;
-
-static DEFINE_SPINLOCK(logbuf_lock);
-
-const struct file_operations proc_log_operations = {
- .open = log_open,
- .release = log_release,
- .read = log_read,
- .write = log_write,
- .poll = log_poll,
-};
-
-static DECLARE_WAIT_QUEUE_HEAD(log_wait);
-
-static void emit_log_char(char c)
-{
- LOG_BUF(log_end) = c;
- log_end++;
-
- if (log_end - log_start > log_buf_len)
- log_start = log_end - log_buf_len;
-}
-
-static int fdebug_log(char *fmt, ...)
-{
- int printed_len;
- char *p;
- va_list args;
- static char debug_log_buf[256];
- unsigned long flags;
-
- spin_lock_irqsave(&logbuf_lock, flags);
- va_start(args, fmt);
- printed_len = vscnprintf(debug_log_buf, sizeof(debug_log_buf), fmt,
- args);
- va_end(args);
-
- for (p = debug_log_buf; *p != 0; p++)
- emit_log_char(*p);
-
- spin_unlock_irqrestore(&logbuf_lock, flags);
-
- wake_up(&log_wait);
-
- return 0;
-}
-
-int debug_log(int type, char *fmt, ...)
-{
- va_list args;
- int retval = 0;
- char tmp_log_buf[256];
-
- /* only critical information get into the official kernel log */
- if (type == LOG_TYPE_CRIT) {
- va_start(args, fmt);
- vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args);
- printk(KERN_ERR "batman-adv: %s", tmp_log_buf);
- va_end(args);
- }
-
- if ((type == LOG_TYPE_CRIT) || (log_level & type)) {
- va_start(args, fmt);
- vscnprintf(tmp_log_buf, sizeof(tmp_log_buf), fmt, args);
- fdebug_log("[%10u] %s", (jiffies / HZ), tmp_log_buf);
- va_end(args);
- }
-
- return retval;
-}
-
-int log_open(struct inode *inode, struct file *file)
-{
- inc_module_count();
- return 0;
-}
-
-int log_release(struct inode *inode, struct file *file)
-{
- dec_module_count();
- return 0;
-}
-
-ssize_t log_read(struct file *file, char __user *buf, size_t count,
- loff_t *ppos)
-{
- int error, i = 0;
- char c;
- unsigned long flags;
-
- if ((file->f_flags & O_NONBLOCK) && !(log_end - log_start))
- return -EAGAIN;
-
- if ((!buf) || (count < 0))
- return -EINVAL;
-
- if (count == 0)
- return 0;
-
- if (!access_ok(VERIFY_WRITE, buf, count))
- return -EFAULT;
-
- error = wait_event_interruptible(log_wait, (log_start - log_end));
-
- if (error)
- return error;
-
- spin_lock_irqsave(&logbuf_lock, flags);
-
- while ((!error) && (log_start != log_end) && (i < count)) {
- c = LOG_BUF(log_start);
-
- log_start++;
-
- spin_unlock_irqrestore(&logbuf_lock, flags);
-
- error = __put_user(c, buf);
-
- spin_lock_irqsave(&logbuf_lock, flags);
-
- buf++;
- i++;
-
- }
-
- spin_unlock_irqrestore(&logbuf_lock, flags);
-
- if (!error)
- return i;
-
- return error;
-}
-
-ssize_t log_write(struct file *file, const char __user *buf, size_t count,
- loff_t *ppos)
-{
- return count;
-}
-
-unsigned int log_poll(struct file *file, poll_table *wait)
-{
- poll_wait(file, &log_wait, wait);
-
- if (log_end - log_start)
- return POLLIN | POLLRDNORM;
-
- return 0;
-}
diff --git a/drivers/staging/batman-adv/main.c b/drivers/staging/batman-adv/main.c
index bb89bfc5dda..2e0b482e710 100644
--- a/drivers/staging/batman-adv/main.c
+++ b/drivers/staging/batman-adv/main.c
@@ -21,9 +21,9 @@
#include "main.h"
#include "proc.h"
-#include "log.h"
#include "routing.h"
#include "send.h"
+#include "originator.h"
#include "soft-interface.h"
#include "device.h"
#include "translation-table.h"
@@ -31,7 +31,6 @@
#include "types.h"
#include "vis.h"
#include "hash.h"
-#include "compat.h"
struct list_head if_list;
struct hlist_head forw_bat_list;
@@ -44,19 +43,34 @@ DEFINE_SPINLOCK(forw_bcast_list_lock);
atomic_t originator_interval;
atomic_t vis_interval;
+atomic_t vis_mode;
atomic_t aggregation_enabled;
int16_t num_hna;
int16_t num_ifs;
struct net_device *soft_device;
-static struct task_struct *kthread_task;
-
unsigned char broadcastAddr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
atomic_t module_state;
+static struct packet_type batman_adv_packet_type __read_mostly = {
+ .type = __constant_htons(ETH_P_BATMAN),
+ .func = batman_skb_recv,
+};
+
struct workqueue_struct *bat_event_workqueue;
+#ifdef CONFIG_BATMAN_ADV_DEBUG
+int debug;
+
+module_param(debug, int, 0644);
+
+int bat_debug_type(int type)
+{
+ return debug & type;
+}
+#endif
+
int init_module(void)
{
int retval;
@@ -70,6 +84,7 @@ int init_module(void)
atomic_set(&originator_interval, 1000);
atomic_set(&vis_interval, 1000);/* TODO: raise this later, this is only
* for debugging now. */
+ atomic_set(&vis_mode, VIS_TYPE_CLIENT_UPDATE);
atomic_set(&aggregation_enabled, 1);
/* the name should not be longer than 10 chars - see
@@ -90,21 +105,22 @@ int init_module(void)
interface_setup);
if (!soft_device) {
- debug_log(LOG_TYPE_CRIT, "Unable to allocate the batman interface\n");
+ printk(KERN_ERR "batman-adv:Unable to allocate the batman interface\n");
goto end;
}
retval = register_netdev(soft_device);
if (retval < 0) {
- debug_log(LOG_TYPE_CRIT, "Unable to register the batman interface: %i\n", retval);
+ printk(KERN_ERR "batman-adv:Unable to register the batman interface: %i\n", retval);
goto free_soft_device;
}
register_netdevice_notifier(&hard_if_notifier);
+ dev_add_pack(&batman_adv_packet_type);
- debug_log(LOG_TYPE_CRIT, "B.A.T.M.A.N. advanced %s%s (compatibility version %i) loaded \n",
- SOURCE_VERSION, REVISION_VERSION_STR, COMPAT_VERSION);
+ printk(KERN_INFO "batman-adv:B.A.T.M.A.N. advanced %s%s (compatibility version %i) loaded \n",
+ SOURCE_VERSION, REVISION_VERSION_STR, COMPAT_VERSION);
return 0;
@@ -124,6 +140,8 @@ void cleanup_module(void)
soft_device = NULL;
}
+ dev_remove_pack(&batman_adv_packet_type);
+
unregister_netdevice_notifier(&hard_if_notifier);
cleanup_procfs();
@@ -151,22 +169,12 @@ void activate_module(void)
if (vis_init() < 1)
goto err;
- /* (re)start kernel thread for packet processing */
- if (!kthread_task) {
- kthread_task = kthread_run(packet_recv_thread, NULL, "batman-adv");
-
- if (IS_ERR(kthread_task)) {
- debug_log(LOG_TYPE_CRIT, "Unable to start packet receive thread\n");
- kthread_task = NULL;
- }
- }
-
update_min_mtu();
atomic_set(&module_state, MODULE_ACTIVE);
goto end;
err:
- debug_log(LOG_TYPE_CRIT, "Unable to allocate memory for mesh information structures: out of mem ?\n");
+ printk(KERN_ERR "batman-adv:Unable to allocate memory for mesh information structures: out of mem ?\n");
shutdown_module();
end:
return;
@@ -182,14 +190,7 @@ void shutdown_module(void)
vis_quit();
- /* deactivate kernel thread for packet processing (if running) */
- if (kthread_task) {
- atomic_set(&exit_cond, 1);
- wake_up_interruptible(&thread_wait);
- kthread_stop(kthread_task);
-
- kthread_task = NULL;
- }
+ /* TODO: unregister BATMAN pack */
originator_free();
diff --git a/drivers/staging/batman-adv/main.h b/drivers/staging/batman-adv/main.h
index facb6b79ee5..deb41f5beda 100644
--- a/drivers/staging/batman-adv/main.h
+++ b/drivers/staging/batman-adv/main.h
@@ -33,16 +33,16 @@
#define TQ_MAX_VALUE 255
#define JITTER 20
-#define TTL 50 /* Time To Live of broadcast messages */
-#define MAX_ADDR 16 /* number of interfaces which can be added to
+#define TTL 50 /* Time To Live of broadcast messages */
+#define MAX_ADDR 16 /* number of interfaces which can be added to
* batman. */
-#define PURGE_TIMEOUT 200000 /* purge originators after time in ms if no
+#define PURGE_TIMEOUT 200000 /* purge originators after time in ms if no
* valid packet comes in -> TODO: check
* influence on TQ_LOCAL_WINDOW_SIZE */
#define LOCAL_HNA_TIMEOUT 3600000
-#define TQ_LOCAL_WINDOW_SIZE 64 /* sliding packet range of received originator
+#define TQ_LOCAL_WINDOW_SIZE 64 /* sliding packet range of received originator
* messages in squence numbers (should be a
* multiple of our word size) */
#define TQ_GLOBAL_WINDOW_SIZE 5
@@ -69,24 +69,27 @@
/*
- * Logging
+ * Debug Messages
*/
-#define LOG_TYPE_CRIT 0 /* highest priority for fatal errors such as
- * blocked sockets / failed packet delivery /
- * programming errors */
-#define LOG_TYPE_WARN 1 /* warnings for small errors like wrong user
- * input / damaged packets / etc */
-#define LOG_TYPE_NOTICE 2 /* notice information for new interfaces /
- * changed settings / new originators / etc */
-#define LOG_TYPE_BATMAN 4 /* all messages related to routing / flooding /
- * broadcasting / etc */
-#define LOG_TYPE_ROUTES 8 /* route or hna added / changed / deleted */
-#define LOG_TYPE_CRIT_NAME "critical"
-#define LOG_TYPE_WARN_NAME "warnings"
-#define LOG_TYPE_NOTICE_NAME "notices"
-#define LOG_TYPE_BATMAN_NAME "batman"
-#define LOG_TYPE_ROUTES_NAME "routes"
+#define DBG_BATMAN 1 /* all messages related to routing / flooding /
+ * broadcasting / etc */
+#define DBG_ROUTES 2 /* route or hna added / changed / deleted */
+
+#ifdef CONFIG_BATMAN_ADV_DEBUG
+extern int debug;
+
+extern int bat_debug_type(int type);
+#define bat_dbg(type, fmt, arg...) do { \
+ if (bat_debug_type(type)) \
+ printk(KERN_DEBUG "batman-adv:" fmt, ## arg); \
+ } \
+ while (0)
+#else /* !CONFIG_BATMAN_ADV_DEBUG */
+#define bat_dbg(type, fmt, arg...) do { \
+ } \
+ while (0)
+#endif
/*
* Vis
@@ -127,6 +130,7 @@ extern spinlock_t forw_bcast_list_lock;
extern atomic_t originator_interval;
extern atomic_t vis_interval;
+extern atomic_t vis_mode;
extern atomic_t aggregation_enabled;
extern int16_t num_hna;
extern int16_t num_ifs;
@@ -147,5 +151,3 @@ int choose_orig(void *data, int32_t size);
int is_my_mac(uint8_t *addr);
int is_bcast(uint8_t *addr);
int is_mcast(uint8_t *addr);
-
-
diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c
new file mode 100644
index 00000000000..29c241119a3
--- /dev/null
+++ b/drivers/staging/batman-adv/originator.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2009 B.A.T.M.A.N. contributors:
+ *
+ * Marek Lindner, Simon Wunderlich
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ *
+ */
+
+/* increase the reference counter for this originator */
+
+#include "main.h"
+#include "originator.h"
+#include "hash.h"
+#include "translation-table.h"
+#include "routing.h"
+
+static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig);
+
+static void start_purge_timer(void)
+{
+ queue_delayed_work(bat_event_workqueue, &purge_orig_wq, 1 * HZ);
+}
+
+int originator_init(void)
+{
+ unsigned long flags;
+ if (orig_hash)
+ return 1;
+
+ spin_lock_irqsave(&orig_hash_lock, flags);
+ orig_hash = hash_new(128, compare_orig, choose_orig);
+
+ if (!orig_hash)
+ goto err;
+
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
+ start_purge_timer();
+ return 1;
+
+err:
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
+ return 0;
+}
+
+void originator_free(void)
+{
+ unsigned long flags;
+
+ if (!orig_hash)
+ return;
+
+ cancel_delayed_work_sync(&purge_orig_wq);
+
+ spin_lock_irqsave(&orig_hash_lock, flags);
+ hash_delete(orig_hash, free_orig_node);
+ orig_hash = NULL;
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
+}
+
+struct neigh_node *
+create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
+ uint8_t *neigh, struct batman_if *if_incoming)
+{
+ struct neigh_node *neigh_node;
+
+ bat_dbg(DBG_BATMAN, "Creating new last-hop neighbor of originator\n");
+
+ neigh_node = kzalloc(sizeof(struct neigh_node), GFP_ATOMIC);
+ if (!neigh_node)
+ return NULL;
+
+ INIT_LIST_HEAD(&neigh_node->list);
+
+ memcpy(neigh_node->addr, neigh, ETH_ALEN);
+ neigh_node->orig_node = orig_neigh_node;
+ neigh_node->if_incoming = if_incoming;
+
+ list_add_tail(&neigh_node->list, &orig_node->neigh_list);
+ return neigh_node;
+}
+
+void free_orig_node(void *data)
+{
+ struct list_head *list_pos, *list_pos_tmp;
+ struct neigh_node *neigh_node;
+ struct orig_node *orig_node = (struct orig_node *)data;
+
+ /* for all neighbors towards this originator ... */
+ list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) {
+ neigh_node = list_entry(list_pos, struct neigh_node, list);
+
+ list_del(list_pos);
+ kfree(neigh_node);
+ }
+
+ hna_global_del_orig(orig_node, "originator timed out");
+
+ kfree(orig_node->bcast_own);
+ kfree(orig_node->bcast_own_sum);
+ kfree(orig_node);
+}
+
+/* this function finds or creates an originator entry for the given
+ * address if it does not exits */
+struct orig_node *get_orig_node(uint8_t *addr)
+{
+ struct orig_node *orig_node;
+ struct hashtable_t *swaphash;
+ int size;
+
+ orig_node = ((struct orig_node *)hash_find(orig_hash, addr));
+
+ if (orig_node != NULL)
+ return orig_node;
+
+ bat_dbg(DBG_BATMAN, "Creating new originator: %pM \n", addr);
+
+ orig_node = kzalloc(sizeof(struct orig_node), GFP_ATOMIC);
+ if (!orig_node)
+ return NULL;
+
+ INIT_LIST_HEAD(&orig_node->neigh_list);
+
+ memcpy(orig_node->orig, addr, ETH_ALEN);
+ orig_node->router = NULL;
+ orig_node->batman_if = NULL;
+ orig_node->hna_buff = NULL;
+
+ size = num_ifs * sizeof(TYPE_OF_WORD) * NUM_WORDS;
+
+ orig_node->bcast_own = kzalloc(size, GFP_ATOMIC);
+ if (!orig_node->bcast_own)
+ goto free_orig_node;
+
+ size = num_ifs * sizeof(uint8_t);
+ orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC);
+ if (!orig_node->bcast_own_sum)
+ goto free_bcast_own;
+
+ if (hash_add(orig_hash, orig_node) < 0)
+ goto free_bcast_own_sum;
+
+ if (orig_hash->elements * 4 > orig_hash->size) {
+ swaphash = hash_resize(orig_hash, orig_hash->size * 2);
+
+ if (swaphash == NULL)
+ printk(KERN_ERR
+ "batman-adv:Couldn't resize orig hash table \n");
+ else
+ orig_hash = swaphash;
+ }
+
+ return orig_node;
+free_bcast_own_sum:
+ kfree(orig_node->bcast_own_sum);
+free_bcast_own:
+ kfree(orig_node->bcast_own);
+free_orig_node:
+ kfree(orig_node);
+ return NULL;
+}
+
+static bool purge_orig_neighbors(struct orig_node *orig_node,
+ struct neigh_node **best_neigh_node)
+{
+ struct list_head *list_pos, *list_pos_tmp;
+ struct neigh_node *neigh_node;
+ bool neigh_purged = false;
+
+ *best_neigh_node = NULL;
+
+
+ /* for all neighbors towards this originator ... */
+ list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) {
+ neigh_node = list_entry(list_pos, struct neigh_node, list);
+
+ if (time_after(jiffies,
+ (neigh_node->last_valid +
+ ((PURGE_TIMEOUT * HZ) / 1000)))) {
+
+ bat_dbg(DBG_BATMAN, "neighbor timeout: originator %pM, neighbor: %pM, last_valid %lu\n", orig_node->orig, neigh_node->addr, (neigh_node->last_valid / HZ));
+
+ neigh_purged = true;
+ list_del(list_pos);
+ kfree(neigh_node);
+ } else {
+ if ((*best_neigh_node == NULL) ||
+ (neigh_node->tq_avg > (*best_neigh_node)->tq_avg))
+ *best_neigh_node = neigh_node;
+ }
+ }
+ return neigh_purged;
+}
+
+
+static bool purge_orig_node(struct orig_node *orig_node)
+{
+ struct neigh_node *best_neigh_node;
+
+ if (time_after(jiffies,
+ (orig_node->last_valid +
+ ((2 * PURGE_TIMEOUT * HZ) / 1000)))) {
+
+ bat_dbg(DBG_BATMAN,
+ "Originator timeout: originator %pM, last_valid %lu\n",
+ orig_node->orig, (orig_node->last_valid / HZ));
+ return true;
+ } else {
+ if (purge_orig_neighbors(orig_node, &best_neigh_node))
+ update_routes(orig_node, best_neigh_node,
+ orig_node->hna_buff,
+ orig_node->hna_buff_len);
+ }
+ return false;
+}
+
+void purge_orig(struct work_struct *work)
+{
+ HASHIT(hashit);
+ struct orig_node *orig_node;
+ unsigned long flags;
+
+ spin_lock_irqsave(&orig_hash_lock, flags);
+
+ /* for all origins... */
+ while (hash_iterate(orig_hash, &hashit)) {
+ orig_node = hashit.bucket->data;
+ if (purge_orig_node(orig_node)) {
+ hash_remove_bucket(orig_hash, &hashit);
+ free_orig_node(orig_node);
+ }
+ }
+
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+ start_purge_timer();
+}
+
+
diff --git a/drivers/staging/batman-adv/log.h b/drivers/staging/batman-adv/originator.h
index 780e3abb48f..6ef7a054a0a 100644
--- a/drivers/staging/batman-adv/log.h
+++ b/drivers/staging/batman-adv/originator.h
@@ -19,14 +19,13 @@
*
*/
-extern const struct file_operations proc_log_operations;
-extern uint8_t log_level;
+int originator_init(void);
+void free_orig_node(void *data);
+void originator_free(void);
+void purge_orig(struct work_struct *work);
+struct orig_node *orig_find(char *mac);
+struct orig_node *get_orig_node(uint8_t *addr);
+struct neigh_node *
+create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node,
+ uint8_t *neigh, struct batman_if *if_incoming);
-int debug_log(int type, char *fmt, ...);
-int log_open(struct inode *inode, struct file *file);
-int log_release(struct inode *inode, struct file *file);
-ssize_t log_read(struct file *file, char __user *buf, size_t count,
- loff_t *ppos);
-ssize_t log_write(struct file *file, const char __user *buf, size_t count,
- loff_t *ppos);
-unsigned int log_poll(struct file *file, poll_table *wait);
diff --git a/drivers/staging/batman-adv/packet.h b/drivers/staging/batman-adv/packet.h
index 5627ca32601..ad006ce8b13 100644
--- a/drivers/staging/batman-adv/packet.h
+++ b/drivers/staging/batman-adv/packet.h
@@ -90,7 +90,7 @@ struct vis_packet {
uint8_t entries; /* number of entries behind this struct */
uint8_t ttl; /* TTL */
uint8_t vis_orig[6]; /* originator that informs about its
- * neighbours */
+ * neighbors */
uint8_t target_orig[6]; /* who should receive this packet */
uint8_t sender_orig[6]; /* who sent or rebroadcasted this packet */
} __attribute__((packed));
diff --git a/drivers/staging/batman-adv/proc.c b/drivers/staging/batman-adv/proc.c
index aac3df7f13f..7de60e84bc9 100644
--- a/drivers/staging/batman-adv/proc.c
+++ b/drivers/staging/batman-adv/proc.c
@@ -21,23 +21,18 @@
#include "main.h"
#include "proc.h"
-#include "log.h"
#include "routing.h"
#include "translation-table.h"
#include "hard-interface.h"
#include "types.h"
#include "hash.h"
#include "vis.h"
-#include "compat.h"
-
-static uint8_t vis_format = DOT_DRAW;
static struct proc_dir_entry *proc_batman_dir, *proc_interface_file;
static struct proc_dir_entry *proc_orig_interval_file, *proc_originators_file;
-static struct proc_dir_entry *proc_log_file, *proc_log_level_file;
static struct proc_dir_entry *proc_transt_local_file;
static struct proc_dir_entry *proc_transt_global_file;
-static struct proc_dir_entry *proc_vis_file, *proc_vis_format_file;
+static struct proc_dir_entry *proc_vis_srv_file, *proc_vis_data_file;
static struct proc_dir_entry *proc_aggr_file;
static int proc_interfaces_read(struct seq_file *seq, void *offset)
@@ -68,7 +63,7 @@ static ssize_t proc_interfaces_write(struct file *instance,
size_t count, loff_t *data)
{
char *if_string, *colon_ptr = NULL, *cr_ptr = NULL;
- int not_copied = 0, if_num = 0;
+ int not_copied = 0, if_num = 0, add_success;
struct batman_if *batman_if = NULL;
if_string = kmalloc(count, GFP_KERNEL);
@@ -77,8 +72,7 @@ static ssize_t proc_interfaces_write(struct file *instance,
return -ENOMEM;
if (count > IFNAMSIZ - 1) {
- debug_log(LOG_TYPE_WARN,
- "Can't add interface: device name is too long\n");
+ printk(KERN_WARNING "batman-adv:Can't add interface: device name is too long\n");
goto end;
}
@@ -105,7 +99,7 @@ static ssize_t proc_interfaces_write(struct file *instance,
rcu_read_lock();
list_for_each_entry_rcu(batman_if, &if_list, list) {
if (strncmp(batman_if->dev, if_string, count) == 0) {
- debug_log(LOG_TYPE_WARN, "Given interface is already active: %s\n", if_string);
+ printk(KERN_ERR "batman-adv:Given interface is already active: %s\n", if_string);
rcu_read_unlock();
goto end;
@@ -115,22 +109,17 @@ static ssize_t proc_interfaces_write(struct file *instance,
}
rcu_read_unlock();
- hardif_add_interface(if_string, if_num);
+ add_success = hardif_add_interface(if_string, if_num);
+ if (add_success < 0)
+ goto end;
+
+ num_ifs = if_num + 1;
if ((atomic_read(&module_state) == MODULE_INACTIVE) &&
(hardif_get_active_if_num() > 0))
activate_module();
- rcu_read_lock();
- if (list_empty(&if_list)) {
- rcu_read_unlock();
- goto end;
- }
- rcu_read_unlock();
-
- num_ifs = if_num + 1;
return count;
-
end:
kfree(if_string);
return count;
@@ -162,20 +151,18 @@ static ssize_t proc_orig_interval_write(struct file *file,
retval = strict_strtoul(interval_string, 10, &originator_interval_tmp);
if (retval) {
- debug_log(LOG_TYPE_WARN, "New originator interval invalid\n");
+ printk(KERN_ERR "batman-adv:New originator interval invalid\n");
goto end;
}
if (originator_interval_tmp <= JITTER * 2) {
- debug_log(LOG_TYPE_WARN,
- "New originator interval too small: %i (min: %i)\n",
- originator_interval_tmp, JITTER * 2);
+ printk(KERN_WARNING "batman-adv:New originator interval too small: %li (min: %i)\n",
+ originator_interval_tmp, JITTER * 2);
goto end;
}
- debug_log(LOG_TYPE_NOTICE,
- "Changing originator interval from: %i to: %i\n",
- atomic_read(&originator_interval), originator_interval_tmp);
+ printk(KERN_INFO "batman-adv:Changing originator interval from: %i to: %li\n",
+ atomic_read(&originator_interval), originator_interval_tmp);
atomic_set(&originator_interval, originator_interval_tmp);
@@ -191,11 +178,12 @@ static int proc_orig_interval_open(struct inode *inode, struct file *file)
static int proc_originators_read(struct seq_file *seq, void *offset)
{
- struct hash_it_t *hashit = NULL;
+ HASHIT(hashit);
struct orig_node *orig_node;
struct neigh_node *neigh_node;
int batman_count = 0;
char orig_str[ETH_STR_LEN], router_str[ETH_STR_LEN];
+ unsigned long flags;
rcu_read_lock();
if (list_empty(&if_list)) {
@@ -218,11 +206,11 @@ static int proc_originators_read(struct seq_file *seq, void *offset)
((struct batman_if *)if_list.next)->addr_str);
rcu_read_unlock();
- spin_lock(&orig_hash_lock);
+ spin_lock_irqsave(&orig_hash_lock, flags);
- while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
+ while (hash_iterate(orig_hash, &hashit)) {
- orig_node = hashit->bucket->data;
+ orig_node = hashit.bucket->data;
if (!orig_node->router)
continue;
@@ -249,7 +237,7 @@ static int proc_originators_read(struct seq_file *seq, void *offset)
}
- spin_unlock(&orig_hash_lock);
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
if (batman_count == 0)
seq_printf(seq, "No batman nodes in range ... \n");
@@ -263,84 +251,6 @@ static int proc_originators_open(struct inode *inode, struct file *file)
return single_open(file, proc_originators_read, NULL);
}
-static int proc_log_level_read(struct seq_file *seq, void *offset)
-{
-
- seq_printf(seq, "[x] %s (%d)\n", LOG_TYPE_CRIT_NAME, LOG_TYPE_CRIT);
- seq_printf(seq, "[%c] %s (%d)\n",
- (LOG_TYPE_WARN & log_level) ? 'x' : ' ',
- LOG_TYPE_WARN_NAME, LOG_TYPE_WARN);
- seq_printf(seq, "[%c] %s (%d)\n",
- (LOG_TYPE_NOTICE & log_level) ? 'x' : ' ',
- LOG_TYPE_NOTICE_NAME, LOG_TYPE_NOTICE);
- seq_printf(seq, "[%c] %s (%d)\n",
- (LOG_TYPE_BATMAN & log_level) ? 'x' : ' ',
- LOG_TYPE_BATMAN_NAME, LOG_TYPE_BATMAN);
- seq_printf(seq, "[%c] %s (%d)\n",
- (LOG_TYPE_ROUTES & log_level) ? 'x' : ' ',
- LOG_TYPE_ROUTES_NAME, LOG_TYPE_ROUTES);
- return 0;
-}
-
-static int proc_log_level_open(struct inode *inode, struct file *file)
-{
- return single_open(file, proc_log_level_read, NULL);
-}
-
-static ssize_t proc_log_level_write(struct file *instance,
- const char __user *userbuffer,
- size_t count, loff_t *data)
-{
- char *log_level_string, *tokptr, *cp;
- int finished, not_copied = 0;
- unsigned long log_level_tmp = 0;
-
- log_level_string = kmalloc(count, GFP_KERNEL);
-
- if (!log_level_string)
- return -ENOMEM;
-
- not_copied = copy_from_user(log_level_string, userbuffer, count);
- log_level_string[count - not_copied - 1] = 0;
-
- if (strict_strtoul(log_level_string, 10, &log_level_tmp) < 0) {
- /* was not a number, doing textual parsing */
- log_level_tmp = 0;
- tokptr = log_level_string;
-
- for (cp = log_level_string, finished = 0; !finished; cp++) {
- switch (*cp) {
- case 0:
- finished = 1;
- case ' ':
- case '\n':
- case '\t':
- *cp = 0;
- /* compare */
- if (strcmp(tokptr, LOG_TYPE_WARN_NAME) == 0)
- log_level_tmp |= LOG_TYPE_WARN;
- if (strcmp(tokptr, LOG_TYPE_NOTICE_NAME) == 0)
- log_level_tmp |= LOG_TYPE_NOTICE;
- if (strcmp(tokptr, LOG_TYPE_BATMAN_NAME) == 0)
- log_level_tmp |= LOG_TYPE_BATMAN;
- if (strcmp(tokptr, LOG_TYPE_ROUTES_NAME) == 0)
- log_level_tmp |= LOG_TYPE_ROUTES;
- tokptr = cp + 1;
- break;
- default:
- ;
- }
- }
- }
-
- debug_log(LOG_TYPE_CRIT, "Changing log_level from: %i to: %i\n",
- log_level, log_level_tmp);
- log_level = log_level_tmp;
-
- kfree(log_level_string);
- return count;
-}
-
static int proc_transt_local_read(struct seq_file *seq, void *offset)
{
char *buf;
@@ -405,172 +315,8 @@ static int proc_transt_global_open(struct inode *inode, struct file *file)
return single_open(file, proc_transt_global_read, NULL);
}
-/* insert interface to the list of interfaces of one originator */
-
-static void proc_vis_insert_interface(const uint8_t *interface,
- struct vis_if_list **if_entry,
- bool primary)
-{
- /* Did we get an empty list? (then insert imediately) */
- if(*if_entry == NULL) {
- *if_entry = kmalloc(sizeof(struct vis_if_list), GFP_KERNEL);
- if (*if_entry == NULL)
- return;
-
- (*if_entry)->primary = primary;
- (*if_entry)->next = NULL;
- memcpy((*if_entry)->addr, interface, ETH_ALEN);
- } else {
- struct vis_if_list *head_if_entry = *if_entry;
- /* Do we already have this interface in our list? */
- while (!compare_orig((*if_entry)->addr, (void *)interface)) {
-
- /* Or did we reach the end (then append the interface) */
- if ((*if_entry)->next == NULL) {
- (*if_entry)->next = kmalloc(sizeof(struct vis_if_list), GFP_KERNEL);
- if ((*if_entry)->next == NULL)
- return;
-
- memcpy((*if_entry)->next->addr, interface, ETH_ALEN);
- (*if_entry)->next->primary = primary;
- (*if_entry)->next->next = NULL;
- break;
- }
- *if_entry = (*if_entry)->next;
- }
- /* Rewind the list to its head */
- *if_entry = head_if_entry;
- }
-}
-/* read an entry */
-
-static void proc_vis_read_entry(struct seq_file *seq,
- struct vis_info_entry *entry,
- struct vis_if_list **if_entry,
- uint8_t *vis_orig,
- uint8_t current_format,
- uint8_t first_line)
-{
- char from[40];
- char to[40];
- int int_part, frac_part;
-
- addr_to_string(to, entry->dest);
- if (entry->quality == 0) {
-#ifndef VIS_SUBCLUSTERS_DISABLED
- proc_vis_insert_interface(vis_orig, if_entry, true);
-#endif /* VIS_SUBCLUSTERS_DISABLED */
- addr_to_string(from, vis_orig);
- if (current_format == DOT_DRAW) {
- seq_printf(seq, "\t\"%s\" -> \"%s\" [label=\"HNA\"]\n",
- from, to);
- } else {
- seq_printf(seq,
- "%s\t{ router : \"%s\", gateway : \"%s\", label : \"HNA\" }",
- (first_line ? "" : ",\n"), from, to);
- }
- } else {
-#ifndef VIS_SUBCLUSTERS_DISABLED
- proc_vis_insert_interface(entry->src, if_entry, compare_orig(entry->src, vis_orig));
-#endif /* VIS_SUBCLUSTERS_DISABLED */
- addr_to_string(from, entry->src);
-
- /* kernel has no printf-support for %f? it'd be better to return
- * this in float. */
-
- int_part = TQ_MAX_VALUE / entry->quality;
- frac_part = 1000 * TQ_MAX_VALUE / entry->quality - int_part * 1000;
-
- if (current_format == DOT_DRAW) {
- seq_printf(seq,
- "\t\"%s\" -> \"%s\" [label=\"%d.%d\"]\n",
- from, to, int_part, frac_part);
- } else {
- seq_printf(seq,
- "%s\t{ router : \"%s\", neighbour : \"%s\", label : %d.%d }",
- (first_line ? "" : ",\n"), from, to, int_part, frac_part);
- }
- }
-}
-
-
-static int proc_vis_read(struct seq_file *seq, void *offset)
-{
- struct hash_it_t *hashit = NULL;
- struct vis_info *info;
- struct vis_info_entry *entries;
- struct vis_if_list *if_entries = NULL;
- int i;
- uint8_t current_format, first_line = 1;
-#ifndef VIS_SUBCLUSTERS_DISABLED
- char tmp_addr_str[ETH_STR_LEN];
- struct vis_if_list *tmp_if_next;
-#endif /* VIS_SUBCLUSTERS_DISABLED */
-
- current_format = vis_format;
-
- rcu_read_lock();
- if (list_empty(&if_list) || (!is_vis_server())) {
- rcu_read_unlock();
- if (current_format == DOT_DRAW)
- seq_printf(seq, "digraph {\n}\n");
- goto end;
- }
-
- rcu_read_unlock();
-
- if (current_format == DOT_DRAW)
- seq_printf(seq, "digraph {\n");
-
- spin_lock(&vis_hash_lock);
- while (NULL != (hashit = hash_iterate(vis_hash, hashit))) {
- info = hashit->bucket->data;
- entries = (struct vis_info_entry *)
- ((char *)info + sizeof(struct vis_info));
-
- for (i = 0; i < info->packet.entries; i++) {
- proc_vis_read_entry(seq, &entries[i], &if_entries,
- info->packet.vis_orig,
- current_format, first_line);
- if (first_line)
- first_line = 0;
- }
-
-#ifndef VIS_SUBCLUSTERS_DISABLED
- /* Generate subgraphs from the collected items */
- if (current_format == DOT_DRAW) {
-
- addr_to_string(tmp_addr_str, info->packet.vis_orig);
- seq_printf(seq, "\tsubgraph \"cluster_%s\" {\n", tmp_addr_str);
- while (if_entries != NULL) {
-
- addr_to_string(tmp_addr_str, if_entries->addr);
- if (if_entries->primary)
- seq_printf(seq, "\t\t\"%s\" [peripheries=2]\n", tmp_addr_str);
- else
- seq_printf(seq, "\t\t\"%s\"\n", tmp_addr_str);
-
- /* ... and empty the list while doing this */
- tmp_if_next = if_entries->next;
- kfree(if_entries);
- if_entries = tmp_if_next;
- }
- seq_printf(seq, "\t}\n");
- }
-#endif /* VIS_SUBCLUSTERS_DISABLED */
- }
- spin_unlock(&vis_hash_lock);
-
- if (current_format == DOT_DRAW)
- seq_printf(seq, "}\n");
- else
- seq_printf(seq, "\n");
-end:
- return 0;
-}
-
/* setting the mode of the vis server by the user */
-static ssize_t proc_vis_write(struct file *file, const char __user * buffer,
+static ssize_t proc_vis_srv_write(struct file *file, const char __user * buffer,
size_t count, loff_t *ppos)
{
char *vis_mode_string;
@@ -584,72 +330,84 @@ static ssize_t proc_vis_write(struct file *file, const char __user * buffer,
not_copied = copy_from_user(vis_mode_string, buffer, count);
vis_mode_string[count - not_copied - 1] = 0;
- if (strcmp(vis_mode_string, "client") == 0) {
- debug_log(LOG_TYPE_NOTICE, "Setting VIS mode to client\n");
- vis_set_mode(VIS_TYPE_CLIENT_UPDATE);
- } else if (strcmp(vis_mode_string, "server") == 0) {
- debug_log(LOG_TYPE_NOTICE, "Setting VIS mode to server\n");
- vis_set_mode(VIS_TYPE_SERVER_SYNC);
+ if ((strcmp(vis_mode_string, "client") == 0) ||
+ (strcmp(vis_mode_string, "disabled") == 0)) {
+ printk(KERN_INFO "batman-adv:Setting VIS mode to client (disabling vis server)\n");
+ atomic_set(&vis_mode, VIS_TYPE_CLIENT_UPDATE);
+ } else if ((strcmp(vis_mode_string, "server") == 0) ||
+ (strcmp(vis_mode_string, "enabled") == 0)) {
+ printk(KERN_INFO "batman-adv:Setting VIS mode to server (enabling vis server)\n");
+ atomic_set(&vis_mode, VIS_TYPE_SERVER_SYNC);
} else
- debug_log(LOG_TYPE_WARN, "Unknown VIS mode: %s\n",
- vis_mode_string);
+ printk(KERN_ERR "batman-adv:Unknown VIS mode: %s\n",
+ vis_mode_string);
kfree(vis_mode_string);
return count;
}
-static int proc_vis_open(struct inode *inode, struct file *file)
+static int proc_vis_srv_read(struct seq_file *seq, void *offset)
{
- return single_open(file, proc_vis_read, NULL);
-}
+ int vis_server = atomic_read(&vis_mode);
+
+ seq_printf(seq, "[%c] client mode (server disabled) \n",
+ (vis_server == VIS_TYPE_CLIENT_UPDATE) ? 'x' : ' ');
+ seq_printf(seq, "[%c] server mode (server enabled) \n",
+ (vis_server == VIS_TYPE_SERVER_SYNC) ? 'x' : ' ');
-static int proc_vis_format_read(struct seq_file *seq, void *offset)
-{
- uint8_t current_format = vis_format;
-
- seq_printf(seq, "[%c] %s\n",
- (current_format == DOT_DRAW) ? 'x' : ' ',
- VIS_FORMAT_DD_NAME);
- seq_printf(seq, "[%c] %s\n",
- (current_format == JSON) ? 'x' : ' ',
- VIS_FORMAT_JSON_NAME);
return 0;
}
-static int proc_vis_format_open(struct inode *inode, struct file *file)
+static int proc_vis_srv_open(struct inode *inode, struct file *file)
{
- return single_open(file, proc_vis_format_read, NULL);
+ return single_open(file, proc_vis_srv_read, NULL);
}
-static ssize_t proc_vis_format_write(struct file *file,
- const char __user *buffer,
- size_t count, loff_t *ppos)
+static int proc_vis_data_read(struct seq_file *seq, void *offset)
{
- char *vis_format_string;
- int not_copied = 0;
+ HASHIT(hashit);
+ struct vis_info *info;
+ struct vis_info_entry *entries;
+ HLIST_HEAD(vis_if_list);
+ int i;
+ char tmp_addr_str[ETH_STR_LEN];
+ unsigned long flags;
+ int vis_server = atomic_read(&vis_mode);
+
+ rcu_read_lock();
+ if (list_empty(&if_list) || (vis_server == VIS_TYPE_CLIENT_UPDATE)) {
+ rcu_read_unlock();
+ goto end;
+ }
- vis_format_string = kmalloc(count, GFP_KERNEL);
+ rcu_read_unlock();
- if (!vis_format_string)
- return -ENOMEM;
+ spin_lock_irqsave(&vis_hash_lock, flags);
+ while (hash_iterate(vis_hash, &hashit)) {
+ info = hashit.bucket->data;
+ entries = (struct vis_info_entry *)
+ ((char *)info + sizeof(struct vis_info));
+ addr_to_string(tmp_addr_str, info->packet.vis_orig);
+ seq_printf(seq, "%s,", tmp_addr_str);
- not_copied = copy_from_user(vis_format_string, buffer, count);
- vis_format_string[count - not_copied - 1] = 0;
-
- if (strcmp(vis_format_string, VIS_FORMAT_DD_NAME) == 0) {
- debug_log(LOG_TYPE_NOTICE, "Setting VIS output format to: %s\n",
- VIS_FORMAT_DD_NAME);
- vis_format = DOT_DRAW;
- } else if (strcmp(vis_format_string, VIS_FORMAT_JSON_NAME) == 0) {
- debug_log(LOG_TYPE_NOTICE, "Setting VIS output format to: %s\n",
- VIS_FORMAT_JSON_NAME);
- vis_format = JSON;
- } else
- debug_log(LOG_TYPE_WARN, "Unknown VIS output format: %s\n",
- vis_format_string);
+ for (i = 0; i < info->packet.entries; i++) {
+ proc_vis_read_entry(seq, &entries[i], &vis_if_list,
+ info->packet.vis_orig);
+ }
- kfree(vis_format_string);
- return count;
+ /* add primary/secondary records */
+ proc_vis_read_prim_sec(seq, &vis_if_list);
+ seq_printf(seq, "\n");
+ }
+ spin_unlock_irqrestore(&vis_hash_lock, flags);
+
+end:
+ return 0;
+}
+
+static int proc_vis_data_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, proc_vis_data_read, NULL);
}
static int proc_aggr_read(struct seq_file *seq, void *offset)
@@ -665,6 +423,7 @@ static ssize_t proc_aggr_write(struct file *file, const char __user *buffer,
char *aggr_string;
int not_copied = 0;
unsigned long aggregation_enabled_tmp;
+ int retval;
aggr_string = kmalloc(count, GFP_KERNEL);
@@ -674,22 +433,21 @@ static ssize_t proc_aggr_write(struct file *file, const char __user *buffer,
not_copied = copy_from_user(aggr_string, buffer, count);
aggr_string[count - not_copied - 1] = 0;
- strict_strtoul(aggr_string, 10, &aggregation_enabled_tmp);
+ retval = strict_strtoul(aggr_string, 10, &aggregation_enabled_tmp);
- if ((aggregation_enabled_tmp != 0) && (aggregation_enabled_tmp != 1)) {
- debug_log(LOG_TYPE_WARN, "Aggregation can only be enabled (1) or disabled (0), given value: %li\n", aggregation_enabled_tmp);
- goto end;
+ if (retval || aggregation_enabled_tmp > 1) {
+ printk(KERN_ERR "batman-adv:Aggregation can only be enabled (1) or disabled (0), given value: %li\n", aggregation_enabled_tmp);
+ } else {
+ printk(KERN_INFO "batman-adv:Changing aggregation from: %s (%i) to: %s (%li)\n",
+ (atomic_read(&aggregation_enabled) == 1 ?
+ "enabled" : "disabled"),
+ atomic_read(&aggregation_enabled),
+ (aggregation_enabled_tmp == 1 ? "enabled" : "disabled"),
+ aggregation_enabled_tmp);
+ atomic_set(&aggregation_enabled,
+ (unsigned)aggregation_enabled_tmp);
}
- debug_log(LOG_TYPE_NOTICE, "Changing aggregation from: %s (%i) to: %s (%li)\n",
- (atomic_read(&aggregation_enabled) == 1 ?
- "enabled" : "disabled"),
- atomic_read(&aggregation_enabled),
- (aggregation_enabled_tmp == 1 ? "enabled" : "disabled"),
- aggregation_enabled_tmp);
-
- atomic_set(&aggregation_enabled, (unsigned)aggregation_enabled_tmp);
-end:
kfree(aggr_string);
return count;
}
@@ -715,20 +473,20 @@ static const struct file_operations proc_aggr_fops = {
.release = single_release,
};
-static const struct file_operations proc_vis_format_fops = {
+static const struct file_operations proc_vis_srv_fops = {
.owner = THIS_MODULE,
- .open = proc_vis_format_open,
+ .open = proc_vis_srv_open,
.read = seq_read,
- .write = proc_vis_format_write,
+ .write = proc_vis_srv_write,
.llseek = seq_lseek,
.release = single_release,
};
-static const struct file_operations proc_vis_fops = {
+static const struct file_operations proc_vis_data_fops = {
.owner = THIS_MODULE,
- .open = proc_vis_open,
+ .open = proc_vis_data_open,
.read = seq_read,
- .write = proc_vis_write,
+ .write = proc_dummy_write,
.llseek = seq_lseek,
.release = single_release,
};
@@ -760,15 +518,6 @@ static const struct file_operations proc_transt_global_fops = {
.release = single_release,
};
-static const struct file_operations proc_log_level_fops = {
- .owner = THIS_MODULE,
- .open = proc_log_level_open,
- .read = seq_read,
- .write = proc_log_level_write,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
static const struct file_operations proc_interfaces_fops = {
.owner = THIS_MODULE,
.open = proc_interfaces_open,
@@ -795,12 +544,6 @@ void cleanup_procfs(void)
if (proc_transt_local_file)
remove_proc_entry(PROC_FILE_TRANST_LOCAL, proc_batman_dir);
- if (proc_log_file)
- remove_proc_entry(PROC_FILE_LOG, proc_batman_dir);
-
- if (proc_log_level_file)
- remove_proc_entry(PROC_FILE_LOG_LEVEL, proc_batman_dir);
-
if (proc_originators_file)
remove_proc_entry(PROC_FILE_ORIGINATORS, proc_batman_dir);
@@ -810,11 +553,11 @@ void cleanup_procfs(void)
if (proc_interface_file)
remove_proc_entry(PROC_FILE_INTERFACES, proc_batman_dir);
- if (proc_vis_file)
- remove_proc_entry(PROC_FILE_VIS, proc_batman_dir);
+ if (proc_vis_data_file)
+ remove_proc_entry(PROC_FILE_VIS_DATA, proc_batman_dir);
- if (proc_vis_format_file)
- remove_proc_entry(PROC_FILE_VIS_FORMAT, proc_batman_dir);
+ if (proc_vis_srv_file)
+ remove_proc_entry(PROC_FILE_VIS_SRV, proc_batman_dir);
if (proc_aggr_file)
remove_proc_entry(PROC_FILE_AGGR, proc_batman_dir);
@@ -862,17 +605,6 @@ int setup_procfs(void)
return -EFAULT;
}
- proc_log_level_file = create_proc_entry(PROC_FILE_LOG_LEVEL,
- S_IWUSR | S_IRUGO,
- proc_batman_dir);
- if (proc_log_level_file) {
- proc_log_level_file->proc_fops = &proc_log_level_fops;
- } else {
- printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_LOG_LEVEL);
- cleanup_procfs();
- return -EFAULT;
- }
-
proc_originators_file = create_proc_entry(PROC_FILE_ORIGINATORS,
S_IRUGO, proc_batman_dir);
if (proc_originators_file) {
@@ -883,16 +615,6 @@ int setup_procfs(void)
return -EFAULT;
}
- proc_log_file = create_proc_entry(PROC_FILE_LOG,
- S_IRUGO, proc_batman_dir);
- if (proc_log_file) {
- proc_log_file->proc_fops = &proc_log_operations;
- } else {
- printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_FILE_LOG, PROC_FILE_GATEWAYS);
- cleanup_procfs();
- return -EFAULT;
- }
-
proc_transt_local_file = create_proc_entry(PROC_FILE_TRANST_LOCAL,
S_IRUGO, proc_batman_dir);
if (proc_transt_local_file) {
@@ -913,23 +635,23 @@ int setup_procfs(void)
return -EFAULT;
}
- proc_vis_file = create_proc_entry(PROC_FILE_VIS, S_IWUSR | S_IRUGO,
- proc_batman_dir);
- if (proc_vis_file) {
- proc_vis_file->proc_fops = &proc_vis_fops;
+ proc_vis_srv_file = create_proc_entry(PROC_FILE_VIS_SRV,
+ S_IWUSR | S_IRUGO,
+ proc_batman_dir);
+ if (proc_vis_srv_file) {
+ proc_vis_srv_file->proc_fops = &proc_vis_srv_fops;
} else {
- printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS);
+ printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_SRV);
cleanup_procfs();
return -EFAULT;
}
- proc_vis_format_file = create_proc_entry(PROC_FILE_VIS_FORMAT,
- S_IWUSR | S_IRUGO,
- proc_batman_dir);
- if (proc_vis_format_file) {
- proc_vis_format_file->proc_fops = &proc_vis_format_fops;
+ proc_vis_data_file = create_proc_entry(PROC_FILE_VIS_DATA, S_IRUGO,
+ proc_batman_dir);
+ if (proc_vis_data_file) {
+ proc_vis_data_file->proc_fops = &proc_vis_data_fops;
} else {
- printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_FORMAT);
+ printk(KERN_ERR "batman-adv: Registering the '/proc/net/%s/%s' file failed\n", PROC_ROOT_DIR, PROC_FILE_VIS_DATA);
cleanup_procfs();
return -EFAULT;
}
@@ -946,5 +668,3 @@ int setup_procfs(void)
return 0;
}
-
-
diff --git a/drivers/staging/batman-adv/proc.h b/drivers/staging/batman-adv/proc.h
index 16d3efdebe5..cd690e0f3e4 100644
--- a/drivers/staging/batman-adv/proc.h
+++ b/drivers/staging/batman-adv/proc.h
@@ -31,19 +31,10 @@
#define PROC_FILE_LOG_LEVEL "log_level"
#define PROC_FILE_TRANST_LOCAL "transtable_local"
#define PROC_FILE_TRANST_GLOBAL "transtable_global"
-#define PROC_FILE_VIS "vis"
-#define PROC_FILE_VIS_FORMAT "vis_format"
+#define PROC_FILE_VIS_SRV "vis_server"
+#define PROC_FILE_VIS_DATA "vis_data"
#define PROC_FILE_AGGR "aggregate_ogm"
void cleanup_procfs(void);
int setup_procfs(void);
-/* While scanning for vis-entries of a particular vis-originator
- * this list collects its interfaces to create a subgraph/cluster
- * out of them later
- */
-struct vis_if_list {
- uint8_t addr[ETH_ALEN];
- bool primary;
- struct vis_if_list *next;
-};
diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c
index 4a14c363ac2..d89048beebe 100644
--- a/drivers/staging/batman-adv/routing.c
+++ b/drivers/staging/batman-adv/routing.c
@@ -19,304 +19,226 @@
*
*/
-
-
-
-
#include "main.h"
#include "routing.h"
-#include "log.h"
#include "send.h"
+#include "hash.h"
#include "soft-interface.h"
#include "hard-interface.h"
#include "device.h"
#include "translation-table.h"
+#include "originator.h"
#include "types.h"
-#include "hash.h"
#include "ring_buffer.h"
#include "vis.h"
#include "aggregation.h"
-#include "compat.h"
-
-
DECLARE_WAIT_QUEUE_HEAD(thread_wait);
-static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig);
-
-static atomic_t data_ready_cond;
-atomic_t exit_cond;
-
-static void start_purge_timer(void)
-{
- queue_delayed_work(bat_event_workqueue, &purge_orig_wq, 1 * HZ);
-}
-
-int originator_init(void)
-{
- if (orig_hash)
- return 1;
-
- spin_lock(&orig_hash_lock);
- orig_hash = hash_new(128, compare_orig, choose_orig);
-
- if (!orig_hash)
- goto err;
-
- spin_unlock(&orig_hash_lock);
- start_purge_timer();
- return 1;
-
-err:
- spin_unlock(&orig_hash_lock);
- return 0;
-}
-
-void originator_free(void)
-{
- if (!orig_hash)
- return;
-
- cancel_delayed_work_sync(&purge_orig_wq);
-
- spin_lock(&orig_hash_lock);
- hash_delete(orig_hash, free_orig_node);
- orig_hash = NULL;
- spin_unlock(&orig_hash_lock);
-}
-static struct neigh_node *create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, uint8_t *neigh, struct batman_if *if_incoming)
+void slide_own_bcast_window(struct batman_if *batman_if)
{
- struct neigh_node *neigh_node;
+ HASHIT(hashit);
+ struct orig_node *orig_node;
+ TYPE_OF_WORD *word;
+ unsigned long flags;
- debug_log(LOG_TYPE_BATMAN, "Creating new last-hop neighbour of originator\n");
+ spin_lock_irqsave(&orig_hash_lock, flags);
- neigh_node = kmalloc(sizeof(struct neigh_node), GFP_ATOMIC);
- memset(neigh_node, 0, sizeof(struct neigh_node));
- INIT_LIST_HEAD(&neigh_node->list);
+ while (hash_iterate(orig_hash, &hashit)) {
+ orig_node = hashit.bucket->data;
+ word = &(orig_node->bcast_own[batman_if->if_num * NUM_WORDS]);
- memcpy(neigh_node->addr, neigh, ETH_ALEN);
- neigh_node->orig_node = orig_neigh_node;
- neigh_node->if_incoming = if_incoming;
+ bit_get_packet(word, 1, 0);
+ orig_node->bcast_own_sum[batman_if->if_num] =
+ bit_packet_count(word);
+ }
- list_add_tail(&neigh_node->list, &orig_node->neigh_list);
- return neigh_node;
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
}
-void free_orig_node(void *data)
+static void update_HNA(struct orig_node *orig_node,
+ unsigned char *hna_buff, int hna_buff_len)
{
- struct list_head *list_pos, *list_pos_tmp;
- struct neigh_node *neigh_node;
- struct orig_node *orig_node = (struct orig_node *)data;
+ if ((hna_buff_len != orig_node->hna_buff_len) ||
+ ((hna_buff_len > 0) &&
+ (orig_node->hna_buff_len > 0) &&
+ (memcmp(orig_node->hna_buff, hna_buff, hna_buff_len) != 0))) {
- /* for all neighbours towards this originator ... */
- list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) {
- neigh_node = list_entry(list_pos, struct neigh_node, list);
+ if (orig_node->hna_buff_len > 0)
+ hna_global_del_orig(orig_node,
+ "originator changed hna");
- list_del(list_pos);
- kfree(neigh_node);
+ if ((hna_buff_len > 0) && (hna_buff != NULL))
+ hna_global_add_orig(orig_node, hna_buff, hna_buff_len);
}
-
- hna_global_del_orig(orig_node, "originator timed out");
-
- kfree(orig_node->bcast_own);
- kfree(orig_node->bcast_own_sum);
- kfree(orig_node);
}
-/* this function finds or creates an originator entry for the given address if it does not exits */
-static struct orig_node *get_orig_node(uint8_t *addr)
+static void update_route(struct orig_node *orig_node,
+ struct neigh_node *neigh_node,
+ unsigned char *hna_buff, int hna_buff_len)
{
- struct orig_node *orig_node;
- struct hashtable_t *swaphash;
- char orig_str[ETH_STR_LEN];
-
- orig_node = ((struct orig_node *)hash_find(orig_hash, addr));
-
- if (orig_node != NULL)
- return orig_node;
-
- addr_to_string(orig_str, addr);
- debug_log(LOG_TYPE_BATMAN, "Creating new originator: %s \n", orig_str);
-
- orig_node = kmalloc(sizeof(struct orig_node), GFP_ATOMIC);
- memset(orig_node, 0, sizeof(struct orig_node));
- INIT_LIST_HEAD(&orig_node->neigh_list);
-
- memcpy(orig_node->orig, addr, ETH_ALEN);
- orig_node->router = NULL;
- orig_node->batman_if = NULL;
- orig_node->hna_buff = NULL;
+ /* route deleted */
+ if ((orig_node->router != NULL) && (neigh_node == NULL)) {
- orig_node->bcast_own = kmalloc(num_ifs * sizeof(TYPE_OF_WORD) * NUM_WORDS, GFP_ATOMIC);
- memset(orig_node->bcast_own, 0, num_ifs * sizeof(TYPE_OF_WORD) * NUM_WORDS);
+ bat_dbg(DBG_ROUTES, "Deleting route towards: %pM\n",
+ orig_node->orig);
+ hna_global_del_orig(orig_node, "originator timed out");
- orig_node->bcast_own_sum = kmalloc(num_ifs * sizeof(uint8_t), GFP_ATOMIC);
- memset(orig_node->bcast_own_sum, 0, num_ifs * sizeof(uint8_t));
-
- hash_add(orig_hash, orig_node);
+ /* route added */
+ } else if ((orig_node->router == NULL) && (neigh_node != NULL)) {
- if (orig_hash->elements * 4 > orig_hash->size) {
- swaphash = hash_resize(orig_hash, orig_hash->size * 2);
+ bat_dbg(DBG_ROUTES,
+ "Adding route towards: %pM (via %pM)\n",
+ orig_node->orig, neigh_node->addr);
+ hna_global_add_orig(orig_node, hna_buff, hna_buff_len);
- if (swaphash == NULL)
- debug_log(LOG_TYPE_CRIT, "Couldn't resize orig hash table \n");
- else
- orig_hash = swaphash;
+ /* route changed */
+ } else {
+ bat_dbg(DBG_ROUTES, "Changing route towards: %pM (now via %pM - was via %pM)\n", orig_node->orig, neigh_node->addr, orig_node->router->addr);
}
- return orig_node;
-}
-
-void slide_own_bcast_window(struct batman_if *batman_if)
-{
- struct hash_it_t *hashit = NULL;
- struct orig_node *orig_node;
-
- spin_lock(&orig_hash_lock);
-
- while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
- orig_node = hashit->bucket->data;
-
- bit_get_packet((TYPE_OF_WORD *)&(orig_node->bcast_own[batman_if->if_num * NUM_WORDS]), 1, 0);
- orig_node->bcast_own_sum[batman_if->if_num] = bit_packet_count((TYPE_OF_WORD *)&(orig_node->bcast_own[batman_if->if_num * NUM_WORDS]));
- }
+ if (neigh_node != NULL)
+ orig_node->batman_if = neigh_node->if_incoming;
+ else
+ orig_node->batman_if = NULL;
- spin_unlock(&orig_hash_lock);
+ orig_node->router = neigh_node;
}
-static void update_routes(struct orig_node *orig_node, struct neigh_node *neigh_node, unsigned char *hna_buff, int hna_buff_len)
+
+void update_routes(struct orig_node *orig_node,
+ struct neigh_node *neigh_node,
+ unsigned char *hna_buff, int hna_buff_len)
{
- char orig_str[ETH_STR_LEN], neigh_str[ETH_STR_LEN], router_str[ETH_STR_LEN];
if (orig_node == NULL)
return;
- if (orig_node->router != neigh_node) {
- addr_to_string(orig_str, orig_node->orig);
-
- /* route deleted */
- if ((orig_node->router != NULL) && (neigh_node == NULL)) {
-
- debug_log(LOG_TYPE_ROUTES, "Deleting route towards: %s\n", orig_str);
- hna_global_del_orig(orig_node, "originator timed out");
-
- /* route added */
- } else if ((orig_node->router == NULL) && (neigh_node != NULL)) {
-
- addr_to_string(neigh_str, neigh_node->addr);
- debug_log(LOG_TYPE_ROUTES, "Adding route towards: %s (via %s)\n", orig_str, neigh_str);
- hna_global_add_orig(orig_node, hna_buff, hna_buff_len);
-
- /* route changed */
- } else {
-
- addr_to_string(neigh_str, neigh_node->addr);
- addr_to_string(router_str, orig_node->router->addr);
- debug_log(LOG_TYPE_ROUTES, "Changing route towards: %s (now via %s - was via %s)\n", orig_str, neigh_str, router_str);
-
- }
-
- if (neigh_node != NULL)
- orig_node->batman_if = neigh_node->if_incoming;
- else
- orig_node->batman_if = NULL;
-
- orig_node->router = neigh_node;
-
+ if (orig_node->router != neigh_node)
+ update_route(orig_node, neigh_node, hna_buff, hna_buff_len);
/* may be just HNA changed */
- } else {
-
- if ((hna_buff_len != orig_node->hna_buff_len) || ((hna_buff_len > 0) && (orig_node->hna_buff_len > 0) && (memcmp(orig_node->hna_buff, hna_buff, hna_buff_len) != 0))) {
-
- if (orig_node->hna_buff_len > 0)
- hna_global_del_orig(orig_node, "originator changed hna");
-
- if ((hna_buff_len > 0) && (hna_buff != NULL))
- hna_global_add_orig(orig_node, hna_buff, hna_buff_len);
-
- }
-
- }
+ else
+ update_HNA(orig_node, hna_buff, hna_buff_len);
}
-static int isBidirectionalNeigh(struct orig_node *orig_node, struct orig_node *orig_neigh_node, struct batman_packet *batman_packet, struct batman_if *if_incoming)
+static int isBidirectionalNeigh(struct orig_node *orig_node,
+ struct orig_node *orig_neigh_node,
+ struct batman_packet *batman_packet,
+ struct batman_if *if_incoming)
{
struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
- char orig_str[ETH_STR_LEN], neigh_str[ETH_STR_LEN];
unsigned char total_count;
- addr_to_string(orig_str, orig_node->orig);
- addr_to_string(neigh_str, orig_neigh_node->orig);
-
if (orig_node == orig_neigh_node) {
- list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
+ list_for_each_entry(tmp_neigh_node,
+ &orig_node->neigh_list,
+ list) {
- if (compare_orig(tmp_neigh_node->addr, orig_neigh_node->orig) && (tmp_neigh_node->if_incoming == if_incoming))
+ if (compare_orig(tmp_neigh_node->addr,
+ orig_neigh_node->orig) &&
+ (tmp_neigh_node->if_incoming == if_incoming))
neigh_node = tmp_neigh_node;
}
- if (neigh_node == NULL)
- neigh_node = create_neighbor(orig_node, orig_neigh_node, orig_neigh_node->orig, if_incoming);
+ if (!neigh_node)
+ neigh_node = create_neighbor(orig_node,
+ orig_neigh_node,
+ orig_neigh_node->orig,
+ if_incoming);
+ /* create_neighbor failed, return 0 */
+ if (!neigh_node)
+ return 0;
neigh_node->last_valid = jiffies;
} else {
/* find packet count of corresponding one hop neighbor */
- list_for_each_entry(tmp_neigh_node, &orig_neigh_node->neigh_list, list) {
+ list_for_each_entry(tmp_neigh_node,
+ &orig_neigh_node->neigh_list, list) {
- if (compare_orig(tmp_neigh_node->addr, orig_neigh_node->orig) && (tmp_neigh_node->if_incoming == if_incoming))
+ if (compare_orig(tmp_neigh_node->addr,
+ orig_neigh_node->orig) &&
+ (tmp_neigh_node->if_incoming == if_incoming))
neigh_node = tmp_neigh_node;
}
- if (neigh_node == NULL)
- neigh_node = create_neighbor(orig_neigh_node, orig_neigh_node, orig_neigh_node->orig, if_incoming);
+ if (!neigh_node)
+ neigh_node = create_neighbor(orig_neigh_node,
+ orig_neigh_node,
+ orig_neigh_node->orig,
+ if_incoming);
+ /* create_neighbor failed, return 0 */
+ if (!neigh_node)
+ return 0;
}
orig_node->last_valid = jiffies;
/* pay attention to not get a value bigger than 100 % */
- total_count = (orig_neigh_node->bcast_own_sum[if_incoming->if_num] > neigh_node->real_packet_count ? neigh_node->real_packet_count : orig_neigh_node->bcast_own_sum[if_incoming->if_num]);
+ total_count = (orig_neigh_node->bcast_own_sum[if_incoming->if_num] >
+ neigh_node->real_packet_count ?
+ neigh_node->real_packet_count :
+ orig_neigh_node->bcast_own_sum[if_incoming->if_num]);
/* if we have too few packets (too less data) we set tq_own to zero */
/* if we receive too few packets it is not considered bidirectional */
- if ((total_count < TQ_LOCAL_BIDRECT_SEND_MINIMUM) || (neigh_node->real_packet_count < TQ_LOCAL_BIDRECT_RECV_MINIMUM))
+ if ((total_count < TQ_LOCAL_BIDRECT_SEND_MINIMUM) ||
+ (neigh_node->real_packet_count < TQ_LOCAL_BIDRECT_RECV_MINIMUM))
orig_neigh_node->tq_own = 0;
else
- /* neigh_node->real_packet_count is never zero as we only purge old information when getting new information */
- orig_neigh_node->tq_own = (TQ_MAX_VALUE * total_count) / neigh_node->real_packet_count;
+ /* neigh_node->real_packet_count is never zero as we
+ * only purge old information when getting new
+ * information */
+ orig_neigh_node->tq_own = (TQ_MAX_VALUE * total_count) /
+ neigh_node->real_packet_count;
/*
- * 1 - ((1-x) ** 3), normalized to TQ_MAX_VALUE
- * this does affect the nearly-symmetric links only a little,
- * but punishes asymmetric links more.
- * this will give a value between 0 and TQ_MAX_VALUE
+ * 1 - ((1-x) ** 3), normalized to TQ_MAX_VALUE this does
+ * affect the nearly-symmetric links only a little, but
+ * punishes asymmetric links more. This will give a value
+ * between 0 and TQ_MAX_VALUE
*/
- orig_neigh_node->tq_asym_penalty = TQ_MAX_VALUE - (TQ_MAX_VALUE *
- (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count) *
- (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count) *
- (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count)) /
- (TQ_LOCAL_WINDOW_SIZE * TQ_LOCAL_WINDOW_SIZE * TQ_LOCAL_WINDOW_SIZE);
-
- batman_packet->tq = ((batman_packet->tq * orig_neigh_node->tq_own * orig_neigh_node->tq_asym_penalty) / (TQ_MAX_VALUE * TQ_MAX_VALUE));
-
- debug_log(LOG_TYPE_BATMAN, "bidirectional: orig = %-15s neigh = %-15s => own_bcast = %2i, real recv = %2i, local tq: %3i, asym_penalty: %3i, total tq: %3i \n",
- orig_str, neigh_str, total_count, neigh_node->real_packet_count, orig_neigh_node->tq_own, orig_neigh_node->tq_asym_penalty, batman_packet->tq);
-
- /* if link has the minimum required transmission quality consider it bidirectional */
+ orig_neigh_node->tq_asym_penalty =
+ TQ_MAX_VALUE -
+ (TQ_MAX_VALUE *
+ (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count) *
+ (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count) *
+ (TQ_LOCAL_WINDOW_SIZE - neigh_node->real_packet_count)) /
+ (TQ_LOCAL_WINDOW_SIZE *
+ TQ_LOCAL_WINDOW_SIZE *
+ TQ_LOCAL_WINDOW_SIZE);
+
+ batman_packet->tq = ((batman_packet->tq *
+ orig_neigh_node->tq_own *
+ orig_neigh_node->tq_asym_penalty) /
+ (TQ_MAX_VALUE * TQ_MAX_VALUE));
+
+ bat_dbg(DBG_BATMAN, "bidirectional: orig = %-15pM neigh = %-15pM => own_bcast = %2i, real recv = %2i, local tq: %3i, asym_penalty: %3i, total tq: %3i \n",
+ orig_node->orig, orig_neigh_node->orig, total_count,
+ neigh_node->real_packet_count, orig_neigh_node->tq_own,
+ orig_neigh_node->tq_asym_penalty, batman_packet->tq);
+
+ /* if link has the minimum required transmission quality
+ * consider it bidirectional */
if (batman_packet->tq >= TQ_TOTAL_BIDRECT_LIMIT)
return 1;
return 0;
}
-static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr, struct batman_packet *batman_packet, struct batman_if *if_incoming, unsigned char *hna_buff, int hna_buff_len, char is_duplicate)
+static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr,
+ struct batman_packet *batman_packet,
+ struct batman_if *if_incoming,
+ unsigned char *hna_buff, int hna_buff_len,
+ char is_duplicate)
{
struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL;
int tmp_hna_buff_len;
- debug_log(LOG_TYPE_BATMAN, "update_originator(): Searching and updating originator entry of received packet \n");
+ bat_dbg(DBG_BATMAN, "update_originator(): Searching and updating originator entry of received packet \n");
list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
- if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) && (tmp_neigh_node->if_incoming == if_incoming)) {
+ if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) &&
+ (tmp_neigh_node->if_incoming == if_incoming)) {
neigh_node = tmp_neigh_node;
continue;
}
@@ -324,19 +246,34 @@ static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr, stru
if (is_duplicate)
continue;
- ring_buffer_set(tmp_neigh_node->tq_recv, &tmp_neigh_node->tq_index, 0);
- tmp_neigh_node->tq_avg = ring_buffer_avg(tmp_neigh_node->tq_recv);
+ ring_buffer_set(tmp_neigh_node->tq_recv,
+ &tmp_neigh_node->tq_index, 0);
+ tmp_neigh_node->tq_avg =
+ ring_buffer_avg(tmp_neigh_node->tq_recv);
}
- if (neigh_node == NULL)
- neigh_node = create_neighbor(orig_node, get_orig_node(ethhdr->h_source), ethhdr->h_source, if_incoming);
- else
- debug_log(LOG_TYPE_BATMAN, "Updating existing last-hop neighbour of originator\n");
+ if (!neigh_node) {
+ struct orig_node *orig_tmp;
+
+ orig_tmp = get_orig_node(ethhdr->h_source);
+ if (!orig_tmp)
+ return;
+
+ neigh_node = create_neighbor(orig_node,
+ orig_tmp,
+ ethhdr->h_source, if_incoming);
+ if (!neigh_node)
+ return;
+ } else
+ bat_dbg(DBG_BATMAN,
+ "Updating existing last-hop neighbor of originator\n");
orig_node->flags = batman_packet->flags;
neigh_node->last_valid = jiffies;
- ring_buffer_set(neigh_node->tq_recv, &neigh_node->tq_index, batman_packet->tq);
+ ring_buffer_set(neigh_node->tq_recv,
+ &neigh_node->tq_index,
+ batman_packet->tq);
neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv);
if (!is_duplicate) {
@@ -344,9 +281,11 @@ static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr, stru
neigh_node->last_ttl = batman_packet->ttl;
}
- tmp_hna_buff_len = (hna_buff_len > batman_packet->num_hna * ETH_ALEN ? batman_packet->num_hna * ETH_ALEN : hna_buff_len);
+ tmp_hna_buff_len = (hna_buff_len > batman_packet->num_hna * ETH_ALEN ?
+ batman_packet->num_hna * ETH_ALEN : hna_buff_len);
- /* if this neighbor already is our next hop there is nothing to change */
+ /* if this neighbor already is our next hop there is nothing
+ * to change */
if (orig_node->router == neigh_node)
goto update_hna;
@@ -355,11 +294,12 @@ static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr, stru
(orig_node->router->tq_avg > neigh_node->tq_avg))
goto update_hna;
- /* if the TQ is the same and the link not more symetric we won't consider it either */
+ /* if the TQ is the same and the link not more symetric we
+ * won't consider it either */
if ((orig_node->router) &&
((neigh_node->tq_avg == orig_node->router->tq_avg) &&
- (orig_node->router->orig_node->bcast_own_sum[if_incoming->if_num] >=
- neigh_node->orig_node->bcast_own_sum[if_incoming->if_num])))
+ (orig_node->router->orig_node->bcast_own_sum[if_incoming->if_num]
+ >= neigh_node->orig_node->bcast_own_sum[if_incoming->if_num])))
goto update_hna;
update_routes(orig_node, neigh_node, hna_buff, tmp_hna_buff_len);
@@ -367,60 +307,72 @@ static void update_orig(struct orig_node *orig_node, struct ethhdr *ethhdr, stru
update_hna:
update_routes(orig_node, orig_node->router, hna_buff, tmp_hna_buff_len);
- return;
}
-static char count_real_packets(struct ethhdr *ethhdr, struct batman_packet *batman_packet, struct batman_if *if_incoming)
+static char count_real_packets(struct ethhdr *ethhdr,
+ struct batman_packet *batman_packet,
+ struct batman_if *if_incoming)
{
struct orig_node *orig_node;
struct neigh_node *tmp_neigh_node;
char is_duplicate = 0;
-
+ uint16_t seq_diff;
orig_node = get_orig_node(batman_packet->orig);
if (orig_node == NULL)
return 0;
-
list_for_each_entry(tmp_neigh_node, &orig_node->neigh_list, list) {
if (!is_duplicate)
- is_duplicate = get_bit_status(tmp_neigh_node->real_bits, orig_node->last_real_seqno, batman_packet->seqno);
-
- if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) && (tmp_neigh_node->if_incoming == if_incoming))
- bit_get_packet(tmp_neigh_node->real_bits, batman_packet->seqno - orig_node->last_real_seqno, 1);
+ is_duplicate =
+ get_bit_status(tmp_neigh_node->real_bits,
+ orig_node->last_real_seqno,
+ batman_packet->seqno);
+ seq_diff = batman_packet->seqno - orig_node->last_real_seqno;
+ if (compare_orig(tmp_neigh_node->addr, ethhdr->h_source) &&
+ (tmp_neigh_node->if_incoming == if_incoming))
+ bit_get_packet(tmp_neigh_node->real_bits, seq_diff, 1);
else
- bit_get_packet(tmp_neigh_node->real_bits, batman_packet->seqno - orig_node->last_real_seqno, 0);
+ bit_get_packet(tmp_neigh_node->real_bits, seq_diff, 0);
- tmp_neigh_node->real_packet_count = bit_packet_count(tmp_neigh_node->real_bits);
+ tmp_neigh_node->real_packet_count =
+ bit_packet_count(tmp_neigh_node->real_bits);
}
if (!is_duplicate) {
- debug_log(LOG_TYPE_BATMAN, "updating last_seqno: old %d, new %d \n", orig_node->last_real_seqno, batman_packet->seqno);
+ bat_dbg(DBG_BATMAN, "updating last_seqno: old %d, new %d \n",
+ orig_node->last_real_seqno, batman_packet->seqno);
orig_node->last_real_seqno = batman_packet->seqno;
}
return is_duplicate;
}
-void receive_bat_packet(struct ethhdr *ethhdr, struct batman_packet *batman_packet, unsigned char *hna_buff, int hna_buff_len, struct batman_if *if_incoming)
+void receive_bat_packet(struct ethhdr *ethhdr,
+ struct batman_packet *batman_packet,
+ unsigned char *hna_buff, int hna_buff_len,
+ struct batman_if *if_incoming)
{
struct batman_if *batman_if;
struct orig_node *orig_neigh_node, *orig_node;
- char orig_str[ETH_STR_LEN], prev_sender_str[ETH_STR_LEN], neigh_str[ETH_STR_LEN];
char has_directlink_flag;
- char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0, is_broadcast = 0, is_bidirectional, is_single_hop_neigh, is_duplicate;
+ char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0;
+ char is_broadcast = 0, is_bidirectional, is_single_hop_neigh;
+ char is_duplicate;
unsigned short if_incoming_seqno;
- /* Silently drop when the batman packet is actually not a correct packet.
+ /* Silently drop when the batman packet is actually not a
+ * correct packet.
*
* This might happen if a packet is padded (e.g. Ethernet has a
* minimum frame length of 64 byte) and the aggregation interprets
* it as an additional length.
*
- * TODO: A more sane solution would be to have a bit in the batman_packet
- * to detect whether the packet is the last packet in an aggregation.
- * Here we expect that the padding is always zero (or not 0x01)
+ * TODO: A more sane solution would be to have a bit in the
+ * batman_packet to detect whether the packet is the last
+ * packet in an aggregation. Here we expect that the padding
+ * is always zero (or not 0x01)
*/
if (batman_packet->packet_type != BAT_PACKET)
return;
@@ -428,27 +380,31 @@ void receive_bat_packet(struct ethhdr *ethhdr, struct batman_packet *batman_pack
/* could be changed by schedule_own_packet() */
if_incoming_seqno = atomic_read(&if_incoming->seqno);
- addr_to_string(orig_str, batman_packet->orig);
- addr_to_string(prev_sender_str, batman_packet->prev_sender);
- addr_to_string(neigh_str, ethhdr->h_source);
-
has_directlink_flag = (batman_packet->flags & DIRECTLINK ? 1 : 0);
- is_single_hop_neigh = (compare_orig(ethhdr->h_source, batman_packet->orig) ? 1 : 0);
+ is_single_hop_neigh = (compare_orig(ethhdr->h_source,
+ batman_packet->orig) ? 1 : 0);
- debug_log(LOG_TYPE_BATMAN, "Received BATMAN packet via NB: %s, IF: %s [%s] (from OG: %s, via prev OG: %s, seqno %d, tq %d, TTL %d, V %d, IDF %d) \n", neigh_str, if_incoming->dev, if_incoming->addr_str, orig_str, prev_sender_str, batman_packet->seqno, batman_packet->tq, batman_packet->ttl, batman_packet->version, has_directlink_flag);
+ bat_dbg(DBG_BATMAN, "Received BATMAN packet via NB: %pM, IF: %s [%s] (from OG: %pM, via prev OG: %pM, seqno %d, tq %d, TTL %d, V %d, IDF %d) \n",
+ ethhdr->h_source, if_incoming->dev, if_incoming->addr_str,
+ batman_packet->orig, batman_packet->prev_sender,
+ batman_packet->seqno, batman_packet->tq, batman_packet->ttl,
+ batman_packet->version, has_directlink_flag);
list_for_each_entry_rcu(batman_if, &if_list, list) {
if (batman_if->if_active != IF_ACTIVE)
continue;
- if (compare_orig(ethhdr->h_source, batman_if->net_dev->dev_addr))
+ if (compare_orig(ethhdr->h_source,
+ batman_if->net_dev->dev_addr))
is_my_addr = 1;
- if (compare_orig(batman_packet->orig, batman_if->net_dev->dev_addr))
+ if (compare_orig(batman_packet->orig,
+ batman_if->net_dev->dev_addr))
is_my_orig = 1;
- if (compare_orig(batman_packet->prev_sender, batman_if->net_dev->dev_addr))
+ if (compare_orig(batman_packet->prev_sender,
+ batman_if->net_dev->dev_addr))
is_my_oldorig = 1;
if (compare_orig(ethhdr->h_source, broadcastAddr))
@@ -456,44 +412,61 @@ void receive_bat_packet(struct ethhdr *ethhdr, struct batman_packet *batman_pack
}
if (batman_packet->version != COMPAT_VERSION) {
- debug_log(LOG_TYPE_BATMAN, "Drop packet: incompatible batman version (%i) \n", batman_packet->version);
+ bat_dbg(DBG_BATMAN,
+ "Drop packet: incompatible batman version (%i)\n",
+ batman_packet->version);
return;
}
if (is_my_addr) {
- debug_log(LOG_TYPE_BATMAN, "Drop packet: received my own broadcast (sender: %s) \n", neigh_str);
+ bat_dbg(DBG_BATMAN,
+ "Drop packet: received my own broadcast (sender: %pM)\n",
+ ethhdr->h_source);
return;
}
if (is_broadcast) {
- debug_log(LOG_TYPE_BATMAN, "Drop packet: ignoring all packets with broadcast source addr (sender: %s) \n", neigh_str);
+ bat_dbg(DBG_BATMAN, "Drop packet: ignoring all packets with broadcast source addr (sender: %pM) \n", ethhdr->h_source);
return;
}
if (is_my_orig) {
+ TYPE_OF_WORD *word;
+ int offset;
+
orig_neigh_node = get_orig_node(ethhdr->h_source);
- /* neighbour has to indicate direct link and it has to come via the corresponding interface */
- /* if received seqno equals last send seqno save new seqno for bidirectional check */
- if (has_directlink_flag && compare_orig(if_incoming->net_dev->dev_addr, batman_packet->orig) &&
- (batman_packet->seqno - if_incoming_seqno + 2 == 0)) {
- bit_mark((TYPE_OF_WORD *)&(orig_neigh_node->bcast_own[if_incoming->if_num * NUM_WORDS]), 0);
- orig_neigh_node->bcast_own_sum[if_incoming->if_num] = bit_packet_count((TYPE_OF_WORD *)&(orig_neigh_node->bcast_own[if_incoming->if_num * NUM_WORDS]));
+ if (!orig_neigh_node)
+ return;
+
+ /* neighbor has to indicate direct link and it has to
+ * come via the corresponding interface */
+ /* if received seqno equals last send seqno save new
+ * seqno for bidirectional check */
+ if (has_directlink_flag &&
+ compare_orig(if_incoming->net_dev->dev_addr,
+ batman_packet->orig) &&
+ (batman_packet->seqno - if_incoming_seqno + 2 == 0)) {
+ offset = if_incoming->if_num * NUM_WORDS;
+ word = &(orig_neigh_node->bcast_own[offset]);
+ bit_mark(word, 0);
+ orig_neigh_node->bcast_own_sum[if_incoming->if_num] =
+ bit_packet_count(word);
}
- debug_log(LOG_TYPE_BATMAN, "Drop packet: originator packet from myself (via neighbour) \n");
+ bat_dbg(DBG_BATMAN, "Drop packet: originator packet from myself (via neighbor) \n");
return;
}
if (batman_packet->tq == 0) {
count_real_packets(ethhdr, batman_packet, if_incoming);
- debug_log(LOG_TYPE_BATMAN, "Drop packet: originator packet with tq equal 0 \n");
+ bat_dbg(DBG_BATMAN, "Drop packet: originator packet with tq equal 0 \n");
return;
}
if (is_my_oldorig) {
- debug_log(LOG_TYPE_BATMAN, "Drop packet: ignoring all rebroadcast echos (sender: %s) \n", neigh_str);
+ bat_dbg(DBG_BATMAN, "Drop packet: ignoring all rebroadcast echos (sender: %pM) \n", ethhdr->h_source);
return;
}
@@ -504,507 +477,502 @@ void receive_bat_packet(struct ethhdr *ethhdr, struct batman_packet *batman_pack
return;
/* avoid temporary routing loops */
- if ((orig_node->router) && (orig_node->router->orig_node->router) &&
- (compare_orig(orig_node->router->addr, batman_packet->prev_sender)) &&
+ if ((orig_node->router) &&
+ (orig_node->router->orig_node->router) &&
+ (compare_orig(orig_node->router->addr,
+ batman_packet->prev_sender)) &&
!(compare_orig(batman_packet->orig, batman_packet->prev_sender)) &&
- (compare_orig(orig_node->router->addr, orig_node->router->orig_node->router->addr))) {
- debug_log(LOG_TYPE_BATMAN, "Drop packet: ignoring all rebroadcast packets that may make me loop (sender: %s) \n", neigh_str);
+ (compare_orig(orig_node->router->addr,
+ orig_node->router->orig_node->router->addr))) {
+ bat_dbg(DBG_BATMAN, "Drop packet: ignoring all rebroadcast packets that may make me loop (sender: %pM) \n", ethhdr->h_source);
return;
}
- /* if sender is a direct neighbor the sender mac equals originator mac */
- orig_neigh_node = (is_single_hop_neigh ? orig_node : get_orig_node(ethhdr->h_source));
+ /* if sender is a direct neighbor the sender mac equals
+ * originator mac */
+ orig_neigh_node = (is_single_hop_neigh ?
+ orig_node : get_orig_node(ethhdr->h_source));
if (orig_neigh_node == NULL)
return;
- /* drop packet if sender is not a direct neighbor and if we don't route towards it */
- if (!is_single_hop_neigh && (orig_neigh_node->router == NULL)) {
- debug_log(LOG_TYPE_BATMAN, "Drop packet: OGM via unknown neighbor! \n");
+ /* drop packet if sender is not a direct neighbor and if we
+ * don't route towards it */
+ if (!is_single_hop_neigh &&
+ (orig_neigh_node->router == NULL)) {
+ bat_dbg(DBG_BATMAN, "Drop packet: OGM via unknown neighbor!\n");
return;
}
- is_bidirectional = isBidirectionalNeigh(orig_node, orig_neigh_node, batman_packet, if_incoming);
+ is_bidirectional = isBidirectionalNeigh(orig_node, orig_neigh_node,
+ batman_packet, if_incoming);
- /* update ranking if it is not a duplicate or has the same seqno and similar ttl as the non-duplicate */
- if (is_bidirectional && (!is_duplicate ||
- ((orig_node->last_real_seqno == batman_packet->seqno) &&
- (orig_node->last_ttl - 3 <= batman_packet->ttl))))
- update_orig(orig_node, ethhdr, batman_packet, if_incoming, hna_buff, hna_buff_len, is_duplicate);
+ /* update ranking if it is not a duplicate or has the same
+ * seqno and similar ttl as the non-duplicate */
+ if (is_bidirectional &&
+ (!is_duplicate ||
+ ((orig_node->last_real_seqno == batman_packet->seqno) &&
+ (orig_node->last_ttl - 3 <= batman_packet->ttl))))
+ update_orig(orig_node, ethhdr, batman_packet,
+ if_incoming, hna_buff, hna_buff_len, is_duplicate);
- /* is single hop (direct) neighbour */
+ /* is single hop (direct) neighbor */
if (is_single_hop_neigh) {
/* mark direct link on incoming interface */
- schedule_forward_packet(orig_node, ethhdr, batman_packet, 1, hna_buff_len, if_incoming);
+ schedule_forward_packet(orig_node, ethhdr, batman_packet,
+ 1, hna_buff_len, if_incoming);
- debug_log(LOG_TYPE_BATMAN, "Forwarding packet: rebroadcast neighbour packet with direct link flag \n");
+ bat_dbg(DBG_BATMAN, "Forwarding packet: rebroadcast neighbor packet with direct link flag\n");
return;
}
/* multihop originator */
if (!is_bidirectional) {
- debug_log(LOG_TYPE_BATMAN, "Drop packet: not received via bidirectional link\n");
+ bat_dbg(DBG_BATMAN,
+ "Drop packet: not received via bidirectional link\n");
return;
}
if (is_duplicate) {
- debug_log(LOG_TYPE_BATMAN, "Drop packet: duplicate packet received\n");
+ bat_dbg(DBG_BATMAN, "Drop packet: duplicate packet received\n");
return;
}
- debug_log(LOG_TYPE_BATMAN, "Forwarding packet: rebroadcast originator packet \n");
- schedule_forward_packet(orig_node, ethhdr, batman_packet, 0, hna_buff_len, if_incoming);
+ bat_dbg(DBG_BATMAN,
+ "Forwarding packet: rebroadcast originator packet\n");
+ schedule_forward_packet(orig_node, ethhdr, batman_packet,
+ 0, hna_buff_len, if_incoming);
}
-void purge_orig(struct work_struct *work)
+int recv_bat_packet(struct sk_buff *skb,
+ struct batman_if *batman_if)
{
- struct list_head *list_pos, *list_pos_tmp;
- struct hash_it_t *hashit = NULL;
- struct orig_node *orig_node;
- struct neigh_node *neigh_node, *best_neigh_node;
- char orig_str[ETH_STR_LEN], neigh_str[ETH_STR_LEN], neigh_purged;
-
- spin_lock(&orig_hash_lock);
-
- /* for all origins... */
- while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
-
- orig_node = hashit->bucket->data;
- addr_to_string(orig_str, orig_node->orig);
-
- if (time_after(jiffies, orig_node->last_valid + ((2 * PURGE_TIMEOUT * HZ) / 1000))) {
-
- debug_log(LOG_TYPE_BATMAN, "Originator timeout: originator %s, last_valid %u \n", orig_str, (orig_node->last_valid / HZ));
-
- hash_remove_bucket(orig_hash, hashit);
- free_orig_node(orig_node);
-
- } else {
-
- best_neigh_node = NULL;
- neigh_purged = 0;
-
- /* for all neighbours towards this originator ... */
- list_for_each_safe(list_pos, list_pos_tmp, &orig_node->neigh_list) {
- neigh_node = list_entry(list_pos, struct neigh_node, list);
-
- if (time_after(jiffies, neigh_node->last_valid + ((PURGE_TIMEOUT * HZ) / 1000))) {
-
- addr_to_string(neigh_str, neigh_node->addr);
- debug_log(LOG_TYPE_BATMAN, "Neighbour timeout: originator %s, neighbour: %s, last_valid %u \n", orig_str, neigh_str, (neigh_node->last_valid / HZ));
-
- neigh_purged = 1;
- list_del(list_pos);
- kfree(neigh_node);
-
- } else {
-
- if ((best_neigh_node == NULL) || (neigh_node->tq_avg > best_neigh_node->tq_avg))
- best_neigh_node = neigh_node;
-
- }
-
- }
+ struct ethhdr *ethhdr;
+ unsigned long flags;
+
+ /* drop packet if it has not necessary minimum size */
+ if (skb_headlen(skb) < sizeof(struct batman_packet))
+ return NET_RX_DROP;
+
+ ethhdr = (struct ethhdr *)skb_mac_header(skb);
+
+ /* packet with broadcast indication but unicast recipient */
+ if (!is_bcast(ethhdr->h_dest))
+ return NET_RX_DROP;
+
+ /* packet with broadcast sender address */
+ if (is_bcast(ethhdr->h_source))
+ return NET_RX_DROP;
+
+ spin_lock_irqsave(&orig_hash_lock, flags);
+ /* TODO: we use headlen instead of "length", because
+ * only this data is paged in. */
+ /* TODO: is another skb_copy needed here? there will be
+ * written on the data, but nobody (?) should further use
+ * this data */
+ receive_aggr_bat_packet(ethhdr,
+ skb->data,
+ skb_headlen(skb),
+ batman_if);
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+ kfree_skb(skb);
+ return NET_RX_SUCCESS;
+}
- if (neigh_purged)
- update_routes(orig_node, best_neigh_node, orig_node->hna_buff, orig_node->hna_buff_len);
+static int recv_my_icmp_packet(struct sk_buff *skb)
+{
+ struct orig_node *orig_node;
+ struct icmp_packet *icmp_packet;
+ struct ethhdr *ethhdr;
+ struct sk_buff *skb_old;
+ struct batman_if *batman_if;
+ int ret;
+ unsigned long flags;
+ uint8_t dstaddr[ETH_ALEN];
- }
+ icmp_packet = (struct icmp_packet *) skb->data;
+ ethhdr = (struct ethhdr *) skb_mac_header(skb);
+ /* add data to device queue */
+ if (icmp_packet->msg_type != ECHO_REQUEST) {
+ bat_device_receive_packet(icmp_packet);
+ return NET_RX_DROP;
}
- spin_unlock(&orig_hash_lock);
+ /* answer echo request (ping) */
+ /* get routing information */
+ spin_lock_irqsave(&orig_hash_lock, flags);
+ orig_node = ((struct orig_node *)hash_find(orig_hash,
+ icmp_packet->orig));
+ ret = NET_RX_DROP;
+
+ if ((orig_node != NULL) &&
+ (orig_node->batman_if != NULL) &&
+ (orig_node->router != NULL)) {
+
+ /* don't lock while sending the packets ... we therefore
+ * copy the required data before sending */
+ batman_if = orig_node->batman_if;
+ memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+ /* create a copy of the skb, if needed, to modify it. */
+ skb_old = NULL;
+ if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) {
+ skb_old = skb;
+ skb = skb_copy(skb, GFP_ATOMIC);
+ if (!skb)
+ return NET_RX_DROP;
+ icmp_packet = (struct icmp_packet *) skb->data;
+ kfree_skb(skb_old);
+ }
- start_purge_timer();
-}
+ memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
+ memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN);
+ icmp_packet->msg_type = ECHO_REPLY;
+ icmp_packet->ttl = TTL;
-static int receive_raw_packet(struct socket *raw_sock, unsigned char *packet_buff, int packet_buff_len)
-{
- struct kvec iov;
- struct msghdr msg;
+ send_skb_packet(skb, batman_if, dstaddr);
+ ret = NET_RX_SUCCESS;
- iov.iov_base = packet_buff;
- iov.iov_len = packet_buff_len;
+ } else
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
- msg.msg_flags = MSG_DONTWAIT; /* non-blocking */
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_control = NULL;
-
- return kernel_recvmsg(raw_sock, &msg, &iov, 1, packet_buff_len, MSG_DONTWAIT);
+ return ret;
}
-int packet_recv_thread(void *data)
+static int recv_icmp_ttl_exceeded(struct sk_buff *skb)
{
- struct batman_if *batman_if;
- struct ethhdr *ethhdr;
- struct batman_packet *batman_packet;
- struct unicast_packet *unicast_packet;
- struct bcast_packet *bcast_packet;
- struct icmp_packet *icmp_packet;
- struct vis_packet *vis_packet;
struct orig_node *orig_node;
- unsigned char *packet_buff, src_str[ETH_STR_LEN], dst_str[ETH_STR_LEN];
- int vis_info_len;
- int result;
-
- atomic_set(&data_ready_cond, 0);
- atomic_set(&exit_cond, 0);
- packet_buff = kmalloc(PACKBUFF_SIZE, GFP_KERNEL);
- if (!packet_buff) {
- debug_log(LOG_TYPE_CRIT, "Could allocate memory for the packet buffer. :(\n");
- return -1;
+ struct icmp_packet *icmp_packet;
+ struct ethhdr *ethhdr;
+ struct sk_buff *skb_old;
+ struct batman_if *batman_if;
+ int ret;
+ unsigned long flags;
+ uint8_t dstaddr[ETH_ALEN];
+
+ icmp_packet = (struct icmp_packet *)skb->data;
+ ethhdr = (struct ethhdr *)skb_mac_header(skb);
+
+ /* send TTL exceeded if packet is an echo request (traceroute) */
+ if (icmp_packet->msg_type != ECHO_REQUEST) {
+ printk(KERN_WARNING "batman-adv:Warning - can't forward icmp packet from %pM to %pM: ttl exceeded\n",
+ icmp_packet->orig, icmp_packet->dst);
+ return NET_RX_DROP;
}
- while ((!kthread_should_stop()) && (!atomic_read(&exit_cond))) {
-
- wait_event_interruptible(thread_wait, (atomic_read(&data_ready_cond) || atomic_read(&exit_cond)));
-
- atomic_set(&data_ready_cond, 0);
-
- if (kthread_should_stop() || atomic_read(&exit_cond))
- break;
-
- /* we only want to safely traverse the list, hard-interfaces
- * won't be deleted anyway as long as this thread runs. */
-
- rcu_read_lock();
- list_for_each_entry_rcu(batman_if, &if_list, list) {
- rcu_read_unlock();
-
- result = -1;
-
- while (1) {
- if (batman_if->if_active != IF_ACTIVE) {
- if (batman_if->if_active != IF_TO_BE_ACTIVATED)
- debug_log(LOG_TYPE_NOTICE,
- "Could not read from deactivated interface %s!\n",
- batman_if->dev);
-
- if (batman_if->raw_sock)
- receive_raw_packet(batman_if->raw_sock, packet_buff, PACKBUFF_SIZE);
- result = 0;
- break;
- }
-
- result = receive_raw_packet(batman_if->raw_sock, packet_buff, PACKBUFF_SIZE);
- if (result <= 0)
- break;
-
- if (result < sizeof(struct ethhdr) + 2)
- continue;
-
- ethhdr = (struct ethhdr *)packet_buff;
- batman_packet = (struct batman_packet *)(packet_buff + sizeof(struct ethhdr));
-
- if (batman_packet->version != COMPAT_VERSION) {
- debug_log(LOG_TYPE_BATMAN, "Drop packet: incompatible batman version (%i) \n", batman_packet->version);
- continue;
- }
-
- switch (batman_packet->packet_type) {
- /* batman originator packet */
- case BAT_PACKET:
- /* packet with broadcast indication but unicast recipient */
- if (!is_bcast(ethhdr->h_dest))
- continue;
-
- /* packet with broadcast sender address */
- if (is_bcast(ethhdr->h_source))
- continue;
-
- /* drop packet if it has not at least one batman packet as payload */
- if (result < sizeof(struct ethhdr) + sizeof(struct batman_packet))
- continue;
-
- spin_lock(&orig_hash_lock);
- receive_aggr_bat_packet(ethhdr,
- packet_buff + sizeof(struct ethhdr),
- result - sizeof(struct ethhdr),
- batman_if);
- spin_unlock(&orig_hash_lock);
-
- break;
-
- /* batman icmp packet */
- case BAT_ICMP:
- /* packet with unicast indication but broadcast recipient */
- if (is_bcast(ethhdr->h_dest))
- continue;
-
- /* packet with broadcast sender address */
- if (is_bcast(ethhdr->h_source))
- continue;
-
- /* not for me */
- if (!is_my_mac(ethhdr->h_dest))
- continue;
-
- /* drop packet if it has not necessary minimum size */
- if (result < sizeof(struct ethhdr) + sizeof(struct icmp_packet))
- continue;
-
- icmp_packet = (struct icmp_packet *)(packet_buff + sizeof(struct ethhdr));
-
- /* packet for me */
- if (is_my_mac(icmp_packet->dst)) {
-
- /* add data to device queue */
- if (icmp_packet->msg_type != ECHO_REQUEST) {
- bat_device_receive_packet(icmp_packet);
- continue;
- }
-
- /* answer echo request (ping) */
- /* get routing information */
- spin_lock(&orig_hash_lock);
- orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet->orig));
-
- if ((orig_node != NULL) && (orig_node->batman_if != NULL) && (orig_node->router != NULL)) {
-
- memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
- memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN);
- icmp_packet->msg_type = ECHO_REPLY;
- icmp_packet->ttl = TTL;
-
- send_raw_packet(packet_buff + sizeof(struct ethhdr),
- result - sizeof(struct ethhdr),
- orig_node->batman_if,
- orig_node->router->addr);
-
- }
-
- spin_unlock(&orig_hash_lock);
- continue;
-
- }
-
- /* TTL exceeded */
- if (icmp_packet->ttl < 2) {
-
- addr_to_string(src_str, icmp_packet->orig);
- addr_to_string(dst_str, icmp_packet->dst);
-
- debug_log(LOG_TYPE_NOTICE, "Error - can't send packet from %s to %s: ttl exceeded\n", src_str, dst_str);
-
- /* send TTL exceeded if packet is an echo request (traceroute) */
- if (icmp_packet->msg_type != ECHO_REQUEST)
- continue;
-
- /* get routing information */
- spin_lock(&orig_hash_lock);
- orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet->orig));
-
- if ((orig_node != NULL) && (orig_node->batman_if != NULL) && (orig_node->router != NULL)) {
-
- memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
- memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN);
- icmp_packet->msg_type = TTL_EXCEEDED;
- icmp_packet->ttl = TTL;
-
- send_raw_packet(packet_buff + sizeof(struct ethhdr),
- result - sizeof(struct ethhdr),
- orig_node->batman_if,
- orig_node->router->addr);
+ /* get routing information */
+ spin_lock_irqsave(&orig_hash_lock, flags);
+ orig_node = ((struct orig_node *)
+ hash_find(orig_hash, icmp_packet->orig));
+ ret = NET_RX_DROP;
+
+ if ((orig_node != NULL) &&
+ (orig_node->batman_if != NULL) &&
+ (orig_node->router != NULL)) {
+
+ /* don't lock while sending the packets ... we therefore
+ * copy the required data before sending */
+ batman_if = orig_node->batman_if;
+ memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+ /* create a copy of the skb, if needed, to modify it. */
+ if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) {
+ skb_old = skb;
+ skb = skb_copy(skb, GFP_ATOMIC);
+ if (!skb)
+ return NET_RX_DROP;
+ icmp_packet = (struct icmp_packet *) skb->data;
+ kfree_skb(skb_old);
+ }
- }
+ memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
+ memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN);
+ icmp_packet->msg_type = TTL_EXCEEDED;
+ icmp_packet->ttl = TTL;
- spin_unlock(&orig_hash_lock);
- continue;
+ send_skb_packet(skb, batman_if, dstaddr);
+ ret = NET_RX_SUCCESS;
- }
+ } else
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
- /* get routing information */
- spin_lock(&orig_hash_lock);
- orig_node = ((struct orig_node *)hash_find(orig_hash, icmp_packet->dst));
+ return ret;
+}
- if ((orig_node != NULL) && (orig_node->batman_if != NULL) && (orig_node->router != NULL)) {
- /* decrement ttl */
- icmp_packet->ttl--;
+int recv_icmp_packet(struct sk_buff *skb)
+{
+ struct icmp_packet *icmp_packet;
+ struct ethhdr *ethhdr;
+ struct orig_node *orig_node;
+ struct sk_buff *skb_old;
+ struct batman_if *batman_if;
+ int hdr_size = sizeof(struct icmp_packet);
+ int ret;
+ unsigned long flags;
+ uint8_t dstaddr[ETH_ALEN];
+
+ /* drop packet if it has not necessary minimum size */
+ if (skb_headlen(skb) < hdr_size)
+ return NET_RX_DROP;
+
+ ethhdr = (struct ethhdr *)skb_mac_header(skb);
+
+ /* packet with unicast indication but broadcast recipient */
+ if (is_bcast(ethhdr->h_dest))
+ return NET_RX_DROP;
+
+ /* packet with broadcast sender address */
+ if (is_bcast(ethhdr->h_source))
+ return NET_RX_DROP;
+
+ /* not for me */
+ if (!is_my_mac(ethhdr->h_dest))
+ return NET_RX_DROP;
+
+ icmp_packet = (struct icmp_packet *) skb->data;
+
+ /* packet for me */
+ if (is_my_mac(icmp_packet->dst))
+ return recv_my_icmp_packet(skb);
+
+ /* TTL exceeded */
+ if (icmp_packet->ttl < 2)
+ return recv_icmp_ttl_exceeded(skb);
+
+ ret = NET_RX_DROP;
+
+ /* get routing information */
+ spin_lock_irqsave(&orig_hash_lock, flags);
+ orig_node = ((struct orig_node *)
+ hash_find(orig_hash, icmp_packet->dst));
+
+ if ((orig_node != NULL) &&
+ (orig_node->batman_if != NULL) &&
+ (orig_node->router != NULL)) {
+
+ /* don't lock while sending the packets ... we therefore
+ * copy the required data before sending */
+ batman_if = orig_node->batman_if;
+ memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+ /* create a copy of the skb, if needed, to modify it. */
+ if (!skb_clone_writable(skb, sizeof(struct icmp_packet))) {
+ skb_old = skb;
+ skb = skb_copy(skb, GFP_ATOMIC);
+ if (!skb)
+ return NET_RX_DROP;
+ icmp_packet = (struct icmp_packet *) skb->data;
+ kfree_skb(skb_old);
+ }
- /* route it */
- send_raw_packet(packet_buff + sizeof(struct ethhdr),
- result - sizeof(struct ethhdr),
- orig_node->batman_if,
- orig_node->router->addr);
- }
+ /* decrement ttl */
+ icmp_packet->ttl--;
- spin_unlock(&orig_hash_lock);
- break;
+ /* route it */
+ send_skb_packet(skb, batman_if, dstaddr);
+ ret = NET_RX_SUCCESS;
- /* unicast packet */
- case BAT_UNICAST:
- /* packet with unicast indication but broadcast recipient */
- if (is_bcast(ethhdr->h_dest))
- continue;
+ } else
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
- /* packet with broadcast sender address */
- if (is_bcast(ethhdr->h_source))
- continue;
+ return ret;
+}
- /* not for me */
- if (!is_my_mac(ethhdr->h_dest))
- continue;
+int recv_unicast_packet(struct sk_buff *skb)
+{
+ struct unicast_packet *unicast_packet;
+ struct orig_node *orig_node;
+ struct ethhdr *ethhdr;
+ struct batman_if *batman_if;
+ struct sk_buff *skb_old;
+ uint8_t dstaddr[ETH_ALEN];
+ int hdr_size = sizeof(struct unicast_packet);
+ int ret;
+ unsigned long flags;
- /* drop packet if it has not necessary minimum size */
- if (result < sizeof(struct ethhdr) + sizeof(struct unicast_packet))
- continue;
+ /* drop packet if it has not necessary minimum size */
+ if (skb_headlen(skb) < hdr_size)
+ return NET_RX_DROP;
- unicast_packet = (struct unicast_packet *)(packet_buff + sizeof(struct ethhdr));
+ ethhdr = (struct ethhdr *) skb_mac_header(skb);
- /* packet for me */
- if (is_my_mac(unicast_packet->dest)) {
+ /* packet with unicast indication but broadcast recipient */
+ if (is_bcast(ethhdr->h_dest))
+ return NET_RX_DROP;
- interface_rx(soft_device, packet_buff + sizeof(struct ethhdr) + sizeof(struct unicast_packet), result - sizeof(struct ethhdr) - sizeof(struct unicast_packet));
- continue;
+ /* packet with broadcast sender address */
+ if (is_bcast(ethhdr->h_source))
+ return NET_RX_DROP;
- }
+ /* not for me */
+ if (!is_my_mac(ethhdr->h_dest))
+ return NET_RX_DROP;
- /* TTL exceeded */
- if (unicast_packet->ttl < 2) {
- addr_to_string(src_str, ((struct ethhdr *)(unicast_packet + 1))->h_source);
- addr_to_string(dst_str, unicast_packet->dest);
+ unicast_packet = (struct unicast_packet *) skb->data;
- debug_log(LOG_TYPE_NOTICE, "Error - can't send packet from %s to %s: ttl exceeded\n", src_str, dst_str);
- continue;
- }
+ /* packet for me */
+ if (is_my_mac(unicast_packet->dest)) {
+ interface_rx(skb, hdr_size);
+ return NET_RX_SUCCESS;
+ }
- /* get routing information */
- spin_lock(&orig_hash_lock);
- orig_node = ((struct orig_node *)hash_find(orig_hash, unicast_packet->dest));
+ /* TTL exceeded */
+ if (unicast_packet->ttl < 2) {
+ printk(KERN_WARNING "batman-adv:Warning - can't forward unicast packet from %pM to %pM: ttl exceeded\n",
+ ethhdr->h_source, unicast_packet->dest);
+ return NET_RX_DROP;
+ }
- if ((orig_node != NULL) && (orig_node->batman_if != NULL) && (orig_node->router != NULL)) {
- /* decrement ttl */
- unicast_packet->ttl--;
+ ret = NET_RX_DROP;
+ /* get routing information */
+ spin_lock_irqsave(&orig_hash_lock, flags);
+ orig_node = ((struct orig_node *)
+ hash_find(orig_hash, unicast_packet->dest));
+
+ if ((orig_node != NULL) &&
+ (orig_node->batman_if != NULL) &&
+ (orig_node->router != NULL)) {
+
+ /* don't lock while sending the packets ... we therefore
+ * copy the required data before sending */
+ batman_if = orig_node->batman_if;
+ memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+ /* create a copy of the skb, if needed, to modify it. */
+ if (!skb_clone_writable(skb, sizeof(struct unicast_packet))) {
+ skb_old = skb;
+ skb = skb_copy(skb, GFP_ATOMIC);
+ if (!skb)
+ return NET_RX_DROP;
+ unicast_packet = (struct unicast_packet *) skb->data;
+ kfree_skb(skb_old);
+ }
+ /* decrement ttl */
+ unicast_packet->ttl--;
- /* route it */
- send_raw_packet(packet_buff + sizeof(struct ethhdr),
- result - sizeof(struct ethhdr),
- orig_node->batman_if,
- orig_node->router->addr);
- }
+ /* route it */
+ send_skb_packet(skb, batman_if, dstaddr);
+ ret = NET_RX_SUCCESS;
- spin_unlock(&orig_hash_lock);
- break;
+ } else
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
- /* broadcast packet */
- case BAT_BCAST:
- /* packet with broadcast indication but unicast recipient */
- if (!is_bcast(ethhdr->h_dest))
- continue;
+ return ret;
+}
- /* packet with broadcast sender address */
- if (is_bcast(ethhdr->h_source))
- continue;
- /* drop packet if it has not necessary minimum size */
- if (result < sizeof(struct ethhdr) + sizeof(struct bcast_packet))
- continue;
+int recv_bcast_packet(struct sk_buff *skb)
+{
+ struct orig_node *orig_node;
+ struct bcast_packet *bcast_packet;
+ struct ethhdr *ethhdr;
+ int hdr_size = sizeof(struct bcast_packet);
+ unsigned long flags;
- /* ignore broadcasts sent by myself */
- if (is_my_mac(ethhdr->h_source))
- continue;
+ /* drop packet if it has not necessary minimum size */
+ if (skb_headlen(skb) < hdr_size)
+ return NET_RX_DROP;
- bcast_packet = (struct bcast_packet *)(packet_buff + sizeof(struct ethhdr));
+ ethhdr = (struct ethhdr *)skb_mac_header(skb);
- /* ignore broadcasts originated by myself */
- if (is_my_mac(bcast_packet->orig))
- continue;
+ /* packet with broadcast indication but unicast recipient */
+ if (!is_bcast(ethhdr->h_dest))
+ return NET_RX_DROP;
- spin_lock(&orig_hash_lock);
- orig_node = ((struct orig_node *)hash_find(orig_hash, bcast_packet->orig));
+ /* packet with broadcast sender address */
+ if (is_bcast(ethhdr->h_source))
+ return NET_RX_DROP;
- if (orig_node == NULL) {
- spin_unlock(&orig_hash_lock);
- continue;
- }
+ /* ignore broadcasts sent by myself */
+ if (is_my_mac(ethhdr->h_source))
+ return NET_RX_DROP;
- /* check flood history */
- if (get_bit_status(orig_node->bcast_bits, orig_node->last_bcast_seqno, ntohs(bcast_packet->seqno))) {
- spin_unlock(&orig_hash_lock);
- continue;
- }
+ bcast_packet = (struct bcast_packet *) skb->data;
- /* mark broadcast in flood history */
- if (bit_get_packet(orig_node->bcast_bits, ntohs(bcast_packet->seqno) - orig_node->last_bcast_seqno, 1))
- orig_node->last_bcast_seqno = ntohs(bcast_packet->seqno);
+ /* ignore broadcasts originated by myself */
+ if (is_my_mac(bcast_packet->orig))
+ return NET_RX_DROP;
- spin_unlock(&orig_hash_lock);
+ spin_lock_irqsave(&orig_hash_lock, flags);
+ orig_node = ((struct orig_node *)
+ hash_find(orig_hash, bcast_packet->orig));
- /* broadcast for me */
- interface_rx(soft_device, packet_buff + sizeof(struct ethhdr) + sizeof(struct bcast_packet), result - sizeof(struct ethhdr) - sizeof(struct bcast_packet));
+ if (orig_node == NULL) {
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
+ return NET_RX_DROP;
+ }
- /* rebroadcast packet */
- add_bcast_packet_to_list(packet_buff + sizeof(struct ethhdr),
- result - sizeof(struct ethhdr));
+ /* check flood history */
+ if (get_bit_status(orig_node->bcast_bits,
+ orig_node->last_bcast_seqno,
+ ntohs(bcast_packet->seqno))) {
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
+ return NET_RX_DROP;
+ }
- break;
+ /* mark broadcast in flood history */
+ if (bit_get_packet(orig_node->bcast_bits,
+ ntohs(bcast_packet->seqno) -
+ orig_node->last_bcast_seqno, 1))
+ orig_node->last_bcast_seqno = ntohs(bcast_packet->seqno);
- /* vis packet */
- case BAT_VIS:
- /* drop if too short. */
- if (result < sizeof(struct ethhdr) + sizeof(struct vis_packet))
- continue;
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
- /* not for me */
- if (!is_my_mac(ethhdr->h_dest))
- continue;
+ /* rebroadcast packet */
+ add_bcast_packet_to_list(skb);
- vis_packet = (struct vis_packet *)(packet_buff + sizeof(struct ethhdr));
- vis_info_len = result - sizeof(struct ethhdr) - sizeof(struct vis_packet);
+ /* broadcast for me */
+ interface_rx(skb, hdr_size);
- /* ignore own packets */
- if (is_my_mac(vis_packet->vis_orig))
- continue;
+ return NET_RX_SUCCESS;
+}
- if (is_my_mac(vis_packet->sender_orig))
- continue;
+int recv_vis_packet(struct sk_buff *skb)
+{
+ struct vis_packet *vis_packet;
+ struct ethhdr *ethhdr;
+ int hdr_size = sizeof(struct vis_packet);
- switch (vis_packet->vis_type) {
- case VIS_TYPE_SERVER_SYNC:
- receive_server_sync_packet(vis_packet, vis_info_len);
- break;
+ if (skb_headlen(skb) < hdr_size)
+ return NET_RX_DROP;
- case VIS_TYPE_CLIENT_UPDATE:
- receive_client_update_packet(vis_packet, vis_info_len);
- break;
+ vis_packet = (struct vis_packet *) skb->data;
+ ethhdr = (struct ethhdr *)skb_mac_header(skb);
- default: /* ignore unknown packet */
- break;
- }
+ /* not for me */
+ if (!is_my_mac(ethhdr->h_dest))
+ return NET_RX_DROP;
- break;
- }
+ /* ignore own packets */
+ if (is_my_mac(vis_packet->vis_orig))
+ return NET_RX_DROP;
- }
+ if (is_my_mac(vis_packet->sender_orig))
+ return NET_RX_DROP;
- if ((result < 0) && (result != -EAGAIN))
- debug_log(LOG_TYPE_CRIT, "Could not receive packet from interface %s: %i\n", batman_if->dev, result);
+ switch (vis_packet->vis_type) {
+ case VIS_TYPE_SERVER_SYNC:
+ /* TODO: handle fragmented skbs properly */
+ receive_server_sync_packet(vis_packet, skb_headlen(skb));
+ break;
- /* lock for the next iteration */
- rcu_read_lock();
- }
- rcu_read_unlock();
+ case VIS_TYPE_CLIENT_UPDATE:
+ /* TODO: handle fragmented skbs properly */
+ receive_client_update_packet(vis_packet, skb_headlen(skb));
+ break;
+ default: /* ignore unknown packet */
+ break;
}
- kfree(packet_buff);
-
- /* do not exit until kthread_stop() is actually called, otherwise it will wait for us
- * forever. */
- while (!kthread_should_stop())
- schedule();
-
- return 0;
-}
-
-void batman_data_ready(struct sock *sk, int len)
-{
- void (*data_ready)(struct sock *, int) = sk->sk_user_data;
-
- data_ready(sk, len);
- atomic_set(&data_ready_cond, 1);
- wake_up_interruptible(&thread_wait);
+ /* We take a copy of the data in the packet, so we should
+ always free the skbuf. */
+ return NET_RX_DROP;
}
-
diff --git a/drivers/staging/batman-adv/routing.h b/drivers/staging/batman-adv/routing.h
index 0123ea86deb..939b8d4f733 100644
--- a/drivers/staging/batman-adv/routing.h
+++ b/drivers/staging/batman-adv/routing.h
@@ -22,13 +22,18 @@
#include "types.h"
extern wait_queue_head_t thread_wait;
-extern atomic_t exit_cond;
-int originator_init(void);
-void free_orig_node(void *data);
-void originator_free(void);
void slide_own_bcast_window(struct batman_if *batman_if);
-void batman_data_ready(struct sock *sk, int len);
-void purge_orig(struct work_struct *work);
-int packet_recv_thread(void *data);
-void receive_bat_packet(struct ethhdr *ethhdr, struct batman_packet *batman_packet, unsigned char *hna_buff, int hna_buff_len, struct batman_if *if_incoming);
+void receive_bat_packet(struct ethhdr *ethhdr,
+ struct batman_packet *batman_packet,
+ unsigned char *hna_buff, int hna_buff_len,
+ struct batman_if *if_incoming);
+void update_routes(struct orig_node *orig_node,
+ struct neigh_node *neigh_node,
+ unsigned char *hna_buff, int hna_buff_len);
+int recv_icmp_packet(struct sk_buff *skb);
+int recv_unicast_packet(struct sk_buff *skb);
+int recv_bcast_packet(struct sk_buff *skb);
+int recv_vis_packet(struct sk_buff *skb);
+int recv_bat_packet(struct sk_buff *skb,
+ struct batman_if *batman_if);
diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c
index eb617508cca..2a9fac8c240 100644
--- a/drivers/staging/batman-adv/send.c
+++ b/drivers/staging/batman-adv/send.c
@@ -21,16 +21,14 @@
#include "main.h"
#include "send.h"
-#include "log.h"
#include "routing.h"
#include "translation-table.h"
+#include "soft-interface.h"
#include "hard-interface.h"
#include "types.h"
#include "vis.h"
#include "aggregation.h"
-#include "compat.h"
-
/* apply hop penalty for a normal link */
static uint8_t hop_penalty(const uint8_t tq)
{
@@ -59,51 +57,69 @@ static unsigned long forward_send_time(void)
return send_time;
}
-/* sends a raw packet. */
-void send_raw_packet(unsigned char *pack_buff, int pack_buff_len,
- struct batman_if *batman_if, uint8_t *dst_addr)
+/* send out an already prepared packet to the given address via the
+ * specified batman interface */
+int send_skb_packet(struct sk_buff *skb,
+ struct batman_if *batman_if,
+ uint8_t *dst_addr)
{
struct ethhdr *ethhdr;
- struct sk_buff *skb;
- int retval;
- char *data;
if (batman_if->if_active != IF_ACTIVE)
- return;
+ goto send_skb_err;
+
+ if (unlikely(!batman_if->net_dev))
+ goto send_skb_err;
if (!(batman_if->net_dev->flags & IFF_UP)) {
- debug_log(LOG_TYPE_WARN,
- "Interface %s is not up - can't send packet via that interface (IF_TO_BE_DEACTIVATED was here) !\n",
- batman_if->dev);
- return;
+ printk(KERN_WARNING
+ "batman-adv:Interface %s is not up - can't send packet via that interface!\n",
+ batman_if->dev);
+ goto send_skb_err;
}
- skb = dev_alloc_skb(pack_buff_len + sizeof(struct ethhdr));
- if (!skb)
- return;
- data = skb_put(skb, pack_buff_len + sizeof(struct ethhdr));
+ /* push to the ethernet header. */
+ if (my_skb_push(skb, sizeof(struct ethhdr)) < 0)
+ goto send_skb_err;
- memcpy(data + sizeof(struct ethhdr), pack_buff, pack_buff_len);
+ skb_reset_mac_header(skb);
- ethhdr = (struct ethhdr *) data;
+ ethhdr = (struct ethhdr *) skb_mac_header(skb);
memcpy(ethhdr->h_source, batman_if->net_dev->dev_addr, ETH_ALEN);
memcpy(ethhdr->h_dest, dst_addr, ETH_ALEN);
ethhdr->h_proto = __constant_htons(ETH_P_BATMAN);
- skb_reset_mac_header(skb);
skb_set_network_header(skb, ETH_HLEN);
skb->priority = TC_PRIO_CONTROL;
skb->protocol = __constant_htons(ETH_P_BATMAN);
+
skb->dev = batman_if->net_dev;
/* dev_queue_xmit() returns a negative result on error. However on
* congestion and traffic shaping, it drops and returns NET_XMIT_DROP
* (which is > 0). This will not be treated as an error. */
- retval = dev_queue_xmit(skb);
- if (retval < 0)
- debug_log(LOG_TYPE_CRIT,
- "Can't write to raw socket (IF_TO_BE_DEACTIVATED was here): %i\n",
- retval);
+
+ return dev_queue_xmit(skb);
+send_skb_err:
+ kfree_skb(skb);
+ return NET_XMIT_DROP;
+}
+
+/* sends a raw packet. */
+void send_raw_packet(unsigned char *pack_buff, int pack_buff_len,
+ struct batman_if *batman_if, uint8_t *dst_addr)
+{
+ struct sk_buff *skb;
+ char *data;
+
+ skb = dev_alloc_skb(pack_buff_len + sizeof(struct ethhdr));
+ if (!skb)
+ return;
+ data = skb_put(skb, pack_buff_len + sizeof(struct ethhdr));
+ memcpy(data + sizeof(struct ethhdr), pack_buff, pack_buff_len);
+ /* pull back to the batman "network header" */
+ skb_pull(skb, sizeof(struct ethhdr));
+ send_skb_packet(skb, batman_if, dst_addr);
}
/* Send a packet to a given interface */
@@ -114,7 +130,6 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
uint8_t packet_num;
int16_t buff_pos;
struct batman_packet *batman_packet;
- char orig_str[ETH_STR_LEN];
if (batman_if->if_active != IF_ACTIVE)
return;
@@ -136,19 +151,18 @@ static void send_packet_to_if(struct forw_packet *forw_packet,
else
batman_packet->flags &= ~DIRECTLINK;
- addr_to_string(orig_str, batman_packet->orig);
fwd_str = (packet_num > 0 ? "Forwarding" : (forw_packet->own ?
"Sending own" :
"Forwarding"));
- debug_log(LOG_TYPE_BATMAN,
- "%s %spacket (originator %s, seqno %d, TQ %d, TTL %d, IDF %s) on interface %s [%s]\n",
- fwd_str,
- (packet_num > 0 ? "aggregated " : ""),
- orig_str, ntohs(batman_packet->seqno),
- batman_packet->tq, batman_packet->ttl,
- (batman_packet->flags & DIRECTLINK ?
- "on" : "off"),
- batman_if->dev, batman_if->addr_str);
+ bat_dbg(DBG_BATMAN,
+ "%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d, IDF %s) on interface %s [%s]\n",
+ fwd_str,
+ (packet_num > 0 ? "aggregated " : ""),
+ batman_packet->orig, ntohs(batman_packet->seqno),
+ batman_packet->tq, batman_packet->ttl,
+ (batman_packet->flags & DIRECTLINK ?
+ "on" : "off"),
+ batman_if->dev, batman_if->addr_str);
buff_pos += sizeof(struct batman_packet) +
(batman_packet->num_hna * ETH_ALEN);
@@ -168,32 +182,28 @@ static void send_packet(struct forw_packet *forw_packet)
struct batman_if *batman_if;
struct batman_packet *batman_packet =
(struct batman_packet *)(forw_packet->packet_buff);
- char orig_str[ETH_STR_LEN];
unsigned char directlink = (batman_packet->flags & DIRECTLINK ? 1 : 0);
if (!forw_packet->if_incoming) {
- debug_log(LOG_TYPE_CRIT,
- "Error - can't forward packet: incoming iface not specified\n");
+ printk(KERN_ERR "batman-adv: Error - can't forward packet: incoming iface not specified\n");
return;
}
if (forw_packet->if_incoming->if_active != IF_ACTIVE)
return;
- addr_to_string(orig_str, batman_packet->orig);
-
/* multihomed peer assumed */
/* non-primary OGMs are only broadcasted on their interface */
if ((directlink && (batman_packet->ttl == 1)) ||
(forw_packet->own && (forw_packet->if_incoming->if_num > 0))) {
/* FIXME: what about aggregated packets ? */
- debug_log(LOG_TYPE_BATMAN,
- "%s packet (originator %s, seqno %d, TTL %d) on interface %s [%s]\n",
- (forw_packet->own ? "Sending own" : "Forwarding"),
- orig_str, ntohs(batman_packet->seqno),
- batman_packet->ttl, forw_packet->if_incoming->dev,
- forw_packet->if_incoming->addr_str);
+ bat_dbg(DBG_BATMAN,
+ "%s packet (originator %pM, seqno %d, TTL %d) on interface %s [%s]\n",
+ (forw_packet->own ? "Sending own" : "Forwarding"),
+ batman_packet->orig, ntohs(batman_packet->seqno),
+ batman_packet->ttl, forw_packet->if_incoming->dev,
+ forw_packet->if_incoming->addr_str);
send_raw_packet(forw_packet->packet_buff,
forw_packet->packet_len,
@@ -238,6 +248,7 @@ void schedule_own_packet(struct batman_if *batman_if)
{
unsigned long send_time;
struct batman_packet *batman_packet;
+ int vis_server = atomic_read(&vis_mode);
/**
* the interface gets activated here to avoid race conditions between
@@ -262,7 +273,7 @@ void schedule_own_packet(struct batman_if *batman_if)
/* change sequence number to network order */
batman_packet->seqno = htons((uint16_t)atomic_read(&batman_if->seqno));
- if (is_vis_server())
+ if (vis_server == VIS_TYPE_SERVER_SYNC)
batman_packet->flags = VIS_SERVER;
else
batman_packet->flags = 0;
@@ -286,7 +297,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
unsigned long send_time;
if (batman_packet->ttl <= 1) {
- debug_log(LOG_TYPE_BATMAN, "ttl exceeded \n");
+ bat_dbg(DBG_BATMAN, "ttl exceeded \n");
return;
}
@@ -314,9 +325,9 @@ void schedule_forward_packet(struct orig_node *orig_node,
/* apply hop penalty */
batman_packet->tq = hop_penalty(batman_packet->tq);
- debug_log(LOG_TYPE_BATMAN, "Forwarding packet: tq_orig: %i, tq_avg: %i, tq_forw: %i, ttl_orig: %i, ttl_forw: %i \n",
- in_tq, tq_avg, batman_packet->tq, in_ttl - 1,
- batman_packet->ttl);
+ bat_dbg(DBG_BATMAN, "Forwarding packet: tq_orig: %i, tq_avg: %i, tq_forw: %i, ttl_orig: %i, ttl_forw: %i \n",
+ in_tq, tq_avg, batman_packet->tq, in_ttl - 1,
+ batman_packet->ttl);
batman_packet->seqno = htons(batman_packet->seqno);
@@ -333,6 +344,8 @@ void schedule_forward_packet(struct orig_node *orig_node,
static void forw_packet_free(struct forw_packet *forw_packet)
{
+ if (forw_packet->skb)
+ kfree_skb(forw_packet->skb);
kfree(forw_packet->packet_buff);
kfree(forw_packet);
}
@@ -340,12 +353,13 @@ static void forw_packet_free(struct forw_packet *forw_packet)
static void _add_bcast_packet_to_list(struct forw_packet *forw_packet,
unsigned long send_time)
{
+ unsigned long flags;
INIT_HLIST_NODE(&forw_packet->list);
/* add new packet to packet list */
- spin_lock(&forw_bcast_list_lock);
+ spin_lock_irqsave(&forw_bcast_list_lock, flags);
hlist_add_head(&forw_packet->list, &forw_bcast_list);
- spin_unlock(&forw_bcast_list_lock);
+ spin_unlock_irqrestore(&forw_bcast_list_lock, flags);
/* start timer for this packet */
INIT_DELAYED_WORK(&forw_packet->delayed_work,
@@ -354,7 +368,7 @@ static void _add_bcast_packet_to_list(struct forw_packet *forw_packet,
send_time);
}
-void add_bcast_packet_to_list(unsigned char *packet_buff, int packet_len)
+void add_bcast_packet_to_list(struct sk_buff *skb)
{
struct forw_packet *forw_packet;
@@ -362,14 +376,16 @@ void add_bcast_packet_to_list(unsigned char *packet_buff, int packet_len)
if (!forw_packet)
return;
- forw_packet->packet_buff = kmalloc(packet_len, GFP_ATOMIC);
- if (!forw_packet->packet_buff) {
+ skb = skb_copy(skb, GFP_ATOMIC);
+ if (!skb) {
kfree(forw_packet);
return;
}
- forw_packet->packet_len = packet_len;
- memcpy(forw_packet->packet_buff, packet_buff, forw_packet->packet_len);
+ skb_reset_mac_header(skb);
+
+ forw_packet->skb = skb;
+ forw_packet->packet_buff = NULL;
/* how often did we send the bcast packet ? */
forw_packet->num_packets = 0;
@@ -384,16 +400,20 @@ void send_outstanding_bcast_packet(struct work_struct *work)
container_of(work, struct delayed_work, work);
struct forw_packet *forw_packet =
container_of(delayed_work, struct forw_packet, delayed_work);
+ unsigned long flags;
+ struct sk_buff *skb1;
- spin_lock(&forw_bcast_list_lock);
+ spin_lock_irqsave(&forw_bcast_list_lock, flags);
hlist_del(&forw_packet->list);
- spin_unlock(&forw_bcast_list_lock);
+ spin_unlock_irqrestore(&forw_bcast_list_lock, flags);
/* rebroadcast packet */
rcu_read_lock();
list_for_each_entry_rcu(batman_if, &if_list, list) {
- send_raw_packet(forw_packet->packet_buff,
- forw_packet->packet_len,
+ /* send a copy of the saved skb */
+ skb1 = skb_copy(forw_packet->skb, GFP_ATOMIC);
+ if (skb1)
+ send_skb_packet(skb1,
batman_if, broadcastAddr);
}
rcu_read_unlock();
@@ -415,10 +435,11 @@ void send_outstanding_bat_packet(struct work_struct *work)
container_of(work, struct delayed_work, work);
struct forw_packet *forw_packet =
container_of(delayed_work, struct forw_packet, delayed_work);
+ unsigned long flags;
- spin_lock(&forw_bat_list_lock);
+ spin_lock_irqsave(&forw_bat_list_lock, flags);
hlist_del(&forw_packet->list);
- spin_unlock(&forw_bat_list_lock);
+ spin_unlock_irqrestore(&forw_bat_list_lock, flags);
send_packet(forw_packet);
@@ -438,38 +459,39 @@ void purge_outstanding_packets(void)
{
struct forw_packet *forw_packet;
struct hlist_node *tmp_node, *safe_tmp_node;
+ unsigned long flags;
- debug_log(LOG_TYPE_BATMAN, "purge_outstanding_packets()\n");
+ bat_dbg(DBG_BATMAN, "purge_outstanding_packets()\n");
/* free bcast list */
- spin_lock(&forw_bcast_list_lock);
+ spin_lock_irqsave(&forw_bcast_list_lock, flags);
hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
&forw_bcast_list, list) {
- spin_unlock(&forw_bcast_list_lock);
+ spin_unlock_irqrestore(&forw_bcast_list_lock, flags);
/**
* send_outstanding_bcast_packet() will lock the list to
* delete the item from the list
*/
cancel_delayed_work_sync(&forw_packet->delayed_work);
- spin_lock(&forw_bcast_list_lock);
+ spin_lock_irqsave(&forw_bcast_list_lock, flags);
}
- spin_unlock(&forw_bcast_list_lock);
+ spin_unlock_irqrestore(&forw_bcast_list_lock, flags);
/* free batman packet list */
- spin_lock(&forw_bat_list_lock);
+ spin_lock_irqsave(&forw_bat_list_lock, flags);
hlist_for_each_entry_safe(forw_packet, tmp_node, safe_tmp_node,
&forw_bat_list, list) {
- spin_unlock(&forw_bat_list_lock);
+ spin_unlock_irqrestore(&forw_bat_list_lock, flags);
/**
* send_outstanding_bat_packet() will lock the list to
* delete the item from the list
*/
cancel_delayed_work_sync(&forw_packet->delayed_work);
- spin_lock(&forw_bat_list_lock);
+ spin_lock_irqsave(&forw_bat_list_lock, flags);
}
- spin_unlock(&forw_bat_list_lock);
+ spin_unlock_irqrestore(&forw_bat_list_lock, flags);
}
diff --git a/drivers/staging/batman-adv/send.h b/drivers/staging/batman-adv/send.h
index 59d500917a3..5fc6f3417cb 100644
--- a/drivers/staging/batman-adv/send.h
+++ b/drivers/staging/batman-adv/send.h
@@ -22,6 +22,9 @@
#include "types.h"
void send_own_packet_work(struct work_struct *work);
+int send_skb_packet(struct sk_buff *skb,
+ struct batman_if *batman_if,
+ uint8_t *dst_addr);
void send_raw_packet(unsigned char *pack_buff, int pack_buff_len,
struct batman_if *batman_if, uint8_t *dst_addr);
void schedule_own_packet(struct batman_if *batman_if);
@@ -30,7 +33,7 @@ void schedule_forward_packet(struct orig_node *orig_node,
struct batman_packet *batman_packet,
uint8_t directlink, int hna_buff_len,
struct batman_if *if_outgoing);
-void add_bcast_packet_to_list(unsigned char *packet_buff, int packet_len);
+void add_bcast_packet_to_list(struct sk_buff *skb);
void send_outstanding_bcast_packet(struct work_struct *work);
void send_outstanding_bat_packet(struct work_struct *work);
void purge_outstanding_packets(void);
diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c
index d543f50b647..c9b35d9f799 100644
--- a/drivers/staging/batman-adv/soft-interface.c
+++ b/drivers/staging/batman-adv/soft-interface.c
@@ -24,18 +24,15 @@
#include "hard-interface.h"
#include "send.h"
#include "translation-table.h"
-#include "log.h"
#include "types.h"
#include "hash.h"
#include <linux/ethtool.h>
#include <linux/etherdevice.h>
-#include "compat.h"
static uint16_t bcast_seqno = 1; /* give own bcast messages seq numbers to avoid
* broadcast storms */
static int32_t skb_packets;
static int32_t skb_bad_packets;
-static int32_t lock_dropped;
unsigned char mainIfAddr[ETH_ALEN];
static unsigned char mainIfAddr_default[ETH_ALEN];
@@ -68,12 +65,12 @@ int main_if_was_up(void)
return (memcmp(mainIfAddr, mainIfAddr_default, ETH_ALEN) != 0 ? 1 : 0);
}
-static int my_skb_push(struct sk_buff *skb, unsigned int len)
+int my_skb_push(struct sk_buff *skb, unsigned int len)
{
int result = 0;
skb_packets++;
- if (skb->data - len < skb->head) {
+ if (skb_headroom(skb) < len) {
skb_bad_packets++;
result = pskb_expand_head(skb, len, 0, GFP_ATOMIC);
@@ -122,7 +119,7 @@ void interface_setup(struct net_device *dev)
/* generate random address */
random_ether_addr(dev_addr);
- memcpy(dev->dev_addr, dev_addr, sizeof(dev->dev_addr));
+ memcpy(dev->dev_addr, dev_addr, ETH_ALEN);
SET_ETHTOOL_OPS(dev, &bat_ethtool_ops);
@@ -147,9 +144,18 @@ struct net_device_stats *interface_stats(struct net_device *dev)
return &priv->stats;
}
-int interface_set_mac_addr(struct net_device *dev, void *addr)
+int interface_set_mac_addr(struct net_device *dev, void *p)
{
- return -EBUSY;
+ struct sockaddr *addr = p;
+
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EADDRNOTAVAIL;
+
+ hna_local_remove(dev->dev_addr, "mac address changed");
+ memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
+ hna_local_add(dev->dev_addr);
+
+ return 0;
}
int interface_change_mtu(struct net_device *dev, int new_mtu)
@@ -170,7 +176,10 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
struct orig_node *orig_node;
struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
struct bat_priv *priv = netdev_priv(dev);
+ struct batman_if *batman_if;
+ uint8_t dstaddr[6];
int data_len = skb->len;
+ unsigned long flags;
if (atomic_read(&module_state) != MODULE_ACTIVE)
goto dropped;
@@ -186,7 +195,6 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
goto dropped;
bcast_packet = (struct bcast_packet *)skb->data;
-
bcast_packet->version = COMPAT_VERSION;
/* batman packet type: broadcast */
@@ -195,27 +203,21 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
/* hw address of first interface is the orig mac because only
* this mac is known throughout the mesh */
memcpy(bcast_packet->orig, mainIfAddr, ETH_ALEN);
+
/* set broadcast sequence number */
bcast_packet->seqno = htons(bcast_seqno);
bcast_seqno++;
/* broadcast packet */
- add_bcast_packet_to_list(skb->data, skb->len);
+ add_bcast_packet_to_list(skb);
+ /* a copy is stored in the bcast list, therefore removing
+ * the original skb. */
+ kfree_skb(skb);
/* unicast packet */
} else {
-
- /* simply spin_lock()ing can deadlock when the lock is already
- * hold. */
- /* TODO: defer the work in a working queue instead of
- * dropping */
- if (!spin_trylock(&orig_hash_lock)) {
- lock_dropped++;
- debug_log(LOG_TYPE_NOTICE, "%d packets dropped because lock was hold\n", lock_dropped);
- goto dropped;
- }
-
+ spin_lock_irqsave(&orig_hash_lock, flags);
/* get routing information */
orig_node = ((struct orig_node *)hash_find(orig_hash,
ethhdr->h_dest));
@@ -244,14 +246,17 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
if (orig_node->batman_if->if_active != IF_ACTIVE)
goto unlock;
- send_raw_packet(skb->data, skb->len,
- orig_node->batman_if,
- orig_node->router->addr);
+ /* don't lock while sending the packets ... we therefore
+ * copy the required data before sending */
+
+ batman_if = orig_node->batman_if;
+ memcpy(dstaddr, orig_node->router->addr, ETH_ALEN);
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
+
+ send_skb_packet(skb, batman_if, dstaddr);
} else {
goto unlock;
}
-
- spin_unlock(&orig_hash_lock);
}
priv->stats.tx_packets++;
@@ -259,42 +264,44 @@ int interface_tx(struct sk_buff *skb, struct net_device *dev)
goto end;
unlock:
- spin_unlock(&orig_hash_lock);
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
dropped:
priv->stats.tx_dropped++;
end:
- kfree_skb(skb);
- return 0;
+ return NETDEV_TX_OK;
}
-void interface_rx(struct net_device *dev, void *packet, int packet_len)
+void interface_rx(struct sk_buff *skb, int hdr_size)
{
- struct sk_buff *skb;
+ struct net_device *dev = soft_device;
struct bat_priv *priv = netdev_priv(dev);
- skb = dev_alloc_skb(packet_len);
-
- if (!skb) {
- priv->stats.rx_dropped++;
- goto out;
+ /* check if enough space is available for pulling, and pull */
+ if (!pskb_may_pull(skb, hdr_size)) {
+ kfree_skb(skb);
+ return;
}
+ skb_pull_rcsum(skb, hdr_size);
+/* skb_set_mac_header(skb, -sizeof(struct ethhdr));*/
- memcpy(skb_put(skb, packet_len), packet, packet_len);
-
- /* Write metadata, and then pass to the receive level */
skb->dev = dev;
skb->protocol = eth_type_trans(skb, dev);
- skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+ /* should not be neccesary anymore as we use skb_pull_rcsum()
+ * TODO: please verify this and remove this TODO
+ * -- Dec 21st 2009, Simon Wunderlich */
+
+/* skb->ip_summed = CHECKSUM_UNNECESSARY;*/
+
+ /* TODO: set skb->pkt_type to PACKET_BROADCAST, PACKET_MULTICAST,
+ * PACKET_OTHERHOST or PACKET_HOST */
priv->stats.rx_packets++;
- priv->stats.rx_bytes += packet_len;
+ priv->stats.rx_bytes += skb->len;
dev->last_rx = jiffies;
netif_rx(skb);
-
-out:
- return;
}
/* ethtool */
@@ -330,7 +337,6 @@ static u32 bat_get_msglevel(struct net_device *dev)
static void bat_set_msglevel(struct net_device *dev, u32 value)
{
- return;
}
static u32 bat_get_link(struct net_device *dev)
diff --git a/drivers/staging/batman-adv/soft-interface.h b/drivers/staging/batman-adv/soft-interface.h
index 515e276ef53..c0cad8134b2 100644
--- a/drivers/staging/batman-adv/soft-interface.h
+++ b/drivers/staging/batman-adv/soft-interface.h
@@ -28,6 +28,7 @@ struct net_device_stats *interface_stats(struct net_device *dev);
int interface_set_mac_addr(struct net_device *dev, void *addr);
int interface_change_mtu(struct net_device *dev, int new_mtu);
int interface_tx(struct sk_buff *skb, struct net_device *dev);
-void interface_rx(struct net_device *dev, void *packet, int packet_len);
+void interface_rx(struct sk_buff *skb, int hdr_size);
+int my_skb_push(struct sk_buff *skb, unsigned int len);
extern unsigned char mainIfAddr[];
diff --git a/drivers/staging/batman-adv/translation-table.c b/drivers/staging/batman-adv/translation-table.c
index c2190e177c5..d56f6654de0 100644
--- a/drivers/staging/batman-adv/translation-table.c
+++ b/drivers/staging/batman-adv/translation-table.c
@@ -21,11 +21,9 @@
#include "main.h"
#include "translation-table.h"
-#include "log.h"
#include "soft-interface.h"
#include "types.h"
#include "hash.h"
-#include "compat.h"
struct hashtable_t *hna_local_hash;
static struct hashtable_t *hna_global_hash;
@@ -62,7 +60,6 @@ void hna_local_add(uint8_t *addr)
struct hna_local_entry *hna_local_entry;
struct hna_global_entry *hna_global_entry;
struct hashtable_t *swaphash;
- char hna_str[ETH_STR_LEN];
unsigned long flags;
spin_lock_irqsave(&hna_local_hash_lock, flags);
@@ -75,19 +72,17 @@ void hna_local_add(uint8_t *addr)
return;
}
- addr_to_string(hna_str, addr);
-
/* only announce as many hosts as possible in the batman-packet and
space in batman_packet->num_hna That also should give a limit to
MAC-flooding. */
if ((num_hna + 1 > (ETH_DATA_LEN - BAT_PACKET_LEN) / ETH_ALEN) ||
(num_hna + 1 > 255)) {
- debug_log(LOG_TYPE_ROUTES, "Can't add new local hna entry (%s): number of local hna entries exceeds packet size \n", hna_str);
+ bat_dbg(DBG_ROUTES, "Can't add new local hna entry (%pM): number of local hna entries exceeds packet size \n", addr);
return;
}
- debug_log(LOG_TYPE_ROUTES, "Creating new local hna entry: %s \n",
- hna_str);
+ bat_dbg(DBG_ROUTES, "Creating new local hna entry: %pM \n",
+ addr);
hna_local_entry = kmalloc(sizeof(struct hna_local_entry), GFP_ATOMIC);
if (!hna_local_entry)
@@ -113,7 +108,7 @@ void hna_local_add(uint8_t *addr)
hna_local_hash->size * 2);
if (swaphash == NULL)
- debug_log(LOG_TYPE_CRIT, "Couldn't resize local hna hash table \n");
+ printk(KERN_ERR "batman-adv:Couldn't resize local hna hash table \n");
else
hna_local_hash = swaphash;
}
@@ -135,18 +130,18 @@ void hna_local_add(uint8_t *addr)
int hna_local_fill_buffer(unsigned char *buff, int buff_len)
{
struct hna_local_entry *hna_local_entry;
- struct hash_it_t *hashit = NULL;
+ HASHIT(hashit);
int i = 0;
unsigned long flags;
spin_lock_irqsave(&hna_local_hash_lock, flags);
- while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) {
+ while (hash_iterate(hna_local_hash, &hashit)) {
if (buff_len < (i + 1) * ETH_ALEN)
break;
- hna_local_entry = hashit->bucket->data;
+ hna_local_entry = hashit.bucket->data;
memcpy(buff + (i * ETH_ALEN), hna_local_entry->addr, ETH_ALEN);
i++;
@@ -164,18 +159,18 @@ int hna_local_fill_buffer(unsigned char *buff, int buff_len)
int hna_local_fill_buffer_text(unsigned char *buff, int buff_len)
{
struct hna_local_entry *hna_local_entry;
- struct hash_it_t *hashit = NULL;
+ HASHIT(hashit);
int bytes_written = 0;
unsigned long flags;
spin_lock_irqsave(&hna_local_hash_lock, flags);
- while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) {
+ while (hash_iterate(hna_local_hash, &hashit)) {
if (buff_len < bytes_written + ETH_STR_LEN + 4)
break;
- hna_local_entry = hashit->bucket->data;
+ hna_local_entry = hashit.bucket->data;
bytes_written += snprintf(buff + bytes_written, ETH_STR_LEN + 4,
" * %02x:%02x:%02x:%02x:%02x:%02x\n",
@@ -202,27 +197,39 @@ static void _hna_local_del(void *data)
static void hna_local_del(struct hna_local_entry *hna_local_entry,
char *message)
{
- char hna_str[ETH_STR_LEN];
-
- addr_to_string(hna_str, hna_local_entry->addr);
- debug_log(LOG_TYPE_ROUTES, "Deleting local hna entry (%s): %s \n",
- hna_str, message);
+ bat_dbg(DBG_ROUTES, "Deleting local hna entry (%pM): %s \n",
+ hna_local_entry->addr, message);
hash_remove(hna_local_hash, hna_local_entry->addr);
_hna_local_del(hna_local_entry);
}
+void hna_local_remove(uint8_t *addr, char *message)
+{
+ struct hna_local_entry *hna_local_entry;
+ unsigned long flags;
+
+ spin_lock_irqsave(&hna_local_hash_lock, flags);
+
+ hna_local_entry = (struct hna_local_entry *)
+ hash_find(hna_local_hash, addr);
+ if (hna_local_entry)
+ hna_local_del(hna_local_entry, message);
+
+ spin_unlock_irqrestore(&hna_local_hash_lock, flags);
+}
+
void hna_local_purge(struct work_struct *work)
{
struct hna_local_entry *hna_local_entry;
- struct hash_it_t *hashit = NULL;
+ HASHIT(hashit);
unsigned long flags;
unsigned long timeout;
spin_lock_irqsave(&hna_local_hash_lock, flags);
- while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) {
- hna_local_entry = hashit->bucket->data;
+ while (hash_iterate(hna_local_hash, &hashit)) {
+ hna_local_entry = hashit.bucket->data;
timeout = hna_local_entry->last_seen +
((LOCAL_HNA_TIMEOUT / 1000) * HZ);
@@ -264,13 +271,10 @@ void hna_global_add_orig(struct orig_node *orig_node,
struct hna_global_entry *hna_global_entry;
struct hna_local_entry *hna_local_entry;
struct hashtable_t *swaphash;
- char hna_str[ETH_STR_LEN], orig_str[ETH_STR_LEN];
int hna_buff_count = 0;
unsigned long flags;
unsigned char *hna_ptr;
- addr_to_string(orig_str, orig_node->orig);
-
while ((hna_buff_count + 1) * ETH_ALEN <= hna_buff_len) {
spin_lock_irqsave(&hna_global_hash_lock, flags);
@@ -290,8 +294,9 @@ void hna_global_add_orig(struct orig_node *orig_node,
memcpy(hna_global_entry->addr, hna_ptr, ETH_ALEN);
- addr_to_string(hna_str, hna_global_entry->addr);
- debug_log(LOG_TYPE_ROUTES, "Creating new global hna entry: %s (via %s)\n", hna_str, orig_str);
+ bat_dbg(DBG_ROUTES,
+ "Creating new global hna entry: %pM (via %pM)\n",
+ hna_global_entry->addr, orig_node->orig);
spin_lock_irqsave(&hna_global_hash_lock, flags);
hash_add(hna_global_hash, hna_global_entry);
@@ -316,14 +321,16 @@ void hna_global_add_orig(struct orig_node *orig_node,
hna_buff_count++;
}
- orig_node->hna_buff_len = hna_buff_len;
+ /* initialize, and overwrite if malloc succeeds */
+ orig_node->hna_buff = NULL;
+ orig_node->hna_buff_len = 0;
- if (orig_node->hna_buff_len > 0) {
- orig_node->hna_buff = kmalloc(orig_node->hna_buff_len,
- GFP_ATOMIC);
- memcpy(orig_node->hna_buff, hna_buff, orig_node->hna_buff_len);
- } else {
- orig_node->hna_buff = NULL;
+ if (hna_buff_len > 0) {
+ orig_node->hna_buff = kmalloc(hna_buff_len, GFP_ATOMIC);
+ if (orig_node->hna_buff) {
+ memcpy(orig_node->hna_buff, hna_buff, hna_buff_len);
+ orig_node->hna_buff_len = hna_buff_len;
+ }
}
spin_lock_irqsave(&hna_global_hash_lock, flags);
@@ -333,7 +340,7 @@ void hna_global_add_orig(struct orig_node *orig_node,
hna_global_hash->size * 2);
if (swaphash == NULL)
- debug_log(LOG_TYPE_CRIT, "Couldn't resize global hna hash table \n");
+ printk(KERN_ERR "batman-adv:Couldn't resize global hna hash table \n");
else
hna_global_hash = swaphash;
}
@@ -344,17 +351,17 @@ void hna_global_add_orig(struct orig_node *orig_node,
int hna_global_fill_buffer_text(unsigned char *buff, int buff_len)
{
struct hna_global_entry *hna_global_entry;
- struct hash_it_t *hashit = NULL;
+ HASHIT(hashit);
int bytes_written = 0;
unsigned long flags;
spin_lock_irqsave(&hna_global_hash_lock, flags);
- while (NULL != (hashit = hash_iterate(hna_global_hash, hashit))) {
+ while (hash_iterate(hna_global_hash, &hashit)) {
if (buff_len < bytes_written + (2 * ETH_STR_LEN) + 10)
break;
- hna_global_entry = hashit->bucket->data;
+ hna_global_entry = hashit.bucket->data;
bytes_written += snprintf(buff + bytes_written,
(2 * ETH_STR_LEN) + 10,
@@ -381,12 +388,9 @@ int hna_global_fill_buffer_text(unsigned char *buff, int buff_len)
void _hna_global_del_orig(struct hna_global_entry *hna_global_entry,
char *message)
{
- char hna_str[ETH_STR_LEN], orig_str[ETH_STR_LEN];
-
- addr_to_string(orig_str, hna_global_entry->orig_node->orig);
- addr_to_string(hna_str, hna_global_entry->addr);
-
- debug_log(LOG_TYPE_ROUTES, "Deleting global hna entry %s (via %s): %s \n", hna_str, orig_str, message);
+ bat_dbg(DBG_ROUTES, "Deleting global hna entry %pM (via %pM): %s \n",
+ hna_global_entry->addr, hna_global_entry->orig_node->orig,
+ message);
hash_remove(hna_global_hash, hna_global_entry->addr);
kfree(hna_global_entry);
diff --git a/drivers/staging/batman-adv/translation-table.h b/drivers/staging/batman-adv/translation-table.h
index f7da8112931..281125b729f 100644
--- a/drivers/staging/batman-adv/translation-table.h
+++ b/drivers/staging/batman-adv/translation-table.h
@@ -23,6 +23,7 @@
int hna_local_init(void);
void hna_local_add(uint8_t *addr);
+void hna_local_remove(uint8_t *addr, char *message);
int hna_local_fill_buffer(unsigned char *buff, int buff_len);
int hna_local_fill_buffer_text(unsigned char *buff, int buff_len);
void hna_local_purge(struct work_struct *work);
diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h
index 3a0ef0c38c9..dec1b54031b 100644
--- a/drivers/staging/batman-adv/types.h
+++ b/drivers/staging/batman-adv/types.h
@@ -39,7 +39,6 @@ struct batman_if {
char if_active;
char addr_str[ETH_STR_LEN];
struct net_device *net_dev;
- struct socket *raw_sock;
atomic_t seqno;
unsigned char *packet_buff;
int packet_len;
@@ -75,7 +74,7 @@ struct neigh_node {
uint8_t tq_index;
uint8_t tq_avg;
uint8_t last_ttl;
- unsigned long last_valid; /* when last packet via this neighbour was received */
+ unsigned long last_valid; /* when last packet via this neighbor was received */
TYPE_OF_WORD real_bits[NUM_WORDS];
struct orig_node *orig_node;
struct batman_if *if_incoming;
@@ -113,6 +112,7 @@ struct forw_packet { /* structure for forw_list maintaining packet
struct hlist_node list;
unsigned long send_time;
uint8_t own;
+ struct sk_buff *skb;
unsigned char *packet_buff;
uint16_t packet_len;
uint32_t direct_link_flags;
@@ -121,4 +121,14 @@ struct forw_packet { /* structure for forw_list maintaining packet
struct batman_if *if_incoming;
};
+/* While scanning for vis-entries of a particular vis-originator
+ * this list collects its interfaces to create a subgraph/cluster
+ * out of them later
+ */
+struct if_list_entry {
+ uint8_t addr[ETH_ALEN];
+ bool primary;
+ struct hlist_node list;
+};
+
#endif
diff --git a/drivers/staging/batman-adv/vis.c b/drivers/staging/batman-adv/vis.c
index f6c9acb289e..fedec1bb309 100644
--- a/drivers/staging/batman-adv/vis.c
+++ b/drivers/staging/batman-adv/vis.c
@@ -23,11 +23,9 @@
#include "send.h"
#include "translation-table.h"
#include "vis.h"
-#include "log.h"
#include "soft-interface.h"
#include "hard-interface.h"
#include "hash.h"
-#include "compat.h"
struct hashtable_t *vis_hash;
DEFINE_SPINLOCK(vis_hash_lock);
@@ -50,39 +48,6 @@ static void free_info(void *data)
kfree(info);
}
-/* set the mode of the visualization to client or server */
-void vis_set_mode(int mode)
-{
- spin_lock(&vis_hash_lock);
-
- if (my_vis_info != NULL)
- my_vis_info->packet.vis_type = mode;
-
- spin_unlock(&vis_hash_lock);
-}
-
-/* is_vis_server(), locked outside */
-static int is_vis_server_locked(void)
-{
- if (my_vis_info != NULL)
- if (my_vis_info->packet.vis_type == VIS_TYPE_SERVER_SYNC)
- return 1;
-
- return 0;
-}
-
-/* get the current set mode */
-int is_vis_server(void)
-{
- int ret = 0;
-
- spin_lock(&vis_hash_lock);
- ret = is_vis_server_locked();
- spin_unlock(&vis_hash_lock);
-
- return ret;
-}
-
/* Compare two vis packets, used by the hashing algorithm */
static int vis_info_cmp(void *data1, void *data2)
{
@@ -115,6 +80,68 @@ static int vis_info_choose(void *data, int size)
return hash % size;
}
+/* insert interface to the list of interfaces of one originator, if it
+ * does not already exist in the list */
+static void proc_vis_insert_interface(const uint8_t *interface,
+ struct hlist_head *if_list,
+ bool primary)
+{
+ struct if_list_entry *entry;
+ struct hlist_node *pos;
+
+ hlist_for_each_entry(entry, pos, if_list, list) {
+ if (compare_orig(entry->addr, (void *)interface))
+ return;
+ }
+
+ /* its a new address, add it to the list */
+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return;
+ memcpy(entry->addr, interface, ETH_ALEN);
+ entry->primary = primary;
+ hlist_add_head(&entry->list, if_list);
+}
+
+void proc_vis_read_prim_sec(struct seq_file *seq,
+ struct hlist_head *if_list)
+{
+ struct if_list_entry *entry;
+ struct hlist_node *pos, *n;
+ char tmp_addr_str[ETH_STR_LEN];
+
+ hlist_for_each_entry_safe(entry, pos, n, if_list, list) {
+ if (entry->primary) {
+ seq_printf(seq, "PRIMARY, ");
+ } else {
+ addr_to_string(tmp_addr_str, entry->addr);
+ seq_printf(seq, "SEC %s, ", tmp_addr_str);
+ }
+
+ hlist_del(&entry->list);
+ kfree(entry);
+ }
+}
+
+/* read an entry */
+void proc_vis_read_entry(struct seq_file *seq,
+ struct vis_info_entry *entry,
+ struct hlist_head *if_list,
+ uint8_t *vis_orig)
+{
+ char to[40];
+
+ addr_to_string(to, entry->dest);
+ if (entry->quality == 0) {
+ proc_vis_insert_interface(vis_orig, if_list, true);
+ seq_printf(seq, "HNA %s, ", to);
+ } else {
+ proc_vis_insert_interface(entry->src, if_list,
+ compare_orig(entry->src, vis_orig));
+ seq_printf(seq, "TQ %s %d, ", to, entry->quality);
+ }
+}
+
/* tries to add one entry to the receive list. */
static void recv_list_add(struct list_head *recv_list, char *mac)
{
@@ -208,21 +235,23 @@ void receive_server_sync_packet(struct vis_packet *vis_packet, int vis_info_len)
{
struct vis_info *info;
int is_new;
+ unsigned long flags;
+ int vis_server = atomic_read(&vis_mode);
- spin_lock(&vis_hash_lock);
+ spin_lock_irqsave(&vis_hash_lock, flags);
info = add_packet(vis_packet, vis_info_len, &is_new);
if (info == NULL)
goto end;
/* only if we are server ourselves and packet is newer than the one in
* hash.*/
- if (is_vis_server_locked() && is_new) {
+ if (vis_server == VIS_TYPE_SERVER_SYNC && is_new) {
memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
if (list_empty(&info->send_list))
list_add_tail(&info->send_list, &send_list);
}
end:
- spin_unlock(&vis_hash_lock);
+ spin_unlock_irqrestore(&vis_hash_lock, flags);
}
/* handle an incoming client update packet and schedule forward if needed. */
@@ -231,12 +260,14 @@ void receive_client_update_packet(struct vis_packet *vis_packet,
{
struct vis_info *info;
int is_new;
+ unsigned long flags;
+ int vis_server = atomic_read(&vis_mode);
/* clients shall not broadcast. */
if (is_bcast(vis_packet->target_orig))
return;
- spin_lock(&vis_hash_lock);
+ spin_lock_irqsave(&vis_hash_lock, flags);
info = add_packet(vis_packet, vis_info_len, &is_new);
if (info == NULL)
goto end;
@@ -244,7 +275,7 @@ void receive_client_update_packet(struct vis_packet *vis_packet,
/* send only if we're the target server or ... */
- if (is_vis_server_locked() &&
+ if (vis_server == VIS_TYPE_SERVER_SYNC &&
is_my_mac(info->packet.target_orig) &&
is_new) {
info->packet.vis_type = VIS_TYPE_SERVER_SYNC; /* upgrade! */
@@ -258,7 +289,7 @@ void receive_client_update_packet(struct vis_packet *vis_packet,
list_add_tail(&info->send_list, &send_list);
}
end:
- spin_unlock(&vis_hash_lock);
+ spin_unlock_irqrestore(&vis_hash_lock, flags);
}
/* Walk the originators and find the VIS server with the best tq. Set the packet
@@ -267,12 +298,12 @@ end:
* Must be called with the originator hash locked */
static int find_best_vis_server(struct vis_info *info)
{
- struct hash_it_t *hashit = NULL;
+ HASHIT(hashit);
struct orig_node *orig_node;
int best_tq = -1;
- while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
- orig_node = hashit->bucket->data;
+ while (hash_iterate(orig_hash, &hashit)) {
+ orig_node = hashit.bucket->data;
if ((orig_node != NULL) &&
(orig_node->router != NULL) &&
(orig_node->flags & VIS_SERVER) &&
@@ -298,7 +329,8 @@ static bool vis_packet_full(struct vis_info *info)
* returns 0 on success, -1 if no packet could be generated */
static int generate_vis_packet(void)
{
- struct hash_it_t *hashit = NULL;
+ HASHIT(hashit_local);
+ HASHIT(hashit_global);
struct orig_node *orig_node;
struct vis_info *info = (struct vis_info *)my_vis_info;
struct vis_info_entry *entry, *entry_array;
@@ -307,27 +339,27 @@ static int generate_vis_packet(void)
unsigned long flags;
info->first_seen = jiffies;
+ info->packet.vis_type = atomic_read(&vis_mode);
- spin_lock(&orig_hash_lock);
+ spin_lock_irqsave(&orig_hash_lock, flags);
memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
info->packet.ttl = TTL;
info->packet.seqno++;
info->packet.entries = 0;
- if (!is_vis_server_locked()) {
+ if (info->packet.vis_type == VIS_TYPE_CLIENT_UPDATE) {
best_tq = find_best_vis_server(info);
if (best_tq < 0) {
- spin_unlock(&orig_hash_lock);
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
return -1;
}
}
- hashit = NULL;
entry_array = (struct vis_info_entry *)
((char *)info + sizeof(struct vis_info));
- while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
- orig_node = hashit->bucket->data;
+ while (hash_iterate(orig_hash, &hashit_global)) {
+ orig_node = hashit_global.bucket->data;
if (orig_node->router != NULL
&& compare_orig(orig_node->router->addr, orig_node->orig)
&& orig_node->batman_if
@@ -342,18 +374,17 @@ static int generate_vis_packet(void)
info->packet.entries++;
if (vis_packet_full(info)) {
- spin_unlock(&orig_hash_lock);
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
return 0;
}
}
}
- spin_unlock(&orig_hash_lock);
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
- hashit = NULL;
spin_lock_irqsave(&hna_local_hash_lock, flags);
- while (NULL != (hashit = hash_iterate(hna_local_hash, hashit))) {
- hna_local_entry = hashit->bucket->data;
+ while (hash_iterate(hna_local_hash, &hashit_local)) {
+ hna_local_entry = hashit_local.bucket->data;
entry = &entry_array[info->packet.entries];
memset(entry->src, 0, ETH_ALEN);
memcpy(entry->dest, hna_local_entry->addr, ETH_ALEN);
@@ -371,16 +402,16 @@ static int generate_vis_packet(void)
static void purge_vis_packets(void)
{
- struct hash_it_t *hashit = NULL;
+ HASHIT(hashit);
struct vis_info *info;
- while (NULL != (hashit = hash_iterate(vis_hash, hashit))) {
- info = hashit->bucket->data;
+ while (hash_iterate(vis_hash, &hashit)) {
+ info = hashit.bucket->data;
if (info == my_vis_info) /* never purge own data. */
continue;
if (time_after(jiffies,
- info->first_seen + (VIS_TIMEOUT/1000)*HZ)) {
- hash_remove_bucket(vis_hash, hashit);
+ info->first_seen + (VIS_TIMEOUT*HZ)/1000)) {
+ hash_remove_bucket(vis_hash, &hashit);
free_info(info);
}
}
@@ -388,14 +419,15 @@ static void purge_vis_packets(void)
static void broadcast_vis_packet(struct vis_info *info, int packet_length)
{
- struct hash_it_t *hashit = NULL;
+ HASHIT(hashit);
struct orig_node *orig_node;
+ unsigned long flags;
- spin_lock(&orig_hash_lock);
+ spin_lock_irqsave(&orig_hash_lock, flags);
/* send to all routers in range. */
- while (NULL != (hashit = hash_iterate(orig_hash, hashit))) {
- orig_node = hashit->bucket->data;
+ while (hash_iterate(orig_hash, &hashit)) {
+ orig_node = hashit.bucket->data;
/* if it's a vis server and reachable, send it. */
if (orig_node &&
@@ -418,14 +450,15 @@ static void broadcast_vis_packet(struct vis_info *info, int packet_length)
}
}
memcpy(info->packet.target_orig, broadcastAddr, ETH_ALEN);
- spin_unlock(&orig_hash_lock);
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
}
static void unicast_vis_packet(struct vis_info *info, int packet_length)
{
struct orig_node *orig_node;
+ unsigned long flags;
- spin_lock(&orig_hash_lock);
+ spin_lock_irqsave(&orig_hash_lock, flags);
orig_node = ((struct orig_node *)
hash_find(orig_hash, info->packet.target_orig));
@@ -436,7 +469,7 @@ static void unicast_vis_packet(struct vis_info *info, int packet_length)
orig_node->batman_if,
orig_node->router->addr);
}
- spin_unlock(&orig_hash_lock);
+ spin_unlock_irqrestore(&orig_hash_lock, flags);
}
/* only send one vis packet. called from send_vis_packets() */
@@ -445,8 +478,7 @@ static void send_vis_packet(struct vis_info *info)
int packet_length;
if (info->packet.ttl < 2) {
- debug_log(LOG_TYPE_NOTICE,
- "Error - can't send vis packet: ttl exceeded\n");
+ printk(KERN_WARNING "batman-adv: Error - can't send vis packet: ttl exceeded\n");
return;
}
@@ -467,8 +499,9 @@ static void send_vis_packet(struct vis_info *info)
static void send_vis_packets(struct work_struct *work)
{
struct vis_info *info, *temp;
+ unsigned long flags;
- spin_lock(&vis_hash_lock);
+ spin_lock_irqsave(&vis_hash_lock, flags);
purge_vis_packets();
if (generate_vis_packet() == 0)
@@ -479,7 +512,7 @@ static void send_vis_packets(struct work_struct *work)
list_del_init(&info->send_list);
send_vis_packet(info);
}
- spin_unlock(&vis_hash_lock);
+ spin_unlock_irqrestore(&vis_hash_lock, flags);
start_vis_timer();
}
static DECLARE_DELAYED_WORK(vis_timer_wq, send_vis_packets);
@@ -488,20 +521,21 @@ static DECLARE_DELAYED_WORK(vis_timer_wq, send_vis_packets);
* initialized (e.g. bat0 is initialized, interfaces have been added) */
int vis_init(void)
{
+ unsigned long flags;
if (vis_hash)
return 1;
- spin_lock(&vis_hash_lock);
+ spin_lock_irqsave(&vis_hash_lock, flags);
vis_hash = hash_new(256, vis_info_cmp, vis_info_choose);
if (!vis_hash) {
- debug_log(LOG_TYPE_CRIT, "Can't initialize vis_hash\n");
+ printk(KERN_ERR "batman-adv:Can't initialize vis_hash\n");
goto err;
}
my_vis_info = kmalloc(1000, GFP_ATOMIC);
if (!my_vis_info) {
- debug_log(LOG_TYPE_CRIT, "Can't initialize vis packet\n");
+ printk(KERN_ERR "batman-adv:Can't initialize vis packet\n");
goto err;
}
@@ -511,7 +545,6 @@ int vis_init(void)
INIT_LIST_HEAD(&my_vis_info->send_list);
my_vis_info->packet.version = COMPAT_VERSION;
my_vis_info->packet.packet_type = BAT_VIS;
- my_vis_info->packet.vis_type = VIS_TYPE_CLIENT_UPDATE;
my_vis_info->packet.ttl = TTL;
my_vis_info->packet.seqno = 0;
my_vis_info->packet.entries = 0;
@@ -522,19 +555,19 @@ int vis_init(void)
memcpy(my_vis_info->packet.sender_orig, mainIfAddr, ETH_ALEN);
if (hash_add(vis_hash, my_vis_info) < 0) {
- debug_log(LOG_TYPE_CRIT,
- "Can't add own vis packet into hash\n");
+ printk(KERN_ERR
+ "batman-adv:Can't add own vis packet into hash\n");
free_info(my_vis_info); /* not in hash, need to remove it
* manually. */
goto err;
}
- spin_unlock(&vis_hash_lock);
+ spin_unlock_irqrestore(&vis_hash_lock, flags);
start_vis_timer();
return 1;
err:
- spin_unlock(&vis_hash_lock);
+ spin_unlock_irqrestore(&vis_hash_lock, flags);
vis_quit();
return 0;
}
@@ -542,23 +575,23 @@ err:
/* shutdown vis-server */
void vis_quit(void)
{
+ unsigned long flags;
if (!vis_hash)
return;
cancel_delayed_work_sync(&vis_timer_wq);
- spin_lock(&vis_hash_lock);
+ spin_lock_irqsave(&vis_hash_lock, flags);
/* properly remove, kill timers ... */
hash_delete(vis_hash, free_info);
vis_hash = NULL;
my_vis_info = NULL;
- spin_unlock(&vis_hash_lock);
+ spin_unlock_irqrestore(&vis_hash_lock, flags);
}
/* schedule packets for (re)transmission */
static void start_vis_timer(void)
{
queue_delayed_work(bat_event_workqueue, &vis_timer_wq,
- (atomic_read(&vis_interval)/1000) * HZ);
+ (atomic_read(&vis_interval) * HZ) / 1000);
}
-
diff --git a/drivers/staging/batman-adv/vis.h b/drivers/staging/batman-adv/vis.h
index 276fabab4e8..0cdafde0ec3 100644
--- a/drivers/staging/batman-adv/vis.h
+++ b/drivers/staging/batman-adv/vis.h
@@ -45,16 +45,15 @@ struct recvlist_node {
uint8_t mac[ETH_ALEN];
};
-enum vis_formats {
- DOT_DRAW,
- JSON,
-};
-
extern struct hashtable_t *vis_hash;
extern spinlock_t vis_hash_lock;
-void vis_set_mode(int mode);
-int is_vis_server(void);
+void proc_vis_read_entry(struct seq_file *seq,
+ struct vis_info_entry *entry,
+ struct hlist_head *if_list,
+ uint8_t *vis_orig);
+void proc_vis_read_prim_sec(struct seq_file *seq,
+ struct hlist_head *if_list);
void receive_server_sync_packet(struct vis_packet *vis_packet,
int vis_info_len);
void receive_client_update_packet(struct vis_packet *vis_packet,
diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c
index a9fdcda5db7..581aa5fee2e 100644
--- a/drivers/staging/comedi/comedi_compat32.c
+++ b/drivers/staging/comedi/comedi_compat32.c
@@ -26,7 +26,6 @@
#define __NO_VERSION__
#include "comedi.h"
-#include <linux/smp_lock.h>
#include <linux/uaccess.h>
#include "comedi_compat32.h"
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 8117748ad5a..aca96747e5e 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -63,7 +63,7 @@ module_param(comedi_debug, int, 0644);
int comedi_autoconfig = 1;
module_param(comedi_autoconfig, bool, 0444);
-int comedi_num_legacy_minors = 0;
+int comedi_num_legacy_minors;
module_param(comedi_num_legacy_minors, int, 0444);
static DEFINE_SPINLOCK(comedi_file_info_table_lock);
@@ -1510,7 +1510,7 @@ static unsigned int comedi_poll(struct file *file, poll_table * wait)
}
static ssize_t comedi_write(struct file *file, const char *buf, size_t nbytes,
- loff_t * offset)
+ loff_t *offset)
{
struct comedi_subdevice *s;
struct comedi_async *async;
@@ -1612,7 +1612,7 @@ done:
}
static ssize_t comedi_read(struct file *file, char *buf, size_t nbytes,
- loff_t * offset)
+ loff_t *offset)
{
struct comedi_subdevice *s;
struct comedi_async *async;
@@ -2004,12 +2004,10 @@ void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
if (async->cb_mask & s->async->events) {
if (comedi_get_subdevice_runflags(s) & SRF_USER) {
wake_up_interruptible(&async->wait_head);
- if (s->subdev_flags & SDF_CMD_READ) {
+ if (s->subdev_flags & SDF_CMD_READ)
kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
- }
- if (s->subdev_flags & SDF_CMD_WRITE) {
+ if (s->subdev_flags & SDF_CMD_WRITE)
kill_fasync(&dev->async_queue, SIGIO, POLL_OUT);
- }
} else {
if (async->cb_func)
async->cb_func(s->async->events, async->cb_arg);
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index c2a632d31c6..44d6b62c230 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -44,7 +44,7 @@
#include <linux/cdev.h>
#include <linux/dma-mapping.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/system.h>
static int postconfig(struct comedi_device *dev);
@@ -99,11 +99,10 @@ static void cleanup_device(struct comedi_device *dev)
static void __comedi_device_detach(struct comedi_device *dev)
{
dev->attached = 0;
- if (dev->driver) {
+ if (dev->driver)
dev->driver->detach(dev);
- } else {
+ else
printk("BUG: dev->driver=NULL in comedi_device_detach()\n");
- }
cleanup_device(dev);
}
@@ -380,9 +379,8 @@ static int insn_rw_emulate_bits(struct comedi_device *dev,
if (ret < 0)
return ret;
- if (insn->insn == INSN_READ) {
+ if (insn->insn == INSN_READ)
data[0] = (new_data[1] >> (chan - base_bitfield_channel)) & 1;
- }
return 1;
}
@@ -429,9 +427,9 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
/* if no change is required, do nothing */
- if (async->prealloc_buf && async->prealloc_bufsz == new_size) {
+ if (async->prealloc_buf && async->prealloc_bufsz == new_size)
return 0;
- }
+
/* deallocate old buffer */
if (async->prealloc_buf) {
vunmap(async->prealloc_buf);
@@ -494,9 +492,9 @@ int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s,
(void *)
get_zeroed_page(GFP_KERNEL);
}
- if (async->buf_page_list[i].virt_addr == NULL) {
+ if (async->buf_page_list[i].virt_addr == NULL)
break;
- }
+
mem_map_reserve(virt_to_page
(async->buf_page_list[i].
virt_addr));
@@ -619,9 +617,9 @@ unsigned int comedi_buf_write_alloc(struct comedi_async *async,
{
unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
- if ((int)(async->buf_write_alloc_count + nbytes - free_end) > 0) {
+ if ((int)(async->buf_write_alloc_count + nbytes - free_end) > 0)
nbytes = free_end - async->buf_write_alloc_count;
- }
+
async->buf_write_alloc_count += nbytes;
/* barrier insures the read of buf_read_count above occurs before
we write data to the write-alloc'ed buffer space */
@@ -635,9 +633,9 @@ unsigned int comedi_buf_write_alloc_strict(struct comedi_async *async,
{
unsigned int free_end = async->buf_read_count + async->prealloc_bufsz;
- if ((int)(async->buf_write_alloc_count + nbytes - free_end) > 0) {
+ if ((int)(async->buf_write_alloc_count + nbytes - free_end) > 0)
nbytes = 0;
- }
+
async->buf_write_alloc_count += nbytes;
/* barrier insures the read of buf_read_count above occurs before
we write data to the write-alloc'ed buffer space */
@@ -657,9 +655,9 @@ unsigned comedi_buf_write_free(struct comedi_async *async, unsigned int nbytes)
async->buf_write_count += nbytes;
async->buf_write_ptr += nbytes;
comedi_buf_munge(async, async->buf_write_count - async->munge_count);
- if (async->buf_write_ptr >= async->prealloc_bufsz) {
+ if (async->buf_write_ptr >= async->prealloc_bufsz)
async->buf_write_ptr %= async->prealloc_bufsz;
- }
+
return nbytes;
}
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
index 0af12fd2a40..fbc26a027de 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Chrono.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
index f3e47e5791d..a6898e4bbb6 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Dig_io.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
index a15c952c0fa..0e498e9eb08 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_INCCPT.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
index 0fc2285c9ef..204d7987700 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Inp_cpt.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
index 138a84f572c..148ce6f67f0 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Pwm.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
index a445dab50ea..6360de59e0e 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ssi.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
index 7e125447579..344df946219 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Tor.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
index d3d78d37de5..de6f7724689 100644
--- a/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
+++ b/drivers/staging/comedi/drivers/addi-data/APCI1710_Ttl.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
index 6e9e7ed4dba..97c10aaa691 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_amcc_S5920.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
@@ -173,11 +173,10 @@ int i_AddiHeaderRW_ReadEeprom(int i_NbOfWordsToRead,
} while (dw_eeprom_busy == EEPROM_BUSY);
/* Select the upper address part */
- if (i_Counter == 0) {
+ if (i_Counter == 0)
b_ReadLowByte = pb_ReadByte[0];
- } else {
+ else
b_ReadHighByte = pb_ReadByte[0];
- }
/* Sleep */
msleep(1);
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.c b/drivers/staging/comedi/drivers/addi-data/addi_common.c
index a56535fbcd3..8db5ab63e36 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_common.h b/drivers/staging/comedi/drivers/addi-data/addi_common.h
index 3ab27cf0fac..caeb6fd2d9b 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_common.h
+++ b/drivers/staging/comedi/drivers/addi-data/addi_common.h
@@ -77,8 +77,8 @@ struct addi_board {
int i_NbrAoChannel; /* num of D/A chans */
int i_AiMaxdata; /* resolution of A/D */
int i_AoMaxdata; /* resolution of D/A */
- const struct comedi_lrange *pr_AiRangelist; /* rangelist for A/D */
- const struct comedi_lrange *pr_AoRangelist; /* rangelist for D/A */
+ const struct comedi_lrange *pr_AiRangelist; /* rangelist for A/D */
+ const struct comedi_lrange *pr_AoRangelist; /* rangelist for D/A */
int i_NbrDiChannel; /* Number of DI channels */
int i_NbrDoChannel; /* Number of DO channels */
diff --git a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
index 69b427390e5..bea329f44d8 100644
--- a/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
+++ b/drivers/staging/comedi/drivers/addi-data/addi_eeprom.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
index 47517a938ec..d7d768ee7c2 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_APCI1710.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
index 016721efdbf..791297266fc 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci035.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
index 723a97bab44..fe06789699f 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1032.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
@@ -54,7 +54,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
#include "hwdrv_apci1032.h"
#include <linux/delay.h>
/* Global variables */
-unsigned int ui_InterruptStatus = 0;
+unsigned int ui_InterruptStatus;
/*
+----------------------------------------------------------------------------+
@@ -108,9 +108,9 @@ int i_APCI1032_ConfigDigitalInput(struct comedi_device *dev, struct comedi_subde
ui_TmpValue =
inl(devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
} /* if (data[1] == ADDIDATA_OR) */
- else {
+ else
outl(0x6, devpriv->iobase + APCI1032_DIGITAL_IP_IRQ);
- } /* else if(data[1] == ADDIDATA_OR) */
+ /* else if(data[1] == ADDIDATA_OR) */
} /* if( data[0] == ADDIDATA_ENABLE) */
else {
ul_Command1 = ul_Command1 & 0xFFFF0000;
@@ -221,9 +221,9 @@ int i_APCI1032_ReadMoreDigitalInput(struct comedi_device *dev, struct comedi_sub
} /* switch(ui_NoOfChannels) */
} /* if(data[1]==0) */
else {
- if (data[1] == 1) {
+ if (data[1] == 1)
*data = ui_InterruptStatus;
- } /* if(data[1]==1) */
+ /* if(data[1]==1) */
} /* else if(data[1]==0) */
return insn->n;
}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
index 36b929ffecb..d5e06ad6acc 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1500.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
index 866eb8d7582..7948c41f60f 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1516.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
index 3ae663bc754..4413279c880 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
index 988e3fc2b85..8bc88adfbb5 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci16xx.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
index d348cd5687a..89783b1eb0b 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2016.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
index ec817082d17..2d325163c16 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2032.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
index aa159dccc36..e01889c3c4f 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci2200.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
index 172fba8dbfe..f93ddd4eb06 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3120.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
@@ -45,7 +45,7 @@ You shoud also find the complete GPL in the COPYING file accompanying this sourc
*/
#include "hwdrv_apci3120.h"
-static unsigned int ui_Temp = 0;
+static unsigned int ui_Temp;
/* FUNCTION DEFINITIONS */
@@ -98,25 +98,22 @@ int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev, struct comedi_su
devpriv->b_InterruptMode = APCI3120_EOS_MODE;
- if (data[1]) {
+ if (data[1])
devpriv->b_EocEosInterrupt = APCI3120_ENABLE;
- } else
+ else
devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
/* Copy channel list and Range List to devpriv */
devpriv->ui_AiNbrofChannels = data[3];
- for (i = 0; i < devpriv->ui_AiNbrofChannels; i++) {
+ for (i = 0; i < devpriv->ui_AiNbrofChannels; i++)
devpriv->ui_AiChannelList[i] = data[4 + i];
- }
- } else /* EOC */
- {
+ } else { /* EOC */
devpriv->b_InterruptMode = APCI3120_EOC_MODE;
- if (data[1]) {
+ if (data[1])
devpriv->b_EocEosInterrupt = APCI3120_ENABLE;
- } else {
+ else
devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
- }
}
return insn->n;
@@ -166,13 +163,9 @@ int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subd
devpriv->us_OutputRegister = 0;
/* devpriv->b_DigitalOutputRegister=0; */
- if (insn->unused[0] == 222) /* second insn read */
- {
-
- for (i = 0; i < insn->n; i++) {
+ if (insn->unused[0] == 222) { /* second insn read */
+ for (i = 0; i < insn->n; i++)
data[i] = devpriv->ui_AiReadData[i];
- }
-
} else {
devpriv->tsk_Current = current; /* Save the current process task structure */
/*
@@ -519,9 +512,8 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_s
/* step 2: make sure trigger sources are unique and mutually compatible */
- if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) {
+ if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
err++;
- }
if (cmd->scan_begin_src != TRIG_TIMER &&
cmd->scan_begin_src != TRIG_FOLLOW)
@@ -548,16 +540,14 @@ int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_s
err++;
}
- if (cmd->scan_begin_src == TRIG_TIMER) /* Test Delay timing */
- {
+ if (cmd->scan_begin_src == TRIG_TIMER) { /* Test Delay timing */
if (cmd->scan_begin_arg < this_board->ui_MinDelaytimeNs) {
cmd->scan_begin_arg = this_board->ui_MinDelaytimeNs;
err++;
}
}
- if (cmd->convert_src == TRIG_TIMER) /* Test Acquisition timing */
- {
+ if (cmd->convert_src == TRIG_TIMER) { /* Test Acquisition timing */
if (cmd->scan_begin_src == TRIG_TIMER) {
if ((cmd->convert_arg)
&& (cmd->convert_arg <
@@ -653,11 +643,10 @@ int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, struct comedi_subde
/* UPDATE-0.7.57->0.7.68devpriv->ui_AiDataLength=s->async->data_len; */
devpriv->ui_AiDataLength = s->async->prealloc_bufsz;
- if (cmd->stop_src == TRIG_COUNT) {
+ if (cmd->stop_src == TRIG_COUNT)
devpriv->ui_AiNbrofScans = cmd->stop_arg;
- } else {
+ else
devpriv->ui_AiNbrofScans = 0;
- }
devpriv->ui_AiTimer0 = 0; /* variables changed to timer0,timer1 */
devpriv->ui_AiTimer1 = 0;
@@ -849,9 +838,8 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev,
}
/*** EL241003 End ******************************************************************************/
- if (devpriv->b_ExttrigEnable == APCI3120_ENABLE) {
+ if (devpriv->b_ExttrigEnable == APCI3120_ENABLE)
i_APCI3120_ExttrigEnable(dev); /* activate EXT trigger */
- }
switch (mode) {
case 1:
/* init timer0 in mode 2 */
@@ -1049,12 +1037,10 @@ int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev,
dmalen1 = 4;
}
} else { /* isn't output buff smaller that our DMA buff? */
- if (dmalen0 > (devpriv->ui_AiDataLength)) {
+ if (dmalen0 > (devpriv->ui_AiDataLength))
dmalen0 = devpriv->ui_AiDataLength;
- }
- if (dmalen1 > (devpriv->ui_AiDataLength)) {
+ if (dmalen1 > (devpriv->ui_AiDataLength))
dmalen1 = devpriv->ui_AiDataLength;
- }
}
devpriv->ui_DmaBufferUsesize[0] = dmalen0;
devpriv->ui_DmaBufferUsesize[1] = dmalen1;
@@ -1356,11 +1342,10 @@ int i_APCI3120_SetupChannelList(struct comedi_device *dev, struct comedi_subdevi
/* store range list to card */
us_TmpValue = CR_CHAN(chanlist[i]); /* get channel number; */
- if (CR_RANGE(chanlist[i]) < APCI3120_BIPOLAR_RANGES) {
+ if (CR_RANGE(chanlist[i]) < APCI3120_BIPOLAR_RANGES)
us_TmpValue &= ((~APCI3120_UNIPOLAR) & 0xff); /* set bipolar */
- } else {
+ else
us_TmpValue |= APCI3120_UNIPOLAR; /* enable unipolar...... */
- }
gain = CR_RANGE(chanlist[i]); /* get gain number */
us_TmpValue |= ((gain & 0x03) << 4); /* <<4 for G0 and G1 bit in RAM */
@@ -1514,8 +1499,7 @@ void v_APCI3120_Interrupt(int irq, void *d)
/* Check If EOS interrupt */
if ((int_daq & 0x2) && (devpriv->b_InterruptMode == APCI3120_EOS_MODE)) {
- if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) /* enable this in without DMA ??? */
- {
+ if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) { /* enable this in without DMA ??? */
if (devpriv->b_AiCyclicAcquisition == APCI3120_ENABLE) {
ui_Check = 0;
@@ -1966,8 +1950,7 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, struct comedi_subdevic
APCI3120_DISABLE_EOS_INT;
outb(devpriv->b_ModeSelectRegister,
devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
- if (data[0] == APCI3120_TIMER) /* initialize timer */
- {
+ if (data[0] == APCI3120_TIMER) { /* initialize timer */
/* devpriv->b_ModeSelectRegister=devpriv->b_ModeSelectRegister |
* APCI3120_ENABLE_TIMER_INT; */
@@ -2006,8 +1989,7 @@ int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, struct comedi_subdevic
/* timer2 in Timer mode enabled */
devpriv->b_Timer2Mode = APCI3120_TIMER;
- } else /* Initialize Watch dog */
- {
+ } else { /* Initialize Watch dog */
/* Set the Timer 2 in mode 5(Watchdog) */
@@ -2092,8 +2074,7 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, struct comedi_subdevice
return -EINVAL;
}
- if (data[0] == 2) /* write new value */
- {
+ if (data[0] == 2) { /* write new value */
if (devpriv->b_Timer2Mode != APCI3120_TIMER) {
comedi_error(dev,
"write :timer2 not configured in TIMER MODE");
@@ -2113,13 +2094,11 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, struct comedi_subdevice
/* Reset FC_TIMER BIT */
inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER);
- if (devpriv->b_Timer2Mode == APCI3120_TIMER) /* start timer */
- {
+ if (devpriv->b_Timer2Mode == APCI3120_TIMER) { /* start timer */
/* Enable Timer */
devpriv->b_ModeSelectRegister =
devpriv->b_ModeSelectRegister & 0x0B;
- } else /* start watch dog */
- {
+ } else { /* start watch dog */
/* Enable WatchDog */
devpriv->b_ModeSelectRegister =
(devpriv->
@@ -2146,8 +2125,7 @@ int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, struct comedi_subdevice
outb(devpriv->b_ModeSelectRegister,
devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
- if (devpriv->b_Timer2Mode == APCI3120_TIMER) /* start timer */
- {
+ if (devpriv->b_Timer2Mode == APCI3120_TIMER) { /* start timer */
/* For Timer mode is Gate2 must be activated **timer started */
devpriv->us_OutputRegister =
devpriv->
@@ -2299,8 +2277,7 @@ int i_APCI3120_InsnReadTimer(struct comedi_device *dev, struct comedi_subdevice
/* combining both words */
data[0] = (unsigned int) ((us_TmpValue) | ((us_TmpValue_2) << 16));
- } else /* Read watch dog status */
- {
+ } else { /* Read watch dog status */
us_StatusValue = inw(devpriv->iobase + APCI3120_RD_STATUS);
us_StatusValue =
@@ -2441,10 +2418,9 @@ int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device *dev,
devpriv->b_OutputMemoryStatus = APCI3120_DISABLE;
devpriv->b_DigitalOutputRegister = 0;
}
- if (!devpriv->b_OutputMemoryStatus) {
+ if (!devpriv->b_OutputMemoryStatus)
ui_Temp = 0;
-
- } /* if(!devpriv->b_OutputMemoryStatus ) */
+ /* if(!devpriv->b_OutputMemoryStatus ) */
return insn->n;
}
@@ -2504,23 +2480,23 @@ int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev,
/*
+----------------------------------------------------------------------------+
-| Function name :int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,|
-|struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) |
-| |
+| Function name :int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,|
+|struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data) |
+| |
+----------------------------------------------------------------------------+
-| Task : Write digiatl output |
-| |
+| Task : Write digiatl output |
+| |
+----------------------------------------------------------------------------+
-| Input Parameters : struct comedi_device *dev |
-| struct comedi_subdevice *s |
-| struct comedi_insn *insn |
-| unsigned int *data |
- data[0] Value to be written
- data[1] :1 Set digital o/p ON
- data[1] 2 Set digital o/p OFF with memory ON
+| Input Parameters : struct comedi_device *dev |
+| struct comedi_subdevice *s |
+| struct comedi_insn *insn |
+| unsigned int *data |
+ data[0] Value to be written
+ data[1] :1 Set digital o/p ON
+ data[1] 2 Set digital o/p OFF with memory ON
+----------------------------------------------------------------------------+
-| Return Value : |
-| |
+| Return Value : |
+| |
+----------------------------------------------------------------------------+
*/
@@ -2615,8 +2591,7 @@ int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,
ui_Channel = CR_CHAN(insn->chanspec);
/* this_board->i_hwdrv_InsnWriteAnalogOutput(dev, ui_Range, ui_Channel,data[0]); */
- if (ui_Range) /* if 1 then unipolar */
- {
+ if (ui_Range) { /* if 1 then unipolar */
if (data[0] != 0)
data[0] =
@@ -2627,8 +2602,7 @@ int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,
((((ui_Channel & 0x03) << 14) & 0xC000) | (1 <<
13) | 8192);
- } else /* if 0 then bipolar */
- {
+ } else { /* if 0 then bipolar */
data[0] =
((((ui_Channel & 0x03) << 14) & 0xC000) | (0 << 13) |
data[0]);
@@ -2639,8 +2613,7 @@ int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,
* out put n values at the given channel. printk("\nwaiting for
* DA_READY BIT");
*/
- do /* Waiting of DA_READY BIT */
- {
+ do { /* Waiting of DA_READY BIT */
us_TmpValue =
((unsigned short) inw(devpriv->iobase +
APCI3120_RD_STATUS)) & 0x0001;
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
index 98c23872e37..560c848f625 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3200.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
index 7b38d177394..4ed441a1adc 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
index 1d1e5fc2ea9..3692326d474 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3xxx.c
@@ -17,7 +17,7 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
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
-You shoud also find the complete GPL in the COPYING file accompanying this source code.
+You should also find the complete GPL in the COPYING file accompanying this source code.
@endverbatim
*/
@@ -1206,7 +1206,7 @@ int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device *dev,
if (b_Channel < 8) {
/*****************************************************************************/
- /* Read port 0 (first digital output port) and set/reset the selcted channel */
+ /* Read port 0 (first digital output port) and set/reset the selected channel */
/*****************************************************************************/
dw_Status = inl(devpriv->iobase + 80);
@@ -1228,7 +1228,7 @@ int i_APCI3XXX_InsnWriteTTLIO(struct comedi_device *dev,
if ((devpriv->ul_TTLPortConfiguration[0] & 0xFF)
== 0xFF) {
/*****************************************************************************/
- /* Read port 2 (first digital output port) and set/reset the selcted channel */
+ /* Read port 2 (first digital output port) and set/reset the selected channel */
/*****************************************************************************/
dw_Status = inl(devpriv->iobase + 112);
diff --git a/drivers/staging/comedi/drivers/adl_pci9118.c b/drivers/staging/comedi/drivers/adl_pci9118.c
index 791ea8334e1..9934a3cf254 100644
--- a/drivers/staging/comedi/drivers/adl_pci9118.c
+++ b/drivers/staging/comedi/drivers/adl_pci9118.c
@@ -88,9 +88,9 @@ Configuration options:
#define IORANGE_9118 64 /* I hope */
#define PCI9118_CHANLEN 255 /* len of chanlist, some source say 256, but reality looks like 255 :-( */
-#define PCI9118_CNT0 0x00 /* R/W: 8254 couter 0 */
-#define PCI9118_CNT1 0x04 /* R/W: 8254 couter 0 */
-#define PCI9118_CNT2 0x08 /* R/W: 8254 couter 0 */
+#define PCI9118_CNT0 0x00 /* R/W: 8254 counter 0 */
+#define PCI9118_CNT1 0x04 /* R/W: 8254 counter 0 */
+#define PCI9118_CNT2 0x08 /* R/W: 8254 counter 0 */
#define PCI9118_CNTCTRL 0x0c /* W: 8254 counter control */
#define PCI9118_AD_DATA 0x10 /* R: A/D data */
#define PCI9118_DA1 0x10 /* W: D/A registers */
diff --git a/drivers/staging/comedi/drivers/adq12b.c b/drivers/staging/comedi/drivers/adq12b.c
index c5ed8bb9760..f3ba645bf63 100644
--- a/drivers/staging/comedi/drivers/adq12b.c
+++ b/drivers/staging/comedi/drivers/adq12b.c
@@ -42,23 +42,23 @@ If you do not specify any options, they will default to
option 1: I/O base address. The following table is provided as a help
of the hardware jumpers.
- address jumper JADR
- 0x300 1 (factory default)
- 0x320 2
- 0x340 3
- 0x360 4
- 0x380 5
- 0x3A0 6
+ address jumper JADR
+ 0x300 1 (factory default)
+ 0x320 2
+ 0x340 3
+ 0x360 4
+ 0x380 5
+ 0x3A0 6
option 2: unipolar/bipolar ADC selection: 0 -> bipolar, 1 -> unipolar
- selection comedi_config option JUB
- bipolar 0 2-3 (factory default)
- unipolar 1 1-2
+ selection comedi_config option JUB
+ bipolar 0 2-3 (factory default)
+ unipolar 1 1-2
option 3: single-ended/differential AI selection: 0 -> SE, 1 -> differential
- selection comedi_config option JCHA JCHB
+ selection comedi_config option JCHA JCHB
single-ended 0 1-2 1-2 (factory default)
differential 1 2-3 2-3
@@ -140,7 +140,7 @@ static const struct adq12b_board adq12b_boards[] = {
.ai_bits = 12,
.di_chans = 8,
.do_chans = 5
- }*/
+ }*/
};
#define thisboard ((const struct adq12b_board *)dev->board_ptr)
@@ -164,14 +164,15 @@ struct adq12b_private {
static int adq12b_attach(struct comedi_device *dev,
struct comedi_devconfig *it);
static int adq12b_detach(struct comedi_device *dev);
+
static struct comedi_driver driver_adq12b = {
-driver_name:"adq12b",
-module:THIS_MODULE,
-attach:adq12b_attach,
-detach:adq12b_detach,
-board_name:&adq12b_boards[0].name,
-offset:sizeof(struct adq12b_board),
-num_names:ARRAY_SIZE(adq12b_boards),
+ .driver_name = "adq12b",
+ .module = THIS_MODULE,
+ .attach = adq12b_attach,
+ .detach = adq12b_detach,
+ .board_name = &adq12b_boards[0].name,
+ .offset = sizeof(struct adq12b_board),
+ .num_names = ARRAY_SIZE(adq12b_boards),
};
static int adq12b_ai_rinsn(struct comedi_device *dev,
@@ -200,15 +201,16 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
unipolar = it->options[1];
differential = it->options[2];
- printk("comedi%d: adq12b called with options base=0x%03lx, %s and %s\n",
- dev->minor, iobase, (unipolar == 1) ? "unipolar" : "bipolar",
+ printk(KERN_INFO "comedi%d: adq12b called with options base=0x%03lx, "
+ "%s and %s\n", dev->minor, iobase,
+ (unipolar == 1) ? "unipolar" : "bipolar",
(differential == 1) ? "differential" : "single-ended");
/* if no address was specified, try the default 0x300 */
if (iobase == 0) {
- printk
- ("comedi%d: adq12b warning: I/O base address not specified. Trying the default 0x300.\n",
- dev->minor);
+ printk(KERN_WARNING "comedi%d: adq12b warning: I/O base "
+ "address not specified. Trying the default 0x300.\n",
+ dev->minor);
iobase = 0x300;
}
@@ -259,11 +261,10 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->n_chan = thisboard->ai_se_chans;
}
- if (unipolar) {
+ if (unipolar)
s->range_table = &range_adq12b_ai_unipolar;
- } else {
+ else
s->range_table = &range_adq12b_ai_bipolar;
- }
s->maxdata = (1 << thisboard->ai_bits) - 1;
@@ -289,7 +290,7 @@ static int adq12b_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->range_table = &range_digital;
s->insn_bits = adq12b_do_insn_bits;
- printk("attached\n");
+ printk(KERN_INFO "attached\n");
return 0;
}
@@ -309,7 +310,7 @@ static int adq12b_detach(struct comedi_device *dev)
kfree(devpriv);
- printk("comedi%d: adq12b: removed\n", dev->minor);
+ printk(KERN_INFO "comedi%d: adq12b: removed\n", dev->minor);
return 0;
}
@@ -344,17 +345,18 @@ static int adq12b_ai_rinsn(struct comedi_device *dev,
/* wait for end of convertion */
i = 0;
do {
-/* udelay(1); */
+ /* udelay(1); */
status = inb(dev->iobase + ADQ12B_STINR);
status = status & ADQ12B_EOC;
} while (status == 0 && ++i < TIMEOUT);
-/* } while (++i < 10); */
+ /* } while (++i < 10); */
/* read data */
hi = inb(dev->iobase + ADQ12B_ADHIG);
lo = inb(dev->iobase + ADQ12B_ADLOW);
- /* printk("debug: chan=%d range=%d status=%d hi=%d lo=%d\n", channel, range, status, hi, lo); */
+ /* printk("debug: chan=%d range=%d status=%d hi=%d lo=%d\n",
+ channel, range, status, hi, lo); */
data[n] = (hi << 8) | lo;
}
diff --git a/drivers/staging/comedi/drivers/adv_pci1710.c b/drivers/staging/comedi/drivers/adv_pci1710.c
index 951e57949f7..394d2ea19c2 100644
--- a/drivers/staging/comedi/drivers/adv_pci1710.c
+++ b/drivers/staging/comedi/drivers/adv_pci1710.c
@@ -84,9 +84,9 @@ Configuration options:
#define PCI171x_DAREF 14 /* W: D/A reference control */
#define PCI171x_DI 16 /* R: digi inputs */
#define PCI171x_DO 16 /* R: digi inputs */
-#define PCI171x_CNT0 24 /* R/W: 8254 couter 0 */
-#define PCI171x_CNT1 26 /* R/W: 8254 couter 1 */
-#define PCI171x_CNT2 28 /* R/W: 8254 couter 2 */
+#define PCI171x_CNT0 24 /* R/W: 8254 counter 0 */
+#define PCI171x_CNT1 26 /* R/W: 8254 counter 1 */
+#define PCI171x_CNT2 28 /* R/W: 8254 counter 2 */
#define PCI171x_CNTCTRL 30 /* W: 8254 counter control */
/* upper bits from status register (PCI171x_STATUS) (lower is same woth control reg) */
@@ -724,6 +724,7 @@ static int move_block_from_fifo(struct comedi_device *dev,
devpriv->ai_act_scan++;
}
}
+ s->async->cur_chan = j;
DPRINTK("adv_pci1710 EDBG: END: move_block_from_fifo(...)\n");
return 0;
}
@@ -1034,14 +1035,6 @@ static int pci171x_ai_cmdtest(struct comedi_device *dev,
}
}
- if (!cmd->chanlist_len) {
- cmd->chanlist_len = 1;
- err++;
- }
- if (cmd->chanlist_len > this_board->n_aichan) {
- cmd->chanlist_len = this_board->n_aichan;
- err++;
- }
if (cmd->scan_end_arg != cmd->chanlist_len) {
cmd->scan_end_arg = cmd->chanlist_len;
err++;
@@ -1230,6 +1223,12 @@ static void setup_channel_list(struct comedi_device *dev,
DPRINTK("GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range,
devpriv->act_chanlist[i]);
}
+#ifdef PCI171x_PARANOIDCHECK
+ for ( ; i < n_chan; i++) { /* store remainder of channel list */
+ devpriv->act_chanlist[i] =
+ (CR_CHAN(chanlist[i]) << 12) & 0xf000;
+ }
+#endif
devpriv->ai_et_MuxVal =
CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8);
diff --git a/drivers/staging/comedi/drivers/aio_iiro_16.c b/drivers/staging/comedi/drivers/aio_iiro_16.c
index 3857fd566d2..4baef9ff932 100644
--- a/drivers/staging/comedi/drivers/aio_iiro_16.c
+++ b/drivers/staging/comedi/drivers/aio_iiro_16.c
@@ -98,7 +98,7 @@ static int aio_iiro_16_attach(struct comedi_device *dev,
int iobase;
struct comedi_subdevice *s;
- printk("comedi%d: aio_iiro_16: ", dev->minor);
+ printk(KERN_INFO "comedi%d: aio_iiro_16: ", dev->minor);
dev->board_name = thisboard->name;
@@ -140,7 +140,7 @@ static int aio_iiro_16_attach(struct comedi_device *dev,
static int aio_iiro_16_detach(struct comedi_device *dev)
{
- printk("comedi%d: aio_iiro_16: remove\n", dev->minor);
+ printk(KERN_INFO "comedi%d: aio_iiro_16: remove\n", dev->minor);
if (dev->iobase)
release_region(dev->iobase, AIO_IIRO_16_SIZE);
diff --git a/drivers/staging/comedi/drivers/amplc_dio200.c b/drivers/staging/comedi/drivers/amplc_dio200.c
index 69ab2813dd2..204f30ef6e9 100644
--- a/drivers/staging/comedi/drivers/amplc_dio200.c
+++ b/drivers/staging/comedi/drivers/amplc_dio200.c
@@ -48,8 +48,8 @@ Passing a zero for an option is the same as leaving it unspecified.
SUBDEVICES
- PC218E PC212E PC215E/PCI215
- ------------- ------------- -------------
+ PC218E PC212E PC215E/PCI215
+ ------------- ------------- -------------
Subdevices 7 6 5
0 CTR-X1 PPI-X PPI-X
1 CTR-X2 CTR-Y1 PPI-Y
@@ -59,8 +59,8 @@ SUBDEVICES
5 CTR-Z2 INTERRUPT
6 INTERRUPT
- PC214E PC272E/PCI272
- ------------- -------------
+ PC214E PC272E/PCI272
+ ------------- -------------
Subdevices 4 4
0 PPI-X PPI-X
1 PPI-Y PPI-Y
@@ -96,8 +96,8 @@ instructions are supported:
0 to 7 as follows:
0. CLK n, the counter channel's dedicated CLK input from the SK1
- connector. (N.B. for other values, the counter channel's CLKn
- pin on the SK1 connector is an output!)
+ connector. (N.B. for other values, the counter channel's CLKn
+ pin on the SK1 connector is an output!)
1. Internal 10 MHz clock.
2. Internal 1 MHz clock.
3. Internal 100 kHz clock.
@@ -105,8 +105,8 @@ instructions are supported:
5. Internal 1 kHz clock.
6. OUT n-1, the output of counter channel n-1 (see note 1 below).
7. Ext Clock, the counter chip's dedicated Ext Clock input from
- the SK1 connector. This pin is shared by all three counter
- channels on the chip.
+ the SK1 connector. This pin is shared by all three counter
+ channels on the chip.
INSN_CONFIG_GET_CLOCK_SRC. Returns the counter channel's current
clock source in data[1]. For internal clock sources, data[2] is set
@@ -120,10 +120,10 @@ instructions are supported:
0. VCC (internal +5V d.c.), i.e. gate permanently enabled.
1. GND (internal 0V d.c.), i.e. gate permanently disabled.
2. GAT n, the counter channel's dedicated GAT input from the SK1
- connector. (N.B. for other values, the counter channel's GATn
- pin on the SK1 connector is an output!)
+ connector. (N.B. for other values, the counter channel's GATn
+ pin on the SK1 connector is an output!)
3. /OUT n-2, the inverted output of counter channel n-2 (see note
- 2 below).
+ 2 below).
4. Reserved.
5. Reserved.
6. Reserved.
@@ -153,8 +153,8 @@ below.
INTERRUPT SOURCES
- PC218E PC212E PC215E/PCI215
- ------------- ------------- -------------
+ PC218E PC212E PC215E/PCI215
+ ------------- ------------- -------------
Sources 6 6 6
0 CTR-X1-OUT PPI-X-C0 PPI-X-C0
1 CTR-X2-OUT PPI-X-C3 PPI-X-C3
@@ -163,8 +163,8 @@ INTERRUPT SOURCES
4 CTR-Z1-OUT CTR-Z1-OUT CTR-Z1-OUT
5 CTR-Z2-OUT CTR-Z2-OUT CTR-Z2-OUT
- PC214E PC272E/PCI272
- ------------- -------------
+ PC214E PC272E/PCI272
+ ------------- -------------
Sources 1 6
0 JUMPER-J5 PPI-X-C0
1 PPI-X-C3
@@ -435,11 +435,13 @@ MODULE_DEVICE_TABLE(pci, dio200_pci_table);
* Useful for shorthand access to the particular board structure
*/
#define thisboard ((const struct dio200_board *)dev->board_ptr)
-#define thislayout (&dio200_layouts[((struct dio200_board *)dev->board_ptr)->layout])
+#define thislayout (&dio200_layouts[((struct dio200_board *) \
+ dev->board_ptr)->layout])
/* this structure is for data unique to this hardware driver. If
several hardware drivers keep similar information in this structure,
- feel free to suggest moving the variable to the struct comedi_device struct. */
+ feel free to suggest moving the variable to the struct comedi_device struct.
+ */
struct dio200_private {
#ifdef CONFIG_COMEDI_PCI
struct pci_dev *pci_dev; /* PCI device */
@@ -603,9 +605,8 @@ static void dio200_stop_intr(struct comedi_device *dev,
subpriv->active = 0;
subpriv->enabled_isns = 0;
- if (subpriv->has_int_sce) {
+ if (subpriv->has_int_sce)
outb(0, subpriv->iobase);
- }
}
/*
@@ -629,16 +630,14 @@ static int dio200_start_intr(struct comedi_device *dev,
/* Determine interrupt sources to enable. */
isn_bits = 0;
if (cmd->chanlist) {
- for (n = 0; n < cmd->chanlist_len; n++) {
+ for (n = 0; n < cmd->chanlist_len; n++)
isn_bits |= (1U << CR_CHAN(cmd->chanlist[n]));
- }
}
isn_bits &= subpriv->valid_isns;
/* Enable interrupt sources. */
subpriv->enabled_isns = isn_bits;
- if (subpriv->has_int_sce) {
+ if (subpriv->has_int_sce)
outb(isn_bits, subpriv->iobase);
- }
}
return retval;
@@ -662,14 +661,13 @@ dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
spin_lock_irqsave(&subpriv->spinlock, flags);
s->async->inttrig = 0;
- if (subpriv->active) {
+ if (subpriv->active)
event = dio200_start_intr(dev, s);
- }
+
spin_unlock_irqrestore(&subpriv->spinlock, flags);
- if (event) {
+ if (event)
comedi_event(dev, s);
- }
return 1;
}
@@ -726,9 +724,8 @@ static int dio200_handle_read_intr(struct comedi_device *dev,
* Reenable them NOW to minimize the time they are disabled.
*/
cur_enabled = subpriv->enabled_isns;
- if (subpriv->has_int_sce) {
+ if (subpriv->has_int_sce)
outb(cur_enabled, subpriv->iobase);
- }
if (subpriv->active) {
/*
@@ -747,9 +744,8 @@ static int dio200_handle_read_intr(struct comedi_device *dev,
len = s->async->cmd.chanlist_len;
for (n = 0; n < len; n++) {
ch = CR_CHAN(s->async->cmd.chanlist[n]);
- if (triggered & (1U << ch)) {
+ if (triggered & (1U << ch))
val |= (1U << n);
- }
}
/* Write the scan to the buffer. */
if (comedi_buf_put(s->async, val)) {
@@ -781,9 +777,8 @@ static int dio200_handle_read_intr(struct comedi_device *dev,
}
spin_unlock_irqrestore(&subpriv->spinlock, flags);
- if (oldevents != s->async->events) {
+ if (oldevents != s->async->events)
comedi_event(dev, s);
- }
return (triggered != 0);
}
@@ -798,9 +793,9 @@ static int dio200_subdev_intr_cancel(struct comedi_device *dev,
unsigned long flags;
spin_lock_irqsave(&subpriv->spinlock, flags);
- if (subpriv->active) {
+ if (subpriv->active)
dio200_stop_intr(dev, s);
- }
+
spin_unlock_irqrestore(&subpriv->spinlock, flags);
return 0;
@@ -846,7 +841,8 @@ dio200_subdev_intr_cmdtest(struct comedi_device *dev,
if (err)
return 1;
- /* step 2: make sure trigger sources are unique and mutually compatible */
+ /* step 2: make sure trigger sources are unique and mutually
+ compatible */
/* these tests are true if more than one _src bit is set */
if ((cmd->start_src & (cmd->start_src - 1)) != 0)
@@ -952,9 +948,8 @@ static int dio200_subdev_intr_cmd(struct comedi_device *dev,
}
spin_unlock_irqrestore(&subpriv->spinlock, flags);
- if (event) {
+ if (event)
comedi_event(dev, s);
- }
return 0;
}
@@ -980,9 +975,8 @@ dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
subpriv->valid_isns = valid_isns;
spin_lock_init(&subpriv->spinlock);
- if (has_int_sce) {
+ if (has_int_sce)
outb(0, subpriv->iobase); /* Disable interrupt sources. */
- }
s->private = subpriv;
s->type = COMEDI_SUBD_DI;
@@ -1013,10 +1007,7 @@ dio200_subdev_intr_cleanup(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct dio200_subdev_intr *subpriv = s->private;
-
- if (subpriv) {
- kfree(subpriv);
- }
+ kfree(subpriv);
}
/*
@@ -1027,9 +1018,8 @@ static irqreturn_t dio200_interrupt(int irq, void *d)
struct comedi_device *dev = d;
int handled;
- if (!dev->attached) {
+ if (!dev->attached)
return IRQ_NONE;
- }
if (devpriv->intr_sd >= 0) {
handled = dio200_handle_read_intr(dev,
@@ -1266,10 +1256,7 @@ dio200_subdev_8254_cleanup(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct dio200_subdev_intr *subpriv = s->private;
-
- if (subpriv) {
- kfree(subpriv);
- }
+ kfree(subpriv);
}
/*
@@ -1348,9 +1335,8 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
#endif
{
ret = dio200_request_region(dev->minor, iobase, DIO200_IO_SIZE);
- if (ret < 0) {
+ if (ret < 0)
return ret;
- }
}
dev->iobase = iobase;
@@ -1371,17 +1357,17 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
ret = dio200_subdev_8254_init(dev, s, iobase,
layout->sdinfo[n],
layout->has_clk_gat_sce);
- if (ret < 0) {
+ if (ret < 0)
return ret;
- }
+
break;
case sd_8255:
/* digital i/o subdevice (8255) */
ret = subdev_8255_init(dev, s, 0,
iobase + layout->sdinfo[n]);
- if (ret < 0) {
+ if (ret < 0)
return ret;
- }
+
break;
case sd_intr:
/* 'INTERRUPT' subdevice */
@@ -1392,9 +1378,9 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
layout->sdinfo[n],
layout->
has_int_sce);
- if (ret < 0) {
+ if (ret < 0)
return ret;
- }
+
devpriv->intr_sd = n;
} else {
s->type = COMEDI_SUBD_UNUSED;
@@ -1407,9 +1393,8 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
sdx = devpriv->intr_sd;
- if (sdx >= 0 && sdx < dev->n_subdevices) {
+ if (sdx >= 0 && sdx < dev->n_subdevices)
dev->read_subdev = &dev->subdevices[sdx];
- }
dev->board_name = thisboard->name;
@@ -1434,11 +1419,10 @@ static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
printk("(pci %s) ", pci_name(pci_dev));
#endif
}
- if (irq) {
+ if (irq)
printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
- } else {
+ else
printk("(no irq) ");
- }
printk("attached\n");
@@ -1461,9 +1445,8 @@ static int dio200_detach(struct comedi_device *dev)
printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
DIO200_DRIVER_NAME);
- if (dev->irq) {
+ if (dev->irq)
free_irq(dev->irq, dev);
- }
if (dev->subdevices) {
layout = thislayout;
for (n = 0; n < dev->n_subdevices; n++) {
@@ -1486,22 +1469,19 @@ static int dio200_detach(struct comedi_device *dev)
if (devpriv) {
#ifdef CONFIG_COMEDI_PCI
if (devpriv->pci_dev) {
- if (dev->iobase) {
+ if (dev->iobase)
comedi_pci_disable(devpriv->pci_dev);
- }
pci_dev_put(devpriv->pci_dev);
} else
#endif
{
- if (dev->iobase) {
+ if (dev->iobase)
release_region(dev->iobase, DIO200_IO_SIZE);
- }
}
}
- if (dev->board_name) {
+ if (dev->board_name)
printk(KERN_INFO "comedi%d: %s removed\n",
dev->minor, dev->board_name);
- }
return 0;
}
diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c
index 1032a8110d6..a307d68d79c 100644
--- a/drivers/staging/comedi/drivers/amplc_pc236.c
+++ b/drivers/staging/comedi/drivers/amplc_pc236.c
@@ -78,18 +78,18 @@ unused.
*/
/* Disable interrupt, also clear any interrupt there */
#define PCI236_INTR_DISABLE (PLX9052_INTCSR_LI1ENAB_DISABLED \
- | PLX9052_INTCSR_LI1POL_HIGH \
- | PLX9052_INTCSR_LI2POL_HIGH \
- | PLX9052_INTCSR_PCIENAB_DISABLED \
- | PLX9052_INTCSR_LI1SEL_EDGE \
- | PLX9052_INTCSR_LI1CLRINT_ASSERTED)
+ | PLX9052_INTCSR_LI1POL_HIGH \
+ | PLX9052_INTCSR_LI2POL_HIGH \
+ | PLX9052_INTCSR_PCIENAB_DISABLED \
+ | PLX9052_INTCSR_LI1SEL_EDGE \
+ | PLX9052_INTCSR_LI1CLRINT_ASSERTED)
/* Enable interrupt, also clear any interrupt there. */
#define PCI236_INTR_ENABLE (PLX9052_INTCSR_LI1ENAB_ENABLED \
- | PLX9052_INTCSR_LI1POL_HIGH \
- | PLX9052_INTCSR_LI2POL_HIGH \
- | PLX9052_INTCSR_PCIENAB_ENABLED \
- | PLX9052_INTCSR_LI1SEL_EDGE \
- | PLX9052_INTCSR_LI1CLRINT_ASSERTED)
+ | PLX9052_INTCSR_LI1POL_HIGH \
+ | PLX9052_INTCSR_LI2POL_HIGH \
+ | PLX9052_INTCSR_PCIENAB_ENABLED \
+ | PLX9052_INTCSR_LI1SEL_EDGE \
+ | PLX9052_INTCSR_LI1CLRINT_ASSERTED)
/*
* Board descriptions for Amplicon PC36AT and PCI236.
@@ -150,12 +150,13 @@ MODULE_DEVICE_TABLE(pci, pc236_pci_table);
/* this structure is for data unique to this hardware driver. If
several hardware drivers keep similar information in this structure,
- feel free to suggest moving the variable to the struct comedi_device struct. */
+ feel free to suggest moving the variable to the struct comedi_device struct.
+ */
struct pc236_private {
#ifdef CONFIG_COMEDI_PCI
/* PCI device */
struct pci_dev *pci_dev;
- unsigned long lcr_iobase; /* PLX PCI9052 config registers in PCIBAR1 */
+ unsigned long lcr_iobase; /* PLX PCI9052 config registers in PCIBAR1 */
#endif
int enable_irq;
};
@@ -345,9 +346,8 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
#endif
{
ret = pc236_request_region(dev->minor, iobase, PC236_IO_SIZE);
- if (ret < 0) {
+ if (ret < 0)
return ret;
- }
}
dev->iobase = iobase;
@@ -399,11 +399,10 @@ static int pc236_attach(struct comedi_device *dev, struct comedi_devconfig *it)
printk("(pci %s) ", pci_name(pci_dev));
#endif
}
- if (irq) {
+ if (irq)
printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
- } else {
+ else
printk("(no irq) ");
- }
printk("attached\n");
@@ -422,27 +421,24 @@ static int pc236_detach(struct comedi_device *dev)
{
printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
PC236_DRIVER_NAME);
- if (devpriv) {
+ if (devpriv)
pc236_intr_disable(dev);
- }
+
if (dev->irq)
free_irq(dev->irq, dev);
- if (dev->subdevices) {
+ if (dev->subdevices)
subdev_8255_cleanup(dev, dev->subdevices + 0);
- }
if (devpriv) {
#ifdef CONFIG_COMEDI_PCI
if (devpriv->pci_dev) {
- if (dev->iobase) {
+ if (dev->iobase)
comedi_pci_disable(devpriv->pci_dev);
- }
pci_dev_put(devpriv->pci_dev);
} else
#endif
{
- if (dev->iobase) {
+ if (dev->iobase)
release_region(dev->iobase, PC236_IO_SIZE);
- }
}
}
if (dev->board_name) {
diff --git a/drivers/staging/comedi/drivers/amplc_pci224.c b/drivers/staging/comedi/drivers/amplc_pci224.c
index d9836879355..b41e5e5963a 100644
--- a/drivers/staging/comedi/drivers/amplc_pci224.c
+++ b/drivers/staging/comedi/drivers/amplc_pci224.c
@@ -1536,20 +1536,12 @@ static int pci224_detach(struct comedi_device *dev)
s = dev->subdevices + 0;
/* AO subdevice */
- if (s->range_table_list) {
- kfree(s->range_table_list);
- }
+ kfree(s->range_table_list);
}
if (devpriv) {
- if (devpriv->ao_readback) {
- kfree(devpriv->ao_readback);
- }
- if (devpriv->ao_scan_vals) {
- kfree(devpriv->ao_scan_vals);
- }
- if (devpriv->ao_scan_order) {
- kfree(devpriv->ao_scan_order);
- }
+ kfree(devpriv->ao_readback);
+ kfree(devpriv->ao_scan_vals);
+ kfree(devpriv->ao_scan_order);
if (devpriv->pci_dev) {
if (dev->iobase) {
comedi_pci_disable(devpriv->pci_dev);
diff --git a/drivers/staging/comedi/drivers/c6xdigio.c b/drivers/staging/comedi/drivers/c6xdigio.c
index abb0532182b..fb0d5fa7176 100644
--- a/drivers/staging/comedi/drivers/c6xdigio.c
+++ b/drivers/staging/comedi/drivers/c6xdigio.c
@@ -45,7 +45,7 @@ http://robot0.ge.uiuc.edu/~spong/mecha/
#include <linux/interrupt.h>
#include <linux/timex.h>
#include <linux/timer.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <linux/pnp.h>
#include "../comedidev.h"
@@ -220,11 +220,11 @@ static int C6X_encInput(unsigned long baseAddr, unsigned channel)
/* printk("Inside C6X_encInput\n"); */
enc.value = 0;
- if (channel == 0) {
+ if (channel == 0)
ppcmd = 0x48;
- } else {
+ else
ppcmd = 0x50;
- }
+
WriteByteToHwPort(baseAddr, ppcmd);
tmp = ReadByteFromHwPort(baseAddr + 1);
while (((tmp & 0x80) == 0) && (timeout < C6XDIGIO_TIME_OUT)) {
@@ -391,9 +391,8 @@ static int c6xdigio_ei_insn_read(struct comedi_device *dev,
int n;
int chan = CR_CHAN(insn->chanspec);
- for (n = 0; n < insn->n; n++) {
+ for (n = 0; n < insn->n; n++)
data[n] = (C6X_encInput(dev->iobase, chan) & 0xffffff);
- }
return n;
}
@@ -420,9 +419,9 @@ static void board_init(struct comedi_device *dev)
static const struct pnp_device_id c6xdigio_pnp_tbl[] = {
/* Standard LPT Printer Port */
- {.id = "PNP0400",.driver_data = 0},
+ {.id = "PNP0400", .driver_data = 0},
/* ECP Printer Port */
- {.id = "PNP0401",.driver_data = 0},
+ {.id = "PNP0401", .driver_data = 0},
{}
};
@@ -452,15 +451,14 @@ static int c6xdigio_attach(struct comedi_device *dev,
if (result < 0)
return result;
- /* Make sure that PnP ports gets activated */
+ /* Make sure that PnP ports get activated */
pnp_register_driver(&c6xdigio_pnp_driver);
irq = it->options[1];
- if (irq > 0) {
+ if (irq > 0)
printk("comedi%d: irq = %u ignored\n", dev->minor, irq);
- } else if (irq == 0) {
+ else if (irq == 0)
printk("comedi%d: no irq\n", dev->minor);
- }
s = dev->subdevices + 0;
/* pwm output subdevice */
@@ -483,19 +481,19 @@ static int c6xdigio_attach(struct comedi_device *dev,
s->maxdata = 0xffffff;
s->range_table = &range_unknown;
- /* s = dev->subdevices + 2; */
+ /* s = dev->subdevices + 2; */
/* pwm output subdevice */
- /* s->type = COMEDI_SUBD_COUNTER; // Not sure what to put here */
- /* s->subdev_flags = SDF_WRITEABLE; */
- /* s->n_chan = 1; */
- /* s->trig[0] = c6xdigio_ei_init; */
- /* s->insn_read = c6xdigio_ei_init_insn_read; */
- /* s->insn_write = c6xdigio_ei_init_insn_write; */
- /* s->maxdata = 0xFFFF; // Really just a don't care */
- /* s->range_table = &range_unknown; // Not sure what to put here */
-
- /* I will call this init anyway but more than likely the DSP board will not be connect */
- /* when device driver is loaded. */
+ /* s->type = COMEDI_SUBD_COUNTER; // Not sure what to put here */
+ /* s->subdev_flags = SDF_WRITEABLE; */
+ /* s->n_chan = 1; */
+ /* s->trig[0] = c6xdigio_ei_init; */
+ /* s->insn_read = c6xdigio_ei_init_insn_read; */
+ /* s->insn_write = c6xdigio_ei_init_insn_write; */
+ /* s->maxdata = 0xFFFF; // Really just a don't care */
+ /* s->range_table = &range_unknown; // Not sure what to put here */
+
+ /* I will call this init anyway but more than likely the DSP board */
+ /* will not be connected when device driver is loaded. */
board_init(dev);
return 0;
@@ -503,16 +501,17 @@ static int c6xdigio_attach(struct comedi_device *dev,
static int c6xdigio_detach(struct comedi_device *dev)
{
-/* board_halt(dev); may not need this */
+ /* board_halt(dev); may not need this */
printk("comedi%d: c6xdigio: remove\n", dev->minor);
- if (dev->iobase) {
+ if (dev->iobase)
release_region(dev->iobase, C6XDIGIO_SIZE);
- }
- if (dev->irq) {
+
+ /* Not using IRQ so I am not sure if I need this */
+ if (dev->irq)
free_irq(dev->irq, dev);
- } /* Not using IRQ so I am not sure if I need this */
+
pnp_unregister_driver(&c6xdigio_pnp_driver);
return 0;
diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c
index f3e66c440a3..434591de37c 100644
--- a/drivers/staging/comedi/drivers/cb_pcidas.c
+++ b/drivers/staging/comedi/drivers/cb_pcidas.c
@@ -518,7 +518,7 @@ static int trimpot_7376_write(struct comedi_device *dev, uint8_t value);
static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel,
uint8_t value);
static int nvram_read(struct comedi_device *dev, unsigned int address,
- uint8_t * data);
+ uint8_t *data);
static inline unsigned int cal_enable_bits(struct comedi_device *dev)
{
@@ -760,9 +760,8 @@ static int cb_pcidas_detach(struct comedi_device *dev)
if (dev->subdevices)
subdev_8255_cleanup(dev, dev->subdevices + 2);
if (devpriv && devpriv->pci_dev) {
- if (devpriv->s5933_config) {
+ if (devpriv->s5933_config)
comedi_pci_disable(devpriv->pci_dev);
- }
pci_dev_put(devpriv->pci_dev);
}
@@ -1248,9 +1247,8 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev,
cmd->flags & TRIG_ROUND_MASK);
/* set number of conversions */
- if (cmd->stop_src == TRIG_COUNT) {
+ if (cmd->stop_src == TRIG_COUNT)
devpriv->count = cmd->chanlist_len * cmd->stop_arg;
- }
/* enable interrupts */
spin_lock_irqsave(&dev->spinlock, flags);
devpriv->adc_fifo_bits |= INTE;
@@ -1449,9 +1447,8 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev,
devpriv->ao_divisor2, 2);
}
/* set number of conversions */
- if (cmd->stop_src == TRIG_COUNT) {
+ if (cmd->stop_src == TRIG_COUNT)
devpriv->ao_count = cmd->chanlist_len * cmd->stop_arg;
- }
/* set pacer source */
spin_lock_irqsave(&dev->spinlock, flags);
switch (cmd->scan_begin_src) {
@@ -1494,9 +1491,8 @@ static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
num_points * sizeof(short));
num_points = num_bytes / sizeof(short);
- if (cmd->stop_src == TRIG_COUNT) {
+ if (cmd->stop_src == TRIG_COUNT)
devpriv->ao_count -= num_points;
- }
/* write data to board's fifo */
outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, num_bytes);
@@ -1534,9 +1530,8 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
static const int timeout = 10000;
unsigned long flags;
- if (dev->attached == 0) {
+ if (dev->attached == 0)
return IRQ_NONE;
- }
async = s->async;
async->events = 0;
@@ -1558,15 +1553,13 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
status = inw(devpriv->control_status + INT_ADCFIFO);
#ifdef CB_PCIDAS_DEBUG
- if ((status & (INT | EOAI | LADFUL | DAHFI | DAEMI)) == 0) {
+ if ((status & (INT | EOAI | LADFUL | DAHFI | DAEMI)) == 0)
comedi_error(dev, "spurious interrupt");
- }
#endif
/* check for analog output interrupt */
- if (status & (DAHFI | DAEMI)) {
+ if (status & (DAHFI | DAEMI))
handle_ao_interrupt(dev, status);
- }
/* check for analog input interrupts */
/* if fifo half-full */
if (status & ADHFI) {
@@ -1675,9 +1668,8 @@ static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status)
num_points * sizeof(short));
num_points = num_bytes / sizeof(short);
- if (async->cmd.stop_src == TRIG_COUNT) {
+ if (async->cmd.stop_src == TRIG_COUNT)
devpriv->ao_count -= num_points;
- }
/* write data to board's fifo */
outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer,
num_points);
@@ -1852,7 +1844,7 @@ static int wait_for_nvram_ready(unsigned long s5933_base_addr)
}
static int nvram_read(struct comedi_device *dev, unsigned int address,
- uint8_t * data)
+ uint8_t *data)
{
unsigned long iobase = devpriv->s5933_config;
diff --git a/drivers/staging/comedi/drivers/cb_pcidda.c b/drivers/staging/comedi/drivers/cb_pcidda.c
index 782357732ee..81829d6fd28 100644
--- a/drivers/staging/comedi/drivers/cb_pcidda.c
+++ b/drivers/staging/comedi/drivers/cb_pcidda.c
@@ -410,9 +410,8 @@ static int cb_pcidda_detach(struct comedi_device *dev)
*/
if (devpriv) {
if (devpriv->pci_dev) {
- if (devpriv->dac) {
+ if (devpriv->dac)
comedi_pci_disable(devpriv->pci_dev);
- }
pci_dev_put(devpriv->pci_dev);
}
}
@@ -677,9 +676,8 @@ static unsigned int cb_pcidda_serial_in(struct comedi_device *dev)
for (i = 1; i <= value_width; i++) {
/* read bits most significant bit first */
- if (inw_p(devpriv->dac + DACALIBRATION1) & SERIAL_OUT_BIT) {
+ if (inw_p(devpriv->dac + DACALIBRATION1) & SERIAL_OUT_BIT)
value |= 1 << (value_width - i);
- }
}
return value;
@@ -716,9 +714,8 @@ static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
/* send serial output stream to eeprom */
cal2_bits = SELECT_EEPROM_BIT | DESELECT_REF_DAC_BIT | DUMMY_BIT;
/* deactivate caldacs (one caldac for every two channels) */
- for (i = 0; i < max_num_caldacs; i++) {
+ for (i = 0; i < max_num_caldacs; i++)
cal2_bits |= DESELECT_CALDAC_BIT(i);
- }
outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
/* tell eeprom we want to read */
@@ -756,9 +753,8 @@ static void cb_pcidda_write_caldac(struct comedi_device *dev,
*/
cal2_bits = DESELECT_REF_DAC_BIT | DUMMY_BIT;
/* deactivate caldacs (one caldac for every two channels) */
- for (i = 0; i < max_num_caldacs; i++) {
+ for (i = 0; i < max_num_caldacs; i++)
cal2_bits |= DESELECT_CALDAC_BIT(i);
- }
/* activate the caldac we want */
cal2_bits &= ~DESELECT_CALDAC_BIT(caldac);
outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c
index 7daad0a17fb..38ccd105fa3 100644
--- a/drivers/staging/comedi/drivers/cb_pcidio.c
+++ b/drivers/staging/comedi/drivers/cb_pcidio.c
@@ -283,17 +283,15 @@ static int pcidio_detach(struct comedi_device *dev)
printk("comedi%d: cb_pcidio: remove\n", dev->minor);
if (devpriv) {
if (devpriv->pci_dev) {
- if (devpriv->dio_reg_base) {
+ if (devpriv->dio_reg_base)
comedi_pci_disable(devpriv->pci_dev);
- }
pci_dev_put(devpriv->pci_dev);
}
}
if (dev->subdevices) {
int i;
- for (i = 0; i < thisboard->n_8255; i++) {
+ for (i = 0; i < thisboard->n_8255; i++)
subdev_8255_cleanup(dev, dev->subdevices + i);
- }
}
return 0;
}
diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
index cbbca05acb9..2e61727fc9a 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
@@ -330,11 +330,10 @@ found:
s = dev->subdevices + 2;
/* digital i/o subdevice */
- if (thisboard->has_dio) {
+ if (thisboard->has_dio)
subdev_8255_init(dev, s, NULL, devpriv->BADR4);
- } else {
+ else
s->type = COMEDI_SUBD_UNUSED;
- }
printk("attached\n");
@@ -365,9 +364,8 @@ static int cb_pcimdas_detach(struct comedi_device *dev)
free_irq(dev->irq, dev);
if (devpriv) {
if (devpriv->pci_dev) {
- if (devpriv->BADR0) {
+ if (devpriv->BADR0)
comedi_pci_disable(devpriv->pci_dev);
- }
pci_dev_put(devpriv->pci_dev);
}
}
diff --git a/drivers/staging/comedi/drivers/cb_pcimdda.c b/drivers/staging/comedi/drivers/cb_pcimdda.c
index 980fa0aacf9..e32a31763d5 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdda.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdda.c
@@ -284,11 +284,10 @@ static int attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->n_chan = thisboard->ao_chans;
s->maxdata = figure_out_maxdata(thisboard->ao_bits);
/* this is hard-coded here */
- if (it->options[2]) {
+ if (it->options[2])
s->range_table = &range_bipolar10;
- } else {
+ else
s->range_table = &range_bipolar5;
- }
s->insn_write = &ao_winsn;
s->insn_read = &ao_rinsn;
@@ -337,9 +336,8 @@ static int detach(struct comedi_device *dev)
}
if (devpriv->pci_dev) {
- if (devpriv->registers) {
+ if (devpriv->registers)
comedi_pci_disable(devpriv->pci_dev);
- }
pci_dev_put(devpriv->pci_dev);
}
diff --git a/drivers/staging/comedi/drivers/comedi_bond.c b/drivers/staging/comedi/drivers/comedi_bond.c
index cf39a24ddd4..d7260cc8698 100644
--- a/drivers/staging/comedi/drivers/comedi_bond.c
+++ b/drivers/staging/comedi/drivers/comedi_bond.c
@@ -417,7 +417,7 @@ static int doDevConfig(struct comedi_device *dev, struct comedi_devconfig *it)
int sdev = -1, nchans, tmp;
struct BondedDevice *bdev = NULL;
- if (minor < 0 || minor > COMEDI_NUM_BOARD_MINORS) {
+ if (minor < 0 || minor >= COMEDI_NUM_BOARD_MINORS) {
ERROR("Minor %d is invalid!\n", minor);
return 0;
}
diff --git a/drivers/staging/comedi/drivers/contec_pci_dio.c b/drivers/staging/comedi/drivers/contec_pci_dio.c
index b16d652f776..9511814e641 100644
--- a/drivers/staging/comedi/drivers/contec_pci_dio.c
+++ b/drivers/staging/comedi/drivers/contec_pci_dio.c
@@ -173,9 +173,8 @@ static int contec_detach(struct comedi_device *dev)
printk("comedi%d: contec: remove\n", dev->minor);
if (devpriv && devpriv->pci_dev) {
- if (dev->iobase) {
+ if (dev->iobase)
comedi_pci_disable(devpriv->pci_dev);
- }
pci_dev_put(devpriv->pci_dev);
}
diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
index 9b945e5fdd3..f12ef1cd6f5 100644
--- a/drivers/staging/comedi/drivers/das08_cs.c
+++ b/drivers/staging/comedi/drivers/das08_cs.c
@@ -34,7 +34,7 @@ This is the PCMCIA-specific support split off from the
das08 driver.
Options (for pcm-das08):
- NONE
+ NONE
Command support does not exist, but could be added for this board.
*/
@@ -52,7 +52,7 @@ Command support does not exist, but could be added for this board.
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
-static struct pcmcia_device *cur_dev = NULL;
+static struct pcmcia_device *cur_dev;
#define thisboard ((const struct das08_board_struct *)dev->board_ptr)
diff --git a/drivers/staging/comedi/drivers/das6402.c b/drivers/staging/comedi/drivers/das6402.c
index 92487f58fd8..a404a183191 100644
--- a/drivers/staging/comedi/drivers/das6402.c
+++ b/drivers/staging/comedi/drivers/das6402.c
@@ -45,7 +45,7 @@ This driver has suffered bitrot.
#define DAS6402_SIZE 16
-#define N_WORDS 3000*64
+#define N_WORDS (3000*64)
#define STOP 0
#define START 1
diff --git a/drivers/staging/comedi/drivers/das800.c b/drivers/staging/comedi/drivers/das800.c
index ecb97cdbce2..aadc4971c90 100644
--- a/drivers/staging/comedi/drivers/das800.c
+++ b/drivers/staging/comedi/drivers/das800.c
@@ -399,9 +399,8 @@ static irqreturn_t das800_interrupt(int irq, void *d)
} else {
fifo_empty = 0; /* cio-das802/16 has no fifo empty status bit */
}
- if (fifo_empty) {
+ if (fifo_empty)
break;
- }
/* strip off extraneous bits for 12 bit cards */
if (thisboard->resolution == 12)
dataPoint = (dataPoint >> 4) & 0xfff;
@@ -457,9 +456,8 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
int board;
printk("comedi%d: das800: io 0x%lx", dev->minor, iobase);
- if (irq) {
+ if (irq)
printk(", irq %u", irq);
- }
printk("\n");
/* allocate and initialize dev->private */
diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
index 9db9a467c8f..d5cbd515c37 100644
--- a/drivers/staging/comedi/drivers/dmm32at.c
+++ b/drivers/staging/comedi/drivers/dmm32at.c
@@ -1048,11 +1048,10 @@ static int dmm32at_dio_insn_config(struct comedi_device *dev,
* value COMEDI_INPUT or COMEDI_OUTPUT. */
/* if output clear the bit, otherwise set it */
- if (data[0] == COMEDI_OUTPUT) {
+ if (data[0] == COMEDI_OUTPUT)
devpriv->dio_config &= ~chanbit;
- } else {
+ else
devpriv->dio_config |= chanbit;
- }
/* get access to the DIO regs */
dmm_outb(dev, DMM32AT_CNTRL, DMM32AT_DIOACC);
/* set the DIO's to the new configuration setting */
diff --git a/drivers/staging/comedi/drivers/dt2801.c b/drivers/staging/comedi/drivers/dt2801.c
index 7b9af5d755e..3f365aee482 100644
--- a/drivers/staging/comedi/drivers/dt2801.c
+++ b/drivers/staging/comedi/drivers/dt2801.c
@@ -18,10 +18,10 @@ Configuration options:
[1] - unused
[2] - A/D reference 0=differential, 1=single-ended
[3] - A/D range
- 0 = [-10,10]
+ 0 = [-10, 10]
1 = [0,10]
[4] - D/A 0 range
- 0 = [-10,10]
+ 0 = [-10, 10]
1 = [-5,5]
2 = [-2.5,2.5]
3 = [0,10]
@@ -279,9 +279,8 @@ static int dt2801_readdata(struct comedi_device *dev, int *data)
do {
stat = inb_p(dev->iobase + DT2801_STATUS);
- if (stat & (DT_S_COMPOSITE_ERROR | DT_S_READY)) {
+ if (stat & (DT_S_COMPOSITE_ERROR | DT_S_READY))
return stat;
- }
if (stat & DT_S_DATA_OUT_READY) {
*data = inb_p(dev->iobase + DT2801_DATA);
return 0;
@@ -315,9 +314,8 @@ static int dt2801_writedata(struct comedi_device *dev, unsigned int data)
do {
stat = inb_p(dev->iobase + DT2801_STATUS);
- if (stat & DT_S_COMPOSITE_ERROR) {
+ if (stat & DT_S_COMPOSITE_ERROR)
return stat;
- }
if (!(stat & DT_S_DATA_IN_FULL)) {
outb_p(data & 0xff, dev->iobase + DT2801_DATA);
return 0;
@@ -354,18 +352,15 @@ static int dt2801_wait_for_ready(struct comedi_device *dev)
int stat;
stat = inb_p(dev->iobase + DT2801_STATUS);
- if (stat & DT_S_READY) {
+ if (stat & DT_S_READY)
return 0;
- }
do {
stat = inb_p(dev->iobase + DT2801_STATUS);
- if (stat & DT_S_COMPOSITE_ERROR) {
+ if (stat & DT_S_COMPOSITE_ERROR)
return stat;
- }
- if (stat & DT_S_READY) {
+ if (stat & DT_S_READY)
return 0;
- }
} while (--timeout > 0);
return -ETIME;
@@ -382,9 +377,8 @@ static int dt2801_writecmd(struct comedi_device *dev, int command)
printk
("dt2801: composite-error in dt2801_writecmd(), ignoring\n");
}
- if (!(stat & DT_S_READY)) {
+ if (!(stat & DT_S_READY))
printk("dt2801: !ready in dt2801_writecmd(), ignoring\n");
- }
outb_p(command, dev->iobase + DT2801_CMD);
return 0;
@@ -418,9 +412,8 @@ static int dt2801_reset(struct comedi_device *dev)
if (stat & DT_S_READY)
break;
} while (timeout--);
- if (!timeout) {
+ if (!timeout)
printk("dt2801: timeout 1 status=0x%02x\n", stat);
- }
/* printk("dt2801: reading dummy\n"); */
/* dt2801_readdata(dev,&board_code); */
@@ -436,9 +429,8 @@ static int dt2801_reset(struct comedi_device *dev)
if (stat & DT_S_READY)
break;
} while (timeout--);
- if (!timeout) {
+ if (!timeout)
printk("dt2801: timeout 2 status=0x%02x\n", stat);
- }
DPRINTK("dt2801: reading code\n");
dt2801_readdata(dev, &board_code);
@@ -623,11 +615,10 @@ static int dt2801_detach(struct comedi_device *dev)
static int dt2801_error(struct comedi_device *dev, int stat)
{
if (stat < 0) {
- if (stat == -ETIME) {
+ if (stat == -ETIME)
printk("dt2801: timeout\n");
- } else {
+ else
printk("dt2801: error %d\n", stat);
- }
return stat;
}
printk("dt2801: error status 0x%02x, resetting...\n", stat);
diff --git a/drivers/staging/comedi/drivers/dt2815.c b/drivers/staging/comedi/drivers/dt2815.c
index d1db93c043a..d1a4f782243 100644
--- a/drivers/staging/comedi/drivers/dt2815.c
+++ b/drivers/staging/comedi/drivers/dt2815.c
@@ -34,19 +34,19 @@ Configuration options:
[0] - I/O port base base address
[1] - IRQ (unused)
[2] - Voltage unipolar/bipolar configuration
- 0 == unipolar 5V (0V -- +5V)
- 1 == bipolar 5V (-5V -- +5V)
+ 0 == unipolar 5V (0V -- +5V)
+ 1 == bipolar 5V (-5V -- +5V)
[3] - Current offset configuration
- 0 == disabled (0mA -- +32mAV)
- 1 == enabled (+4mA -- +20mAV)
+ 0 == disabled (0mA -- +32mAV)
+ 1 == enabled (+4mA -- +20mAV)
[4] - Firmware program configuration
- 0 == program 1 (see manual table 5-4)
- 1 == program 2 (see manual table 5-4)
- 2 == program 3 (see manual table 5-4)
- 3 == program 4 (see manual table 5-4)
+ 0 == program 1 (see manual table 5-4)
+ 1 == program 2 (see manual table 5-4)
+ 2 == program 3 (see manual table 5-4)
+ 3 == program 4 (see manual table 5-4)
[5] - Analog output 0 range configuration
- 0 == voltage
- 1 == current
+ 0 == voltage
+ 1 == current
[6] - Analog output 1 range configuration (same options)
[7] - Analog output 2 range configuration (same options)
[8] - Analog output 3 range configuration (same options)
@@ -61,17 +61,11 @@ Configuration options:
#include <linux/ioport.h>
#include <linux/delay.h>
-static const struct comedi_lrange range_dt2815_ao_32_current = { 1, {
- RANGE_mA(0,
- 32)
- }
-};
+static const struct comedi_lrange
+ range_dt2815_ao_32_current = {1, {RANGE_mA(0, 32)} };
-static const struct comedi_lrange range_dt2815_ao_20_current = { 1, {
- RANGE_mA(4,
- 20)
- }
-};
+static const struct comedi_lrange
+ range_dt2815_ao_20_current = {1, {RANGE_mA(4, 20)} };
#define DT2815_SIZE 2
@@ -118,9 +112,8 @@ static int dt2815_ao_insn_read(struct comedi_device *dev,
int i;
int chan = CR_CHAN(insn->chanspec);
- for (i = 0; i < insn->n; i++) {
+ for (i = 0; i < insn->n; i++)
data[i] = devpriv->ao_readback[chan];
- }
return i;
}
@@ -139,9 +132,8 @@ static int dt2815_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
status = dt2815_wait_for_status(dev, 0x00);
if (status != 0) {
- printk
- ("dt2815: failed to write low byte on %d reason %x\n",
- chan, status);
+ printk(KERN_WARNING "dt2815: failed to write low byte "
+ "on %d reason %x\n", chan, status);
return -EBUSY;
}
@@ -149,9 +141,8 @@ static int dt2815_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
status = dt2815_wait_for_status(dev, 0x10);
if (status != 0x10) {
- printk
- ("dt2815: failed to write high byte on %d reason %x\n",
- chan, status);
+ printk(KERN_WARNING "dt2815: failed to write high byte "
+ "on %d reason %x\n", chan, status);
return -EBUSY;
}
devpriv->ao_readback[chan] = data[i];
@@ -163,24 +154,24 @@ static int dt2815_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
options[0] Board base address
options[1] IRQ (not applicable)
options[2] Voltage unipolar/bipolar configuration
- 0 == unipolar 5V (0V -- +5V)
- 1 == bipolar 5V (-5V -- +5V)
+ 0 == unipolar 5V (0V -- +5V)
+ 1 == bipolar 5V (-5V -- +5V)
options[3] Current offset configuration
- 0 == disabled (0mA -- +32mAV)
- 1 == enabled (+4mA -- +20mAV)
+ 0 == disabled (0mA -- +32mAV)
+ 1 == enabled (+4mA -- +20mAV)
options[4] Firmware program configuration
- 0 == program 1 (see manual table 5-4)
- 1 == program 2 (see manual table 5-4)
- 2 == program 3 (see manual table 5-4)
- 3 == program 4 (see manual table 5-4)
+ 0 == program 1 (see manual table 5-4)
+ 1 == program 2 (see manual table 5-4)
+ 2 == program 3 (see manual table 5-4)
+ 3 == program 4 (see manual table 5-4)
options[5] Analog output 0 range configuration
- 0 == voltage
- 1 == current
+ 0 == voltage
+ 1 == current
options[6] Analog output 1 range configuration
...
options[12] Analog output 7 range configuration
- 0 == voltage
- 1 == current
+ 0 == voltage
+ 1 == current
*/
static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it)
@@ -191,9 +182,9 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it)
unsigned long iobase;
iobase = it->options[0];
- printk("comedi%d: dt2815: 0x%04lx ", dev->minor, iobase);
+ printk(KERN_INFO "comedi%d: dt2815: 0x%04lx ", dev->minor, iobase);
if (!request_region(iobase, DT2815_SIZE, "dt2815")) {
- printk("I/O port conflict\n");
+ printk(KERN_WARNING "I/O port conflict\n");
return -EIO;
}
@@ -236,19 +227,17 @@ static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it)
unsigned int program;
program = (it->options[4] & 0x3) << 3 | 0x7;
outb(program, dev->iobase + DT2815_DATA);
- printk(", program: 0x%x (@t=%d)\n", program, i);
+ printk(KERN_INFO ", program: 0x%x (@t=%d)\n",
+ program, i);
break;
} else if (status != 0x00) {
- printk("dt2815: unexpected status 0x%x (@t=%d)\n",
- status, i);
- if (status & 0x60) {
+ printk(KERN_WARNING "dt2815: unexpected status 0x%x "
+ "(@t=%d)\n", status, i);
+ if (status & 0x60)
outb(0x00, dev->iobase + DT2815_STATUS);
- }
}
}
- printk("\n");
-
return 0;
}
@@ -260,7 +249,7 @@ static void dt2815_free_resources(struct comedi_device *dev)
static int dt2815_detach(struct comedi_device *dev)
{
- printk("comedi%d: dt2815: remove\n", dev->minor);
+ printk(KERN_INFO "comedi%d: dt2815: remove\n", dev->minor);
dt2815_free_resources(dev);
diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c
index 312f4f282bd..96caae36279 100644
--- a/drivers/staging/comedi/drivers/dt9812.c
+++ b/drivers/staging/comedi/drivers/dt9812.c
@@ -264,7 +264,7 @@ struct dt9812_usb_cmd {
static DECLARE_MUTEX(dt9812_mutex);
-static struct usb_device_id dt9812_table[] = {
+static const struct usb_device_id dt9812_table[] = {
{USB_DEVICE(0x0867, 0x9812)},
{} /* Terminating entry */
};
diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c
index 8fca1804335..a10a2b070a2 100644
--- a/drivers/staging/comedi/drivers/fl512.c
+++ b/drivers/staging/comedi/drivers/fl512.c
@@ -76,14 +76,14 @@ static int fl512_ai_insn(struct comedi_device *dev,
unsigned long iobase = dev->iobase;
for (n = 0; n < insn->n; n++) { /* sample n times on selected channel */
- /* XXX probably can move next step out of for() loop -- will make
- * AI a little bit faster. */
+ /* XXX probably can move next step out of for() loop -- will
+ * make AI a little bit faster. */
outb(chan, iobase + 2); /* select chan */
outb(0, iobase + 3); /* start conversion */
/* XXX should test "done" flag instead of delay */
udelay(30); /* sleep 30 usec */
lo_byte = inb(iobase + 2); /* low 8 byte */
- hi_byte = inb(iobase + 3) & 0xf; /* high 4 bit and mask */
+ hi_byte = inb(iobase + 3) & 0xf; /* high 4 bit and mask */
data[n] = lo_byte + (hi_byte << 8);
}
return n;
@@ -101,8 +101,10 @@ static int fl512_ao_insn(struct comedi_device *dev,
unsigned long iobase = dev->iobase; /* get base address */
for (n = 0; n < insn->n; n++) { /* write n data set */
- outb(data[n] & 0x0ff, iobase + 4 + 2 * chan); /* write low byte */
- outb((data[n] & 0xf00) >> 8, iobase + 4 + 2 * chan); /* write high byte */
+ /* write low byte */
+ outb(data[n] & 0x0ff, iobase + 4 + 2 * chan);
+ /* write high byte */
+ outb((data[n] & 0xf00) >> 8, iobase + 4 + 2 * chan);
inb(iobase + 4 + 2 * chan); /* trig */
devpriv->ao_readback[chan] = data[n];
@@ -121,9 +123,8 @@ static int fl512_ao_insn_readback(struct comedi_device *dev,
int n;
int chan = CR_CHAN(insn->chanspec);
- for (n = 0; n < insn->n; n++) {
+ for (n = 0; n < insn->n; n++)
data[n] = devpriv->ao_readback[chan];
- }
return n;
}
@@ -134,13 +135,15 @@ static int fl512_ao_insn_readback(struct comedi_device *dev,
static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
unsigned long iobase;
- struct comedi_subdevice *s; /* pointer to the subdevice:
- Analog in, Analog out, ( not made ->and Digital IO) */
+
+ /* pointer to the subdevice: Analog in, Analog out,
+ (not made ->and Digital IO) */
+ struct comedi_subdevice *s;
iobase = it->options[0];
- printk("comedi:%d fl512: 0x%04lx", dev->minor, iobase);
+ printk(KERN_INFO "comedi:%d fl512: 0x%04lx", dev->minor, iobase);
if (!request_region(iobase, FL512_SIZE, "fl512")) {
- printk(" I/O port conflict\n");
+ printk(KERN_WARNING " I/O port conflict\n");
return -EIO;
}
dev->iobase = iobase;
@@ -149,7 +152,7 @@ static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it)
return -ENOMEM;
#if DEBUG
- printk("malloc ok\n");
+ printk(KERN_DEBUG "malloc ok\n");
#endif
if (alloc_subdevices(dev, 2) < 0)
@@ -160,24 +163,37 @@ static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it)
*/
/* Analog indput */
s = dev->subdevices + 0;
- s->type = COMEDI_SUBD_AI; /* define subdevice as Analog In */
- s->subdev_flags = SDF_READABLE | SDF_GROUND; /* you can read it from userspace */
- s->n_chan = 16; /* Number of Analog input channels */
- s->maxdata = 0x0fff; /* accept only 12 bits of data */
- s->range_table = &range_fl512; /* device use one of the ranges */
- s->insn_read = fl512_ai_insn; /* function to call when read AD */
- printk("comedi: fl512: subdevice 0 initialized\n");
+ /* define subdevice as Analog In */
+ s->type = COMEDI_SUBD_AI;
+ /* you can read it from userspace */
+ s->subdev_flags = SDF_READABLE | SDF_GROUND;
+ /* Number of Analog input channels */
+ s->n_chan = 16;
+ /* accept only 12 bits of data */
+ s->maxdata = 0x0fff;
+ /* device use one of the ranges */
+ s->range_table = &range_fl512;
+ /* function to call when read AD */
+ s->insn_read = fl512_ai_insn;
+ printk(KERN_INFO "comedi: fl512: subdevice 0 initialized\n");
/* Analog output */
s = dev->subdevices + 1;
- s->type = COMEDI_SUBD_AO; /* define subdevice as Analog OUT */
- s->subdev_flags = SDF_WRITABLE; /* you can write it from userspace */
- s->n_chan = 2; /* Number of Analog output channels */
- s->maxdata = 0x0fff; /* accept only 12 bits of data */
- s->range_table = &range_fl512; /* device use one of the ranges */
- s->insn_write = fl512_ao_insn; /* function to call when write DA */
- s->insn_read = fl512_ao_insn_readback; /* function to call when reading DA */
- printk("comedi: fl512: subdevice 1 initialized\n");
+ /* define subdevice as Analog OUT */
+ s->type = COMEDI_SUBD_AO;
+ /* you can write it from userspace */
+ s->subdev_flags = SDF_WRITABLE;
+ /* Number of Analog output channels */
+ s->n_chan = 2;
+ /* accept only 12 bits of data */
+ s->maxdata = 0x0fff;
+ /* device use one of the ranges */
+ s->range_table = &range_fl512;
+ /* function to call when write DA */
+ s->insn_write = fl512_ao_insn;
+ /* function to call when reading DA */
+ s->insn_read = fl512_ao_insn_readback;
+ printk(KERN_INFO "comedi: fl512: subdevice 1 initialized\n");
return 1;
}
@@ -186,6 +202,6 @@ static int fl512_detach(struct comedi_device *dev)
{
if (dev->iobase)
release_region(dev->iobase, FL512_SIZE);
- printk("comedi%d: fl512: dummy i detach\n", dev->minor);
+ printk(KERN_INFO "comedi%d: fl512: dummy i detach\n", dev->minor);
return 0;
}
diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c
index bd397840dcb..fe5b4953f7e 100644
--- a/drivers/staging/comedi/drivers/jr3_pci.c
+++ b/drivers/staging/comedi/drivers/jr3_pci.c
@@ -954,6 +954,8 @@ out:
return result;
}
+MODULE_FIRMWARE("comedi/jr3pci.idm");
+
static int jr3_pci_detach(struct comedi_device *dev)
{
int i;
diff --git a/drivers/staging/comedi/drivers/mpc624.c b/drivers/staging/comedi/drivers/mpc624.c
index cb4da2ae842..12e72c82815 100644
--- a/drivers/staging/comedi/drivers/mpc624.c
+++ b/drivers/staging/comedi/drivers/mpc624.c
@@ -284,7 +284,7 @@ static int mpc624_ai_rinsn(struct comedi_device *dev,
outb(insn->chanspec, dev->iobase + MPC624_GNMUXCH);
/* printk("Channel %d: \n", insn->chanspec); */
if (!insn->n) {
- printk("MPC624: Warning, no data to aquire\n");
+ printk("MPC624: Warning, no data to acquire\n");
return 0;
}
diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
index bbf75eb6d7f..c223f76031f 100644
--- a/drivers/staging/comedi/drivers/ni_65xx.c
+++ b/drivers/staging/comedi/drivers/ni_65xx.c
@@ -26,12 +26,13 @@
/*
Driver: ni_65xx
Description: National Instruments 65xx static dio boards
-Author: Jon Grierson <jd@renko.co.uk>, Frank Mori Hess <fmhess@users.sourceforge.net>
+Author: Jon Grierson <jd@renko.co.uk>,
+ Frank Mori Hess <fmhess@users.sourceforge.net>
Status: testing
-Devices: [National Instruments] PCI-6509 (ni_65xx), PXI-6509, PCI-6510, PCI-6511,
- PXI-6511, PCI-6512, PXI-6512, PCI-6513, PXI-6513, PCI-6514, PXI-6514, PCI-6515,
- PXI-6515, PCI-6516, PCI-6517, PCI-6518, PCI-6519, PCI-6520, PCI-6521, PXI-6521,
- PCI-6528, PXI-6528
+Devices: [National Instruments] PCI-6509 (ni_65xx), PXI-6509, PCI-6510,
+ PCI-6511, PXI-6511, PCI-6512, PXI-6512, PCI-6513, PXI-6513, PCI-6514,
+ PXI-6514, PCI-6515, PXI-6515, PCI-6516, PCI-6517, PCI-6518, PCI-6519,
+ PCI-6520, PCI-6521, PXI-6521, PCI-6528, PXI-6528
Updated: Wed Oct 18 08:59:11 EDT 2006
Based on the PCI-6527 driver by ds.
@@ -418,9 +419,10 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
return -EINVAL;
base_bitfield_channel = CR_CHAN(insn->chanspec);
for (j = 0; j < max_ports_per_bitfield; ++j) {
- const unsigned port_offset = ni_65xx_port_by_channel(base_bitfield_channel) + j;
+ const unsigned port_offset =
+ ni_65xx_port_by_channel(base_bitfield_channel) + j;
const unsigned port =
- sprivate(s)->base_port + port_offset;
+ sprivate(s)->base_port + port_offset;
unsigned base_port_channel;
unsigned port_mask, port_data, port_read_bits;
int bitshift;
@@ -463,11 +465,11 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev,
* subdevice.) */
port_read_bits ^= 0xFF;
}
- if (bitshift > 0) {
+ if (bitshift > 0)
port_read_bits <<= bitshift;
- } else {
+ else
port_read_bits >>= -bitshift;
- }
+
read_bits |= port_read_bits;
}
data[1] = read_bits;
@@ -532,7 +534,8 @@ static int ni_65xx_intr_cmdtest(struct comedi_device *dev,
if (err)
return 1;
- /* step 2: make sure trigger sources are unique and mutually compatible */
+ /* step 2: make sure trigger sources are unique and mutually
+ compatible */
if (err)
return 2;
@@ -652,7 +655,7 @@ static int ni_65xx_attach(struct comedi_device *dev,
unsigned i;
int ret;
- printk("comedi%d: ni_65xx:", dev->minor);
+ printk(KERN_INFO "comedi%d: ni_65xx:", dev->minor);
ret = alloc_private(dev, sizeof(struct ni_65xx_private));
if (ret < 0)
@@ -664,15 +667,15 @@ static int ni_65xx_attach(struct comedi_device *dev,
ret = mite_setup(private(dev)->mite);
if (ret < 0) {
- printk("error setting up mite\n");
+ printk(KERN_WARNING "error setting up mite\n");
return ret;
}
dev->board_name = board(dev)->name;
dev->irq = mite_irq(private(dev)->mite);
- printk(" %s", dev->board_name);
+ printk(KERN_INFO " %s", dev->board_name);
- printk(" ID=0x%02x",
+ printk(KERN_INFO " ID=0x%02x",
readb(private(dev)->mite->daq_io_addr + ID_Register));
ret = alloc_subdevices(dev, 4);
@@ -773,7 +776,7 @@ static int ni_65xx_attach(struct comedi_device *dev,
"ni_65xx", dev);
if (ret < 0) {
dev->irq = 0;
- printk(" irq not available");
+ printk(KERN_WARNING " irq not available");
}
printk("\n");
@@ -790,21 +793,17 @@ static int ni_65xx_detach(struct comedi_device *dev)
Master_Interrupt_Control);
}
- if (dev->irq) {
+ if (dev->irq)
free_irq(dev->irq, dev);
- }
if (private(dev)) {
unsigned i;
for (i = 0; i < dev->n_subdevices; ++i) {
- if (dev->subdevices[i].private) {
- kfree(dev->subdevices[i].private);
- dev->subdevices[i].private = NULL;
- }
+ kfree(dev->subdevices[i].private);
+ dev->subdevices[i].private = NULL;
}
- if (private(dev)->mite) {
+ if (private(dev)->mite)
mite_unsetup(private(dev)->mite);
- }
}
return 0;
}
@@ -830,7 +829,7 @@ static int ni_65xx_find_device(struct comedi_device *dev, int bus, int slot)
}
}
}
- printk("no device found\n");
+ printk(KERN_WARNING "no device found\n");
mite_list_devices();
return -EIO;
}
diff --git a/drivers/staging/comedi/drivers/ni_660x.c b/drivers/staging/comedi/drivers/ni_660x.c
index 404d3c516ed..017630fb242 100644
--- a/drivers/staging/comedi/drivers/ni_660x.c
+++ b/drivers/staging/comedi/drivers/ni_660x.c
@@ -52,7 +52,8 @@ enum ni_660x_constants {
};
#define NUM_PFI_CHANNELS 40
-/* really there are only up to 3 dma channels, but the register layout allows for 4 */
+/* really there are only up to 3 dma channels, but the register layout allows
+for 4 */
#define MAX_DMA_CHANNEL 4
/* See Register-Level Programmer Manual page 3.1 */
@@ -198,7 +199,7 @@ struct NI_660xRegisterData {
const char *name; /* Register Name */
int offset; /* Offset from base address from GPCT chip */
enum ni_660x_register_direction direction;
- enum ni_660x_register_width size; /* 1 byte, 2 bytes, or 4 bytes */
+ enum ni_660x_register_width size; /* 1 byte, 2 bytes, or 4 bytes */
};
static const struct NI_660xRegisterData registerData[NumRegisters] = {
@@ -382,8 +383,8 @@ enum global_interrupt_config_register_bits {
};
/* Offset of the GPCT chips from the base-adress of the card */
-static const unsigned GPCT_OFFSET[2] = { 0x0, 0x800 }; /* First chip is at base-address +
- 0x00, etc. */
+/* First chip is at base-address + 0x00, etc. */
+static const unsigned GPCT_OFFSET[2] = { 0x0, 0x800 };
/* Board description*/
struct ni_660x_board {
@@ -691,13 +692,13 @@ static enum NI_660x_Register ni_gpct_to_660x_register(enum ni_gpct_register reg)
ni_660x_register = G0StatusRegister;
break;
case NITIO_G1_Status_Reg:
- ni_660x_register = G0StatusRegister;
+ ni_660x_register = G1StatusRegister;
break;
case NITIO_G2_Status_Reg:
- ni_660x_register = G0StatusRegister;
+ ni_660x_register = G2StatusRegister;
break;
case NITIO_G3_Status_Reg:
- ni_660x_register = G0StatusRegister;
+ ni_660x_register = G3StatusRegister;
break;
case NITIO_G0_Interrupt_Enable_Reg:
ni_660x_register = G0InterruptEnable;
@@ -712,7 +713,7 @@ static enum NI_660x_Register ni_gpct_to_660x_register(enum ni_gpct_register reg)
ni_660x_register = G3InterruptEnable;
break;
default:
- printk("%s: unhandled register 0x%x in switch.\n",
+ printk(KERN_WARNING "%s: unhandled register 0x%x in switch.\n",
__func__, reg);
BUG();
return 0;
@@ -737,7 +738,7 @@ static inline void ni_660x_write_register(struct comedi_device *dev,
writel(bits, write_address);
break;
default:
- printk("%s: %s: bug! unhandled case (reg=0x%x) in switch.\n",
+ printk(KERN_WARNING "%s: %s: bug! unhandled case (reg=0x%x) in switch.\n",
__FILE__, __func__, reg);
BUG();
break;
@@ -760,7 +761,7 @@ static inline unsigned ni_660x_read_register(struct comedi_device *dev,
return readl(read_address);
break;
default:
- printk("%s: %s: bug! unhandled case (reg=0x%x) in switch.\n",
+ printk(KERN_WARNING "%s: %s: bug! unhandled case (reg=0x%x) in switch.\n",
__FILE__, __func__, reg);
BUG();
break;
@@ -993,9 +994,9 @@ static int ni_660x_allocate_private(struct comedi_device *dev)
spin_lock_init(&private(dev)->mite_channel_lock);
spin_lock_init(&private(dev)->interrupt_lock);
spin_lock_init(&private(dev)->soft_reg_copy_lock);
- for (i = 0; i < NUM_PFI_CHANNELS; ++i) {
+ for (i = 0; i < NUM_PFI_CHANNELS; ++i)
private(dev)->pfi_output_selects[i] = pfi_output_select_counter;
- }
+
return 0;
}
@@ -1008,9 +1009,8 @@ static int ni_660x_alloc_mite_rings(struct comedi_device *dev)
for (j = 0; j < counters_per_chip; ++j) {
private(dev)->mite_rings[i][j] =
mite_alloc_ring(private(dev)->mite);
- if (private(dev)->mite_rings[i][j] == NULL) {
+ if (private(dev)->mite_rings[i][j] == NULL)
return -ENOMEM;
- }
}
}
return 0;
@@ -1022,9 +1022,8 @@ static void ni_660x_free_mite_rings(struct comedi_device *dev)
unsigned j;
for (i = 0; i < board(dev)->n_chips; ++i) {
- for (j = 0; j < counters_per_chip; ++j) {
+ for (j = 0; j < counters_per_chip; ++j)
mite_free_ring(private(dev)->mite_rings[i][j]);
- }
}
}
@@ -1036,7 +1035,7 @@ static int ni_660x_attach(struct comedi_device *dev,
unsigned i;
unsigned global_interrupt_config_bits;
- printk("comedi%d: ni_660x: ", dev->minor);
+ printk(KERN_INFO "comedi%d: ni_660x: ", dev->minor);
ret = ni_660x_allocate_private(dev);
if (ret < 0)
@@ -1049,7 +1048,7 @@ static int ni_660x_attach(struct comedi_device *dev,
ret = mite_setup2(private(dev)->mite, 1);
if (ret < 0) {
- printk("error setting up mite\n");
+ printk(KERN_WARNING "error setting up mite\n");
return ret;
}
comedi_set_hw_dev(dev, &private(dev)->mite->pcidev->dev);
@@ -1057,7 +1056,7 @@ static int ni_660x_attach(struct comedi_device *dev,
if (ret < 0)
return ret;
- printk(" %s ", dev->board_name);
+ printk(KERN_INFO " %s ", dev->board_name);
dev->n_subdevices = 2 + NI_660X_MAX_NUM_COUNTERS;
@@ -1078,15 +1077,16 @@ static int ni_660x_attach(struct comedi_device *dev,
s->insn_bits = ni_660x_dio_insn_bits;
s->insn_config = ni_660x_dio_insn_config;
s->io_bits = 0; /* all bits default to input */
- /* we use the ioconfig registers to control dio direction, so zero output enables in stc dio control reg */
+ /* we use the ioconfig registers to control dio direction, so zero
+ output enables in stc dio control reg */
ni_660x_write_register(dev, 0, 0, STCDIOControl);
private(dev)->counter_dev = ni_gpct_device_construct(dev,
- &ni_gpct_write_register,
- &ni_gpct_read_register,
- ni_gpct_variant_660x,
- ni_660x_num_counters
- (dev));
+ &ni_gpct_write_register,
+ &ni_gpct_read_register,
+ ni_gpct_variant_660x,
+ ni_660x_num_counters
+ (dev));
if (private(dev)->counter_dev == NULL)
return -ENOMEM;
for (i = 0; i < NI_660X_MAX_NUM_COUNTERS; ++i) {
@@ -1118,12 +1118,12 @@ static int ni_660x_attach(struct comedi_device *dev,
s->type = COMEDI_SUBD_UNUSED;
}
}
- for (i = 0; i < board(dev)->n_chips; ++i) {
+ for (i = 0; i < board(dev)->n_chips; ++i)
init_tio_chip(dev, i);
- }
- for (i = 0; i < ni_660x_num_counters(dev); ++i) {
+
+ for (i = 0; i < ni_660x_num_counters(dev); ++i)
ni_tio_init_counter(&private(dev)->counter_dev->counters[i]);
- }
+
for (i = 0; i < NUM_PFI_CHANNELS; ++i) {
if (i < min_counter_pfi_chan)
ni_660x_set_pfi_routing(dev, i, pfi_output_select_do);
@@ -1134,13 +1134,13 @@ static int ni_660x_attach(struct comedi_device *dev,
}
/* to be safe, set counterswap bits on tio chips after all the counter
outputs have been set to high impedance mode */
- for (i = 0; i < board(dev)->n_chips; ++i) {
+ for (i = 0; i < board(dev)->n_chips; ++i)
set_tio_counterswap(dev, i);
- }
+
ret = request_irq(mite_irq(private(dev)->mite), ni_660x_interrupt,
IRQF_SHARED, "ni_660x", dev);
if (ret < 0) {
- printk(" irq not available\n");
+ printk(KERN_WARNING " irq not available\n");
return ret;
}
dev->irq = mite_irq(private(dev)->mite);
@@ -1149,13 +1149,13 @@ static int ni_660x_attach(struct comedi_device *dev,
global_interrupt_config_bits |= Cascade_Int_Enable_Bit;
ni_660x_write_register(dev, 0, global_interrupt_config_bits,
GlobalInterruptConfigRegister);
- printk("attached\n");
+ printk(KERN_INFO "attached\n");
return 0;
}
static int ni_660x_detach(struct comedi_device *dev)
{
- printk("comedi%d: ni_660x: remove\n", dev->minor);
+ printk(KERN_INFO "comedi%d: ni_660x: remove\n", dev->minor);
/* Free irq */
if (dev->irq)
@@ -1193,9 +1193,8 @@ static void init_tio_chip(struct comedi_device *dev, int chipset)
private(dev)->
dma_configuration_soft_copies[chipset],
DMAConfigRegister);
- for (i = 0; i < NUM_PFI_CHANNELS; ++i) {
+ for (i = 0; i < NUM_PFI_CHANNELS; ++i)
ni_660x_write_register(dev, chipset, 0, IOConfigReg(i));
- }
}
static int
@@ -1234,7 +1233,7 @@ static int ni_660x_find_device(struct comedi_device *dev, int bus, int slot)
}
}
}
- printk("no device found\n");
+ printk(KERN_WARNING "no device found\n");
mite_list_devices();
return -EIO;
}
diff --git a/drivers/staging/comedi/drivers/ni_670x.c b/drivers/staging/comedi/drivers/ni_670x.c
index 9b43547e80a..1e792d592f7 100644
--- a/drivers/staging/comedi/drivers/ni_670x.c
+++ b/drivers/staging/comedi/drivers/ni_670x.c
@@ -93,7 +93,7 @@ static DEFINE_PCI_DEVICE_TABLE(ni_670x_pci_table) = {
{
PCI_VENDOR_ID_NATINST, 0x2c90, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
PCI_VENDOR_ID_NATINST, 0x1920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- /* { PCI_VENDOR_ID_NATINST, 0x0000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */
+ /*{ PCI_VENDOR_ID_NATINST, 0x0000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },*/
{
0}
};
@@ -151,7 +151,7 @@ static int ni_670x_attach(struct comedi_device *dev,
int ret;
int i;
- printk("comedi%d: ni_670x: ", dev->minor);
+ printk(KERN_INFO "comedi%d: ni_670x: ", dev->minor);
ret = alloc_private(dev, sizeof(struct ni_670x_private));
if (ret < 0)
@@ -163,12 +163,12 @@ static int ni_670x_attach(struct comedi_device *dev,
ret = mite_setup(devpriv->mite);
if (ret < 0) {
- printk("error setting up mite\n");
+ printk(KERN_WARNING "error setting up mite\n");
return ret;
}
dev->board_name = thisboard->name;
dev->irq = mite_irq(devpriv->mite);
- printk(" %s", dev->board_name);
+ printk(KERN_INFO " %s", dev->board_name);
if (alloc_subdevices(dev, 2) < 0)
return -ENOMEM;
@@ -207,21 +207,22 @@ static int ni_670x_attach(struct comedi_device *dev,
s->insn_bits = ni_670x_dio_insn_bits;
s->insn_config = ni_670x_dio_insn_config;
- writel(0x10, devpriv->mite->daq_io_addr + MISC_CONTROL_OFFSET); /* Config of misc registers */
- writel(0x00, devpriv->mite->daq_io_addr + AO_CONTROL_OFFSET); /* Config of ao registers */
+ /* Config of misc registers */
+ writel(0x10, devpriv->mite->daq_io_addr + MISC_CONTROL_OFFSET);
+ /* Config of ao registers */
+ writel(0x00, devpriv->mite->daq_io_addr + AO_CONTROL_OFFSET);
- printk("attached\n");
+ printk(KERN_INFO "attached\n");
return 1;
}
static int ni_670x_detach(struct comedi_device *dev)
{
- printk("comedi%d: ni_670x: remove\n", dev->minor);
+ printk(KERN_INFO "comedi%d: ni_670x: remove\n", dev->minor);
+
+ kfree(dev->subdevices[0].range_table_list);
- if (dev->subdevices[0].range_table_list) {
- kfree(dev->subdevices[0].range_table_list);
- }
if (dev->private && devpriv->mite)
mite_unsetup(devpriv->mite);
@@ -250,8 +251,11 @@ static int ni_670x_ao_winsn(struct comedi_device *dev,
vch(15) : 30 | ich(31) : 31 */
for (i = 0; i < insn->n; i++) {
- writel(((chan & 15) << 1) | ((chan & 16) >> 4), devpriv->mite->daq_io_addr + AO_CHAN_OFFSET); /* First write in channel register which channel to use */
- writel(data[i], devpriv->mite->daq_io_addr + AO_VALUE_OFFSET); /* write channel value */
+ /* First write in channel register which channel to use */
+ writel(((chan & 15) << 1) | ((chan & 16) >> 4),
+ devpriv->mite->daq_io_addr + AO_CHAN_OFFSET);
+ /* write channel value */
+ writel(data[i], devpriv->mite->daq_io_addr + AO_VALUE_OFFSET);
devpriv->ao_readback[chan] = data[i];
}
@@ -344,7 +348,7 @@ static int ni_670x_find_device(struct comedi_device *dev, int bus, int slot)
}
}
}
- printk("no device found\n");
+ printk(KERN_INFO "no device found\n");
mite_list_devices();
return -EIO;
}
diff --git a/drivers/staging/comedi/drivers/ni_atmio.c b/drivers/staging/comedi/drivers/ni_atmio.c
index 8ead31164d5..003d00b595b 100644
--- a/drivers/staging/comedi/drivers/ni_atmio.c
+++ b/drivers/staging/comedi/drivers/ni_atmio.c
@@ -329,11 +329,11 @@ static uint16_t ni_atmio_win_in(struct comedi_device *dev, int addr)
}
static struct pnp_device_id device_ids[] = {
- {.id = "NIC1900",.driver_data = 0},
- {.id = "NIC2400",.driver_data = 0},
- {.id = "NIC2500",.driver_data = 0},
- {.id = "NIC2600",.driver_data = 0},
- {.id = "NIC2700",.driver_data = 0},
+ {.id = "NIC1900", .driver_data = 0},
+ {.id = "NIC2400", .driver_data = 0},
+ {.id = "NIC2500", .driver_data = 0},
+ {.id = "NIC2600", .driver_data = 0},
+ {.id = "NIC2700", .driver_data = 0},
{.id = ""}
};
@@ -362,9 +362,9 @@ static int ni_atmio_detach(struct comedi_device *dev)
if (dev->iobase)
release_region(dev->iobase, NI_SIZE);
- if (dev->irq) {
+ if (dev->irq)
free_irq(dev->irq, dev);
- }
+
if (devpriv->isapnp_dev)
pnp_device_detach(devpriv->isapnp_dev);
@@ -387,8 +387,8 @@ static int ni_isapnp_find_board(struct pnp_dev **dev)
if (pnp_device_attach(isapnp_dev) < 0) {
printk
- ("ni_atmio: %s found but already active, skipping.\n",
- ni_boards[i].name);
+ ("ni_atmio: %s found but already active, skipping.\n",
+ ni_boards[i].name);
continue;
}
if (pnp_activate_dev(isapnp_dev) < 0) {
@@ -496,9 +496,9 @@ static int ni_atmio_attach(struct comedi_device *dev,
/* generic E series stuff in ni_mio_common.c */
ret = ni_E_init(dev, it);
- if (ret < 0) {
+ if (ret < 0)
return ret;
- }
+
return 0;
}
@@ -509,16 +509,16 @@ static int ni_getboardtype(struct comedi_device *dev)
int i;
for (i = 0; i < n_ni_boards; i++) {
- if (ni_boards[i].device_id == device_id) {
+ if (ni_boards[i].device_id == device_id)
return i;
- }
+
}
- if (device_id == 255) {
+ if (device_id == 255)
printk(" can't find board\n");
- } else if (device_id == 0) {
+ else if (device_id == 0)
printk(" EEPROM read error (?) or device not found\n");
- } else {
+ else
printk(" unknown device ID %d -- contact author\n", device_id);
- }
+
return -1;
}
diff --git a/drivers/staging/comedi/drivers/ni_daq_700.c b/drivers/staging/comedi/drivers/ni_daq_700.c
index ef5e1183d47..c9b0395a610 100644
--- a/drivers/staging/comedi/drivers/ni_daq_700.c
+++ b/drivers/staging/comedi/drivers/ni_daq_700.c
@@ -76,13 +76,15 @@ struct dio700_board {
static const struct dio700_board dio700_boards[] = {
{
.name = "daqcard-700",
- .device_id = 0x4743, /* 0x10b is manufacturer id, 0x4743 is device id */
+ /* 0x10b is manufacturer id, 0x4743 is device id */
+ .device_id = 0x4743,
.bustype = pcmcia_bustype,
.have_dio = 1,
},
{
.name = "ni_daq_700",
- .device_id = 0x4743, /* 0x10b is manufacturer id, 0x4743 is device id */
+ /* 0x10b is manufacturer id, 0x4743 is device id */
+ .device_id = 0x4743,
.bustype = pcmcia_bustype,
.have_dio = 1,
},
@@ -309,11 +311,11 @@ int subdev_700_init(struct comedi_device *dev, struct comedi_subdevice *s,
return -ENOMEM;
CALLBACK_ARG = arg;
- if (cb == NULL) {
+ if (cb == NULL)
CALLBACK_FUNC = subdev_700_cb;
- } else {
+ else
CALLBACK_FUNC = cb;
- }
+
s->insn_bits = subdev_700_insn;
s->insn_config = subdev_700_insn_config;
@@ -345,12 +347,10 @@ int subdev_700_init_irq(struct comedi_device *dev, struct comedi_subdevice *s,
void subdev_700_cleanup(struct comedi_device *dev, struct comedi_subdevice *s)
{
- if (s->private) {
- if (subdevpriv->have_irq) {
- }
+ if (s->private)
+ if (subdevpriv->have_irq)
- kfree(s->private);
- }
+ kfree(s->private);
}
EXPORT_SYMBOL(subdev_700_init);
@@ -390,9 +390,9 @@ static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
printk("comedi%d: ni_daq_700: %s, io 0x%lx", dev->minor,
thisboard->name, iobase);
#ifdef incomplete
- if (irq) {
+ if (irq)
printk(", irq %u", irq);
- }
+
#endif
printk("\n");
diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c
index dc3f398cb3e..3c88caaa9da 100644
--- a/drivers/staging/comedi/drivers/ni_labpc.c
+++ b/drivers/staging/comedi/drivers/ni_labpc.c
@@ -90,8 +90,10 @@ NI manuals:
#define DRV_NAME "ni_labpc"
-#define LABPC_SIZE 32 /* size of io region used by board */
-#define LABPC_TIMER_BASE 500 /* 2 MHz master clock */
+/* size of io region used by board */
+#define LABPC_SIZE 32
+/* 2 MHz master clock */
+#define LABPC_TIMER_BASE 500
/* Registers for the lab-pc+ */
@@ -99,69 +101,110 @@ NI manuals:
#define COMMAND1_REG 0x0
#define ADC_GAIN_MASK (0x7 << 4)
#define ADC_CHAN_BITS(x) ((x) & 0x7)
-#define ADC_SCAN_EN_BIT 0x80 /* enables multi channel scans */
+/* enables multi channel scans */
+#define ADC_SCAN_EN_BIT 0x80
#define COMMAND2_REG 0x1
-#define PRETRIG_BIT 0x1 /* enable pretriggering (used in conjunction with SWTRIG) */
-#define HWTRIG_BIT 0x2 /* enable paced conversions on external trigger */
-#define SWTRIG_BIT 0x4 /* enable paced conversions */
-#define CASCADE_BIT 0x8 /* use two cascaded counters for pacing */
+/* enable pretriggering (used in conjunction with SWTRIG) */
+#define PRETRIG_BIT 0x1
+/* enable paced conversions on external trigger */
+#define HWTRIG_BIT 0x2
+/* enable paced conversions */
+#define SWTRIG_BIT 0x4
+/* use two cascaded counters for pacing */
+#define CASCADE_BIT 0x8
#define DAC_PACED_BIT(channel) (0x40 << ((channel) & 0x1))
#define COMMAND3_REG 0x2
-#define DMA_EN_BIT 0x1 /* enable dma transfers */
-#define DIO_INTR_EN_BIT 0x2 /* enable interrupts for 8255 */
-#define DMATC_INTR_EN_BIT 0x4 /* enable dma terminal count interrupt */
-#define TIMER_INTR_EN_BIT 0x8 /* enable timer interrupt */
-#define ERR_INTR_EN_BIT 0x10 /* enable error interrupt */
-#define ADC_FNE_INTR_EN_BIT 0x20 /* enable fifo not empty interrupt */
+/* enable dma transfers */
+#define DMA_EN_BIT 0x1
+/* enable interrupts for 8255 */
+#define DIO_INTR_EN_BIT 0x2
+/* enable dma terminal count interrupt */
+#define DMATC_INTR_EN_BIT 0x4
+/* enable timer interrupt */
+#define TIMER_INTR_EN_BIT 0x8
+/* enable error interrupt */
+#define ERR_INTR_EN_BIT 0x10
+/* enable fifo not empty interrupt */
+#define ADC_FNE_INTR_EN_BIT 0x20
#define ADC_CONVERT_REG 0x3
#define DAC_LSB_REG(channel) (0x4 + 2 * ((channel) & 0x1))
#define DAC_MSB_REG(channel) (0x5 + 2 * ((channel) & 0x1))
#define ADC_CLEAR_REG 0x8
#define DMATC_CLEAR_REG 0xa
#define TIMER_CLEAR_REG 0xc
-#define COMMAND6_REG 0xe /* 1200 boards only */
-#define ADC_COMMON_BIT 0x1 /* select ground or common-mode reference */
-#define ADC_UNIP_BIT 0x2 /* adc unipolar */
-#define DAC_UNIP_BIT(channel) (0x4 << ((channel) & 0x1)) /* dac unipolar */
-#define ADC_FHF_INTR_EN_BIT 0x20 /* enable fifo half full interrupt */
-#define A1_INTR_EN_BIT 0x40 /* enable interrupt on end of hardware count */
-#define ADC_SCAN_UP_BIT 0x80 /* scan up from channel zero instead of down to zero */
+/* 1200 boards only */
+#define COMMAND6_REG 0xe
+/* select ground or common-mode reference */
+#define ADC_COMMON_BIT 0x1
+/* adc unipolar */
+#define ADC_UNIP_BIT 0x2
+/* dac unipolar */
+#define DAC_UNIP_BIT(channel) (0x4 << ((channel) & 0x1))
+/* enable fifo half full interrupt */
+#define ADC_FHF_INTR_EN_BIT 0x20
+/* enable interrupt on end of hardware count */
+#define A1_INTR_EN_BIT 0x40
+/* scan up from channel zero instead of down to zero */
+#define ADC_SCAN_UP_BIT 0x80
#define COMMAND4_REG 0xf
-#define INTERVAL_SCAN_EN_BIT 0x1 /* enables 'interval' scanning */
-#define EXT_SCAN_EN_BIT 0x2 /* enables external signal on counter b1 output to trigger scan */
-#define EXT_CONVERT_OUT_BIT 0x4 /* chooses direction (output or input) for EXTCONV* line */
-#define ADC_DIFF_BIT 0x8 /* chooses differential inputs for adc (in conjunction with board jumper) */
+/* enables 'interval' scanning */
+#define INTERVAL_SCAN_EN_BIT 0x1
+/* enables external signal on counter b1 output to trigger scan */
+#define EXT_SCAN_EN_BIT 0x2
+/* chooses direction (output or input) for EXTCONV* line */
+#define EXT_CONVERT_OUT_BIT 0x4
+/* chooses differential inputs for adc (in conjunction with board jumper) */
+#define ADC_DIFF_BIT 0x8
#define EXT_CONVERT_DISABLE_BIT 0x10
-#define COMMAND5_REG 0x1c /* 1200 boards only, calibration stuff */
-#define EEPROM_WRITE_UNPROTECT_BIT 0x4 /* enable eeprom for write */
-#define DITHER_EN_BIT 0x8 /* enable dithering */
-#define CALDAC_LOAD_BIT 0x10 /* load calibration dac */
-#define SCLOCK_BIT 0x20 /* serial clock - rising edge writes, falling edge reads */
-#define SDATA_BIT 0x40 /* serial data bit for writing to eeprom or calibration dacs */
-#define EEPROM_EN_BIT 0x80 /* enable eeprom for read/write */
+/* 1200 boards only, calibration stuff */
+#define COMMAND5_REG 0x1c
+/* enable eeprom for write */
+#define EEPROM_WRITE_UNPROTECT_BIT 0x4
+/* enable dithering */
+#define DITHER_EN_BIT 0x8
+/* load calibration dac */
+#define CALDAC_LOAD_BIT 0x10
+/* serial clock - rising edge writes, falling edge reads */
+#define SCLOCK_BIT 0x20
+/* serial data bit for writing to eeprom or calibration dacs */
+#define SDATA_BIT 0x40
+/* enable eeprom for read/write */
+#define EEPROM_EN_BIT 0x80
#define INTERVAL_COUNT_REG 0x1e
#define INTERVAL_LOAD_REG 0x1f
#define INTERVAL_LOAD_BITS 0x1
/* read-only registers */
#define STATUS1_REG 0x0
-#define DATA_AVAIL_BIT 0x1 /* data is available in fifo */
-#define OVERRUN_BIT 0x2 /* overrun has occurred */
-#define OVERFLOW_BIT 0x4 /* fifo overflow */
-#define TIMER_BIT 0x8 /* timer interrupt has occured */
-#define DMATC_BIT 0x10 /* dma terminal count has occured */
-#define EXT_TRIG_BIT 0x40 /* external trigger has occured */
-#define STATUS2_REG 0x1d /* 1200 boards only */
-#define EEPROM_OUT_BIT 0x1 /* programmable eeprom serial output */
-#define A1_TC_BIT 0x2 /* counter A1 terminal count */
-#define FNHF_BIT 0x4 /* fifo not half full */
+/* data is available in fifo */
+#define DATA_AVAIL_BIT 0x1
+/* overrun has occurred */
+#define OVERRUN_BIT 0x2
+/* fifo overflow */
+#define OVERFLOW_BIT 0x4
+/* timer interrupt has occured */
+#define TIMER_BIT 0x8
+/* dma terminal count has occured */
+#define DMATC_BIT 0x10
+/* external trigger has occured */
+#define EXT_TRIG_BIT 0x40
+/* 1200 boards only */
+#define STATUS2_REG 0x1d
+/* programmable eeprom serial output */
+#define EEPROM_OUT_BIT 0x1
+/* counter A1 terminal count */
+#define A1_TC_BIT 0x2
+/* fifo not half full */
+#define FNHF_BIT 0x4
#define ADC_FIFO_REG 0xa
#define DIO_BASE_REG 0x10
#define COUNTER_A_BASE_REG 0x14
#define COUNTER_A_CONTROL_REG (COUNTER_A_BASE_REG + 0x3)
-#define INIT_A0_BITS 0x14 /* check modes put conversion pacer output in harmless state (a0 mode 2) */
-#define INIT_A1_BITS 0x70 /* put hardware conversion counter output in harmless state (a1 mode 0) */
+/* check modes put conversion pacer output in harmless state (a0 mode 2) */
+#define INIT_A0_BITS 0x14
+/* put hardware conversion counter output in harmless state (a1 mode 0) */
+#define INIT_A1_BITS 0x70
#define COUNTER_B_BASE_REG 0x18
static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it);
@@ -423,7 +466,7 @@ static const struct labpc_board_struct labpc_boards[] = {
.ai_scan_up = 1,
.memory_mapped_io = 1,
},
- /* dummy entry so pci board works when comedi_config is passed driver name */
+/* dummy entry so pci board works when comedi_config is passed driver name */
{
.name = DRV_NAME,
.bustype = pci_bustype,
@@ -436,8 +479,10 @@ static const struct labpc_board_struct labpc_boards[] = {
*/
#define thisboard ((struct labpc_board_struct *)dev->board_ptr)
-static const int dma_buffer_size = 0xff00; /* size in bytes of dma buffer */
-static const int sample_size = 2; /* 2 bytes per sample */
+/* size in bytes of dma buffer */
+static const int dma_buffer_size = 0xff00;
+/* 2 bytes per sample */
+static const int sample_size = 2;
#define devpriv ((struct labpc_private *)dev->private)
@@ -483,12 +528,10 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
printk("comedi%d: ni_labpc: %s, io 0x%lx", dev->minor, thisboard->name,
iobase);
- if (irq) {
+ if (irq)
printk(", irq %u", irq);
- }
- if (dma_chan) {
+ if (dma_chan)
printk(", dma %u", dma_chan);
- }
printk("\n");
if (iobase == 0) {
@@ -513,7 +556,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
devpriv->read_byte = labpc_inb;
devpriv->write_byte = labpc_outb;
}
- /* initialize board's command registers */
+ /* initialize board's command registers */
devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG);
devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG);
@@ -538,12 +581,12 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
}
dev->irq = irq;
- /* grab dma channel */
+ /* grab dma channel */
if (dma_chan > 3) {
printk(" invalid dma channel %u\n", dma_chan);
return -EINVAL;
} else if (dma_chan) {
- /* allocate dma buffer */
+ /* allocate dma buffer */
devpriv->dma_buffer =
kmalloc(dma_buffer_size, GFP_KERNEL | GFP_DMA);
if (devpriv->dma_buffer == NULL) {
@@ -575,7 +618,7 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
SDF_READABLE | SDF_GROUND | SDF_COMMON | SDF_DIFF | SDF_CMD_READ;
s->n_chan = 8;
s->len_chanlist = 8;
- s->maxdata = (1 << 12) - 1; /* 12 bit resolution */
+ s->maxdata = (1 << 12) - 1; /* 12 bit resolution */
s->range_table = thisboard->ai_range_table;
s->do_cmd = labpc_ai_cmd;
s->do_cmdtest = labpc_ai_cmdtest;
@@ -585,8 +628,11 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
/* analog output */
s = dev->subdevices + 1;
if (thisboard->has_ao) {
-/* Could provide command support, except it only has a one sample
- * hardware buffer for analog output and no underrun flag. */
+ /*
+ * Could provide command support, except it only has a
+ * one sample hardware buffer for analog output and no
+ * underrun flag.
+ */
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
s->n_chan = NUM_AO_CHAN;
@@ -608,7 +654,8 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
/* 8255 dio */
s = dev->subdevices + 2;
- /* if board uses io memory we have to give a custom callback function to the 8255 driver */
+ /* if board uses io memory we have to give a custom callback
+ * function to the 8255 driver */
if (thisboard->memory_mapped_io)
subdev_8255_init(dev, s, labpc_dio_mem_callback,
(unsigned long)(dev->iobase + DIO_BASE_REG));
@@ -640,14 +687,12 @@ int labpc_common_attach(struct comedi_device *dev, unsigned long iobase,
s->insn_read = labpc_eeprom_read_insn;
s->insn_write = labpc_eeprom_write_insn;
- for (i = 0; i < EEPROM_SIZE; i++) {
+ for (i = 0; i < EEPROM_SIZE; i++)
devpriv->eeprom_data[i] = labpc_eeprom_read(dev, i);
- }
#ifdef LABPC_DEBUG
printk(" eeprom:");
- for (i = 0; i < EEPROM_SIZE; i++) {
+ for (i = 0; i < EEPROM_SIZE; i++)
printk(" %i:0x%x ", i, devpriv->eeprom_data[i]);
- }
printk("\n");
#endif
} else
@@ -669,7 +714,7 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (alloc_private(dev, sizeof(struct labpc_private)) < 0)
return -ENOMEM;
- /* get base address, irq etc. based on bustype */
+ /* get base address, irq etc. based on bustype */
switch (thisboard->bustype) {
case isa_bustype:
iobase = it->options[0];
@@ -679,9 +724,8 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
case pci_bustype:
#ifdef CONFIG_COMEDI_PCI
retval = labpc_find_device(dev, it->options[0], it->options[1]);
- if (retval < 0) {
+ if (retval < 0)
return retval;
- }
retval = mite_setup(devpriv->mite);
if (retval < 0)
return retval;
@@ -715,7 +759,7 @@ static int labpc_find_device(struct comedi_device *dev, int bus, int slot)
for (mite = mite_devices; mite; mite = mite->next) {
if (mite->used)
continue;
- /* if bus/slot are specified then make sure we have the right bus/slot */
+/* if bus/slot are specified then make sure we have the right bus/slot */
if (bus || slot) {
if (bus != mite->pcidev->bus->number
|| slot != PCI_SLOT(mite->pcidev->devfn))
@@ -726,7 +770,7 @@ static int labpc_find_device(struct comedi_device *dev, int bus, int slot)
continue;
if (mite_device_id(mite) == labpc_boards[i].device_id) {
devpriv->mite = mite;
- /* fixup board pointer, in case we were using the dummy "ni_labpc" entry */
+/* fixup board pointer, in case we were using the dummy "ni_labpc" entry */
dev->board_ptr = &labpc_boards[i];
return 0;
}
@@ -994,7 +1038,7 @@ static int labpc_ai_cmdtest(struct comedi_device *dev,
cmd->stop_src != TRIG_EXT && cmd->stop_src != TRIG_NONE)
err++;
- /* can't have external stop and start triggers at once */
+ /* can't have external stop and start triggers at once */
if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT)
err++;
@@ -1008,9 +1052,9 @@ static int labpc_ai_cmdtest(struct comedi_device *dev,
err++;
}
- if (!cmd->chanlist_len) {
+ if (!cmd->chanlist_len)
err++;
- }
+
if (cmd->scan_end_arg != cmd->chanlist_len) {
cmd->scan_end_arg = cmd->chanlist_len;
err++;
@@ -1022,7 +1066,7 @@ static int labpc_ai_cmdtest(struct comedi_device *dev,
err++;
}
}
- /* make sure scan timing is not too fast */
+ /* make sure scan timing is not too fast */
if (cmd->scan_begin_src == TRIG_TIMER) {
if (cmd->convert_src == TRIG_TIMER &&
cmd->scan_begin_arg <
@@ -1038,7 +1082,7 @@ static int labpc_ai_cmdtest(struct comedi_device *dev,
err++;
}
}
- /* stop source */
+ /* stop source */
switch (cmd->stop_src) {
case TRIG_COUNT:
if (!cmd->stop_arg) {
@@ -1095,7 +1139,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
range = CR_RANGE(cmd->chanlist[0]);
aref = CR_AREF(cmd->chanlist[0]);
- /* make sure board is disabled before setting up aquisition */
+ /* make sure board is disabled before setting up aquisition */
spin_lock_irqsave(&dev->spinlock, flags);
devpriv->command2_bits &= ~SWTRIG_BIT & ~HWTRIG_BIT & ~PRETRIG_BIT;
devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
@@ -1105,9 +1149,9 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG);
/* initialize software conversion count */
- if (cmd->stop_src == TRIG_COUNT) {
+ if (cmd->stop_src == TRIG_COUNT)
devpriv->count = cmd->stop_arg * cmd->chanlist_len;
- }
+
/* setup hardware conversion counter */
if (cmd->stop_src == TRIG_EXT) {
/* load counter a1 with count of 3 (pc+ manual says this is minimum allowed) using mode 0 */
@@ -1176,17 +1220,18 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
channel = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]);
else
channel = CR_CHAN(cmd->chanlist[0]);
- /* munge channel bits for differential / scan disabled mode */
+ /* munge channel bits for differential / scan disabled mode */
if (labpc_ai_scan_mode(cmd) != MODE_SINGLE_CHAN && aref == AREF_DIFF)
channel *= 2;
devpriv->command1_bits |= ADC_CHAN_BITS(channel);
devpriv->command1_bits |= thisboard->ai_range_code[range];
devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG);
- /* manual says to set scan enable bit on second pass */
+ /* manual says to set scan enable bit on second pass */
if (labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_UP ||
labpc_ai_scan_mode(cmd) == MODE_MULT_CHAN_DOWN) {
devpriv->command1_bits |= ADC_SCAN_EN_BIT;
- /* need a brief delay before enabling scan, or scan list will get screwed when you switch
+ /* need a brief delay before enabling scan, or scan
+ * list will get screwed when you switch
* between scan up to scan down mode - dunno why */
udelay(1);
devpriv->write_byte(devpriv->command1_bits,
@@ -1338,7 +1383,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d)
cmd = &async->cmd;
async->events = 0;
- /* read board status */
+ /* read board status */
devpriv->status1_bits = devpriv->read_byte(dev->iobase + STATUS1_REG);
if (thisboard->register_layout == labpc_1200_layout)
devpriv->status2_bits =
@@ -1352,7 +1397,7 @@ static irqreturn_t labpc_interrupt(int irq, void *d)
}
if (devpriv->status1_bits & OVERRUN_BIT) {
- /* clear error interrupt */
+ /* clear error interrupt */
devpriv->write_byte(0x1, dev->iobase + ADC_CLEAR_REG);
async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
comedi_event(dev, s);
@@ -1361,7 +1406,10 @@ static irqreturn_t labpc_interrupt(int irq, void *d)
}
if (devpriv->current_transfer == isa_dma_transfer) {
- /* if a dma terminal count of external stop trigger has occurred */
+ /*
+ * if a dma terminal count of external stop trigger
+ * has occurred
+ */
if (devpriv->status1_bits & DMATC_BIT ||
(thisboard->register_layout == labpc_1200_layout
&& devpriv->status2_bits & A1_TC_BIT)) {
@@ -1479,9 +1527,9 @@ static void labpc_drain_dma(struct comedi_device *dev)
}
/* write data to comedi buffer */
- for (i = 0; i < num_points; i++) {
+ for (i = 0; i < num_points; i++)
cfc_write_to_buffer(s, devpriv->dma_buffer[i]);
- }
+
if (async->cmd.stop_src == TRIG_COUNT)
devpriv->count -= num_points;
@@ -1503,7 +1551,7 @@ static void handle_isa_dma(struct comedi_device *dev)
devpriv->write_byte(0x1, dev->iobase + DMATC_CLEAR_REG);
}
-/* makes sure all data aquired by board is transfered to comedi (used
+/* makes sure all data acquired by board is transfered to comedi (used
* when aquisition is terminated by stop_src == TRIG_EXT). */
static void labpc_drain_dregs(struct comedi_device *dev)
{
@@ -1537,41 +1585,41 @@ static int labpc_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
chan = CR_CHAN(insn->chanspec);
range = CR_RANGE(insn->chanspec);
devpriv->command1_bits |= thisboard->ai_range_code[range];
- /* munge channel bits for differential/scan disabled mode */
+ /* munge channel bits for differential/scan disabled mode */
if (CR_AREF(insn->chanspec) == AREF_DIFF)
chan *= 2;
devpriv->command1_bits |= ADC_CHAN_BITS(chan);
devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG);
- /* setup command6 register for 1200 boards */
+ /* setup command6 register for 1200 boards */
if (thisboard->register_layout == labpc_1200_layout) {
/* reference inputs to ground or common? */
if (CR_AREF(insn->chanspec) != AREF_GROUND)
devpriv->command6_bits |= ADC_COMMON_BIT;
else
devpriv->command6_bits &= ~ADC_COMMON_BIT;
- /* bipolar or unipolar range? */
+ /* bipolar or unipolar range? */
if (thisboard->ai_range_is_unipolar[range])
devpriv->command6_bits |= ADC_UNIP_BIT;
else
devpriv->command6_bits &= ~ADC_UNIP_BIT;
- /* don't interrupt on fifo half full */
+ /* don't interrupt on fifo half full */
devpriv->command6_bits &= ~ADC_FHF_INTR_EN_BIT;
- /* don't enable interrupt on counter a1 terminal count? */
+ /* don't enable interrupt on counter a1 terminal count? */
devpriv->command6_bits &= ~A1_INTR_EN_BIT;
- /* write to register */
+ /* write to register */
devpriv->write_byte(devpriv->command6_bits,
dev->iobase + COMMAND6_REG);
}
- /* setup command4 register */
+ /* setup command4 register */
devpriv->command4_bits = 0;
devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT;
- /* single-ended/differential */
+ /* single-ended/differential */
if (CR_AREF(insn->chanspec) == AREF_DIFF)
devpriv->command4_bits |= ADC_DIFF_BIT;
devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG);
- /* initialize pacer counter output to make sure it doesn't cause any problems */
+ /* initialize pacer counter output to make sure it doesn't cause any problems */
devpriv->write_byte(INIT_A0_BITS, dev->iobase + COUNTER_A_CONTROL_REG);
labpc_clear_adc_fifo(dev);
@@ -1608,7 +1656,7 @@ static int labpc_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
channel = CR_CHAN(insn->chanspec);
- /* turn off pacing of analog output channel */
+ /* turn off pacing of analog output channel */
/* note: hardware bug in daqcard-1200 means pacing cannot
* be independently enabled/disabled for its the two channels */
spin_lock_irqsave(&dev->spinlock, flags);
@@ -1616,7 +1664,7 @@ static int labpc_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
devpriv->write_byte(devpriv->command2_bits, dev->iobase + COMMAND2_REG);
spin_unlock_irqrestore(&dev->spinlock, flags);
- /* set range */
+ /* set range */
if (thisboard->register_layout == labpc_1200_layout) {
range = CR_RANGE(insn->chanspec);
if (range & AO_RANGE_IS_UNIPOLAR)
@@ -1627,13 +1675,13 @@ static int labpc_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
devpriv->write_byte(devpriv->command6_bits,
dev->iobase + COMMAND6_REG);
}
- /* send data */
+ /* send data */
lsb = data[0] & 0xff;
msb = (data[0] >> 8) & 0xff;
devpriv->write_byte(lsb, dev->iobase + DAC_LSB_REG(channel));
devpriv->write_byte(msb, dev->iobase + DAC_MSB_REG(channel));
- /* remember value for readback */
+ /* remember value for readback */
devpriv->ao_value[channel] = data[0];
return 1;
@@ -1705,14 +1753,14 @@ static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd)
if (cmd.convert_src == TRIG_TIMER)
freq = 1000000000 / cmd.convert_arg;
- /* return some default value */
+ /* return some default value */
else
freq = 0xffffffff;
- /* make buffer fill in no more than 1/3 second */
+ /* make buffer fill in no more than 1/3 second */
size = (freq / 3) * sample_size;
- /* set a minimum and maximum size allowed */
+ /* set a minimum and maximum size allowed */
if (size > dma_buffer_size)
size = dma_buffer_size - dma_buffer_size % sample_size;
else if (size < sample_size)
@@ -1724,13 +1772,21 @@ static unsigned int labpc_suggest_transfer_size(struct comedi_cmd cmd)
/* figures out what counter values to use based on command */
static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd)
{
- const int max_counter_value = 0x10000; /* max value for 16 bit counter in mode 2 */
- const int min_counter_value = 2; /* min value for 16 bit counter in mode 2 */
+ /* max value for 16 bit counter in mode 2 */
+ const int max_counter_value = 0x10000;
+ /* min value for 16 bit counter in mode 2 */
+ const int min_counter_value = 2;
unsigned int base_period;
- /* if both convert and scan triggers are TRIG_TIMER, then they both rely on counter b0 */
+ /*
+ * if both convert and scan triggers are TRIG_TIMER, then they
+ * both rely on counter b0
+ */
if (labpc_ai_convert_period(cmd) && labpc_ai_scan_period(cmd)) {
- /* pick the lowest b0 divisor value we can (for maximum input clock speed on convert and scan counters) */
+ /*
+ * pick the lowest b0 divisor value we can (for maximum input
+ * clock speed on convert and scan counters)
+ */
devpriv->divisor_b0 = (labpc_ai_scan_period(cmd) - 1) /
(LABPC_TIMER_BASE * max_counter_value) + 1;
if (devpriv->divisor_b0 < min_counter_value)
@@ -1780,7 +1836,10 @@ static void labpc_adc_timing(struct comedi_device *dev, struct comedi_cmd *cmd)
base_period * devpriv->divisor_a0);
labpc_set_ai_scan_period(cmd,
base_period * devpriv->divisor_b1);
- /* if only one TRIG_TIMER is used, we can employ the generic cascaded timing functions */
+ /*
+ * if only one TRIG_TIMER is used, we can employ the generic
+ * cascaded timing functions
+ */
} else if (labpc_ai_scan_period(cmd)) {
unsigned int scan_period;
@@ -1864,9 +1923,8 @@ static unsigned int labpc_serial_in(struct comedi_device *dev)
udelay(1);
devpriv->status2_bits =
devpriv->read_byte(dev->iobase + STATUS2_REG);
- if (devpriv->status2_bits & EEPROM_OUT_BIT) {
+ if (devpriv->status2_bits & EEPROM_OUT_BIT)
value |= 1 << (value_width - i);
- }
}
return value;
@@ -1876,8 +1934,10 @@ static unsigned int labpc_eeprom_read(struct comedi_device *dev,
unsigned int address)
{
unsigned int value;
- const int read_instruction = 0x3; /* bits to tell eeprom to expect a read */
- const int write_length = 8; /* 8 bit write lengths to eeprom */
+ /* bits to tell eeprom to expect a read */
+ const int read_instruction = 0x3;
+ /* 8 bit write lengths to eeprom */
+ const int write_length = 8;
/* enable read/write to eeprom */
devpriv->command5_bits &= ~EEPROM_EN_BIT;
diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
index d6d49c3bbf1..bd16f913af2 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -3795,7 +3795,7 @@ static int ni_cdo_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
#endif
int retval = 0;
unsigned i;
- const unsigned timeout = 100;
+ const unsigned timeout = 1000;
s->async->inttrig = NULL;
diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c
index 2d88a5be65f..9d337516409 100644
--- a/drivers/staging/comedi/drivers/ni_pcidio.c
+++ b/drivers/staging/comedi/drivers/ni_pcidio.c
@@ -1,8 +1,8 @@
/*
comedi/drivers/ni_pcidio.c
driver for National Instruments PCI-DIO-96/PCI-6508
- National Instruments PCI-DIO-32HS
- National Instruments PCI-6503
+ National Instruments PCI-DIO-32HS
+ National Instruments PCI-6503
COMEDI - Linux Control and Measurement Device Interface
Copyright (C) 1999,2002 David A. Schleef <ds@schleef.org>
@@ -518,7 +518,8 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
ni_pcidio_print_status(status);
/* printk("buf[0]=%08x\n",*(unsigned int *)async->prealloc_buf); */
- /* printk("buf[4096]=%08x\n",*(unsigned int *)(async->prealloc_buf+4096)); */
+ /* printk("buf[4096]=%08x\n",
+ *(unsigned int *)(async->prealloc_buf+4096)); */
spin_lock_irqsave(&devpriv->mite_channel_lock, irq_flags);
if (devpriv->di_mite_chan)
@@ -526,7 +527,9 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
#ifdef MITE_DEBUG
mite_print_chsr(m_status);
#endif
- /* printk("mite_bytes_transferred: %d\n",mite_bytes_transferred(mite,DI_DMA_CHAN)); */
+ /* printk("mite_bytes_transferred: %d\n",
+ mite_bytes_transferred(mite,DI_DMA_CHAN)); */
+
/* mite_dump_regs(mite); */
if (m_status & CHSR_INT) {
if (m_status & CHSR_LINKC) {
@@ -565,7 +568,8 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
DPRINTK("too much work in interrupt\n");
writeb(0x00,
devpriv->mite->daq_io_addr +
- Master_DMA_And_Interrupt_Control);
+ Master_DMA_And_Interrupt_Control
+ );
goto out;
}
AuxData =
@@ -579,8 +583,10 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
flags = readb(devpriv->mite->daq_io_addr +
Group_1_Flags);
}
- /* DPRINTK("buf_int_count: %d\n",async->buf_int_count); */
- /* DPRINTK("1) IntEn=%d,flags=%d,status=%d\n",IntEn,flags,status); */
+ /* DPRINTK("buf_int_count: %d\n",
+ async->buf_int_count); */
+ /* DPRINTK("1) IntEn=%d,flags=%d,status=%d\n",
+ IntEn,flags,status); */
/* ni_pcidio_print_flags(flags); */
/* ni_pcidio_print_status(status); */
async->events |= COMEDI_CB_BLOCK;
@@ -627,8 +633,8 @@ static irqreturn_t nidio_interrupt(int irq, void *d)
flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags);
status = readb(devpriv->mite->daq_io_addr +
Interrupt_And_Window_Status);
- /* DPRINTK("loop end: IntEn=0x%02x,flags=0x%02x,status=0x%02x\n", */
- /* IntEn,flags,status); */
+ /* DPRINTK("loop end: IntEn=0x%02x,flags=0x%02x,"
+ "status=0x%02x\n", IntEn, flags, status); */
/* ni_pcidio_print_flags(flags); */
/* ni_pcidio_print_status(status); */
}
@@ -655,11 +661,10 @@ static void ni_pcidio_print_flags(unsigned int flags)
{
int i;
- printk("group_1_flags:");
+ printk(KERN_INFO "group_1_flags:");
for (i = 7; i >= 0; i--) {
- if (flags & (1 << i)) {
+ if (flags & (1 << i))
printk(" %s", flags_strings[i]);
- }
}
printk("\n");
}
@@ -673,11 +678,10 @@ static void ni_pcidio_print_status(unsigned int flags)
{
int i;
- printk("group_status:");
+ printk(KERN_INFO "group_status:");
for (i = 7; i >= 0; i--) {
- if (flags & (1 << i)) {
+ if (flags & (1 << i))
printk(" %s", status_strings[i]);
- }
}
printk("\n");
}
@@ -793,7 +797,8 @@ static int ni_pcidio_cmdtest(struct comedi_device *dev,
if (err)
return 1;
- /* step 2: make sure trigger sources are unique and mutually compatible */
+ /* step 2: make sure trigger sources are unique and mutually
+ compatible */
/* note that mutual compatibility is not an issue here */
if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_INT)
@@ -974,7 +979,8 @@ static int ni_pcidio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
/* clear and enable interrupts */
writeb(0xff, devpriv->mite->daq_io_addr + Group_1_First_Clear);
- /* writeb(ClearExpired,devpriv->mite->daq_io_addr+Group_1_Second_Clear); */
+ /* writeb(ClearExpired,
+ devpriv->mite->daq_io_addr+Group_1_Second_Clear); */
writeb(IntEn, devpriv->mite->daq_io_addr + Interrupt_Control);
writeb(0x03,
@@ -1052,7 +1058,7 @@ static int ni_pcidio_change(struct comedi_device *dev,
}
static int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index,
- u8 * data, int data_len)
+ u8 *data, int data_len)
{
static const int timeout = 1000;
int i, j;
@@ -1066,9 +1072,8 @@ static int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index,
udelay(1);
}
if (i == timeout) {
- printk
- ("ni_pcidio: failed to load fpga %i, waiting for status 0x2\n",
- fpga_index);
+ printk(KERN_WARNING "ni_pcidio: failed to load fpga %i, "
+ "waiting for status 0x2\n", fpga_index);
return -EIO;
}
writew(0x80 | fpga_index,
@@ -1079,9 +1084,8 @@ static int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index,
udelay(1);
}
if (i == timeout) {
- printk
- ("ni_pcidio: failed to load fpga %i, waiting for status 0x3\n",
- fpga_index);
+ printk(KERN_WARNING "ni_pcidio: failed to load fpga %i, "
+ "waiting for status 0x3\n", fpga_index);
return -EIO;
}
for (j = 0; j + 1 < data_len;) {
@@ -1174,9 +1178,10 @@ static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
int n_subdevices;
unsigned int irq;
- printk("comedi%d: nidio:", dev->minor);
+ printk(KERN_INFO "comedi%d: nidio:", dev->minor);
- if ((ret = alloc_private(dev, sizeof(struct nidio96_private))) < 0)
+ ret = alloc_private(dev, sizeof(struct nidio96_private));
+ if (ret < 0)
return ret;
spin_lock_init(&devpriv->mite_channel_lock);
@@ -1186,7 +1191,7 @@ static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
ret = mite_setup(devpriv->mite);
if (ret < 0) {
- printk("error setting up mite\n");
+ printk(KERN_WARNING "error setting up mite\n");
return ret;
}
comedi_set_hw_dev(dev, &devpriv->mite->pcidev->dev);
@@ -1196,18 +1201,19 @@ static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
dev->board_name = this_board->name;
irq = mite_irq(devpriv->mite);
- printk(" %s", dev->board_name);
+ printk(KERN_INFO " %s", dev->board_name);
if (this_board->uses_firmware) {
ret = pci_6534_upload_firmware(dev, it->options);
if (ret < 0)
return ret;
}
- if (!this_board->is_diodaq) {
+ if (!this_board->is_diodaq)
n_subdevices = this_board->n_8255;
- } else {
+ else
n_subdevices = 1;
- }
- if ((ret = alloc_subdevices(dev, n_subdevices)) < 0)
+
+ ret = alloc_subdevices(dev, n_subdevices);
+ if (ret < 0)
return ret;
if (!this_board->is_diodaq) {
@@ -1220,7 +1226,7 @@ static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
}
} else {
- printk(" rev=%d",
+ printk(KERN_INFO " rev=%d",
readb(devpriv->mite->daq_io_addr + Chip_Version));
s = dev->subdevices + 0;
@@ -1253,9 +1259,9 @@ static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
ret = request_irq(irq, nidio_interrupt, IRQF_SHARED,
"ni_pcidio", dev);
- if (ret < 0) {
- printk(" irq not available");
- }
+ if (ret < 0)
+ printk(KERN_WARNING " irq not available");
+
dev->irq = irq;
}
@@ -1269,9 +1275,8 @@ static int nidio_detach(struct comedi_device *dev)
int i;
if (this_board && !this_board->is_diodaq) {
- for (i = 0; i < this_board->n_8255; i++) {
+ for (i = 0; i < this_board->n_8255; i++)
subdev_8255_cleanup(dev, dev->subdevices + i);
- }
}
if (dev->irq)
@@ -1310,7 +1315,7 @@ static int nidio_find_device(struct comedi_device *dev, int bus, int slot)
}
}
}
- printk("no device found\n");
+ printk(KERN_WARNING "no device found\n");
mite_list_devices();
return -EIO;
}
diff --git a/drivers/staging/comedi/drivers/pcl711.c b/drivers/staging/comedi/drivers/pcl711.c
index 4914784f699..a499f7070f7 100644
--- a/drivers/staging/comedi/drivers/pcl711.c
+++ b/drivers/staging/comedi/drivers/pcl711.c
@@ -207,11 +207,10 @@ static irqreturn_t pcl711_interrupt(int irq, void *d)
/* FIXME! Nothing else sets ntrig! */
if (!(--devpriv->ntrig)) {
- if (this_board->is_8112) {
+ if (this_board->is_8112)
outb(1, dev->iobase + PCL711_MODE);
- } else {
+ else
outb(0, dev->iobase + PCL711_MODE);
- }
s->async->events |= COMEDI_CB_EOA;
}
@@ -232,15 +231,15 @@ static void pcl711_set_changain(struct comedi_device *dev, int chan)
/*
* Set the correct channel. The two channel banks are switched
* using the mask value.
- * NB: To use differential channels, you should use mask = 0x30,
- * but I haven't written the support for this yet. /JJ
+ * NB: To use differential channels, you should use
+ * mask = 0x30, but I haven't written the support for this
+ * yet. /JJ
*/
- if (chan_register >= 8) {
+ if (chan_register >= 8)
chan_register = 0x20 | (chan_register & 0x7);
- } else {
+ else
chan_register |= 0x10;
- }
} else {
outb(chan_register, dev->iobase + PCL711_MUX);
}
@@ -256,15 +255,13 @@ static int pcl711_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s,
for (n = 0; n < insn->n; n++) {
/*
- * Write the correct mode (software polling) and start polling by writing
- * to the trigger register
+ * Write the correct mode (software polling) and start polling
+ * by writing to the trigger register
*/
outb(1, dev->iobase + PCL711_MODE);
- if (this_board->is_8112) {
- } else {
+ if (!this_board->is_8112)
outb(0, dev->iobase + PCL711_SOFTTRIG);
- }
i = PCL711_TIMEOUT;
while (--i) {
@@ -462,9 +459,8 @@ static int pcl711_ao_insn_read(struct comedi_device *dev,
int n;
int chan = CR_CHAN(insn->chanspec);
- for (n = 0; n < insn->n; n++) {
+ for (n = 0; n < insn->n; n++)
data[n] = devpriv->ao_readback[chan];
- }
return n;
@@ -619,9 +615,8 @@ static int pcl711_attach(struct comedi_device *dev, struct comedi_devconfig *it)
this is the "base value" for the mode register, which is
used for the irq on the PCL711
*/
- if (this_board->is_pcl711b) {
+ if (this_board->is_pcl711b)
devpriv->mode = (dev->irq << 4);
- }
/* clear DAC */
outb(0, dev->iobase + PCL711_DA0_LO);
diff --git a/drivers/staging/comedi/drivers/pcl724.c b/drivers/staging/comedi/drivers/pcl724.c
index df1f4ef1461..0f103c32806 100644
--- a/drivers/staging/comedi/drivers/pcl724.c
+++ b/drivers/staging/comedi/drivers/pcl724.c
@@ -17,7 +17,7 @@
[0] - IO Base
[1] - IRQ (0=disable IRQ) IRQ isn't supported at this time!
[2] -number of DIO:
- 0, 144: 144 DIO configuration
+ 0, 144: 144 DIO configuration
1, 96: 96 DIO configuration
*/
/*
@@ -137,8 +137,8 @@ static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it)
iorange = this_board->io_range;
if ((this_board->can_have96) && ((it->options[1] == 1)
|| (it->options[1] == 96)))
- iorange = PCL722_96_SIZE; /* PCL-724 in 96 DIO configuration */
- printk("comedi%d: pcl724: board=%s, 0x%03lx ", dev->minor,
+ iorange = PCL722_96_SIZE; /* PCL-724 in 96 DIO configuration */
+ printk(KERN_INFO "comedi%d: pcl724: board=%s, 0x%03lx ", dev->minor,
this_board->name, iobase);
if (!request_region(iobase, iorange, "pcl724")) {
printk("I/O port conflict\n");
@@ -155,16 +155,16 @@ static int pcl724_attach(struct comedi_device *dev, struct comedi_devconfig *it)
irq = it->options[1];
if (irq) { /* we want to use IRQ */
if (((1 << irq) & this_board->IRQbits) == 0) {
- printk
- (", IRQ %u is out of allowed range, DISABLING IT",
- irq);
+ printk(KERN_WARNING
+ ", IRQ %u is out of allowed range, "
+ "DISABLING IT", irq);
irq = 0; /* Bad IRQ */
} else {
if (request_irq
(irq, interrupt_pcl724, 0, "pcl724", dev)) {
- printk
- (", unable to allocate IRQ %u, DISABLING IT",
- irq);
+ printk(KERN_WARNING
+ ", unable to allocate IRQ %u, "
+ "DISABLING IT", irq);
irq = 0; /* Can't use IRQ */
} else {
printk(", irq=%u", irq);
@@ -207,16 +207,14 @@ static int pcl724_detach(struct comedi_device *dev)
{
int i;
-/* printk("comedi%d: pcl724: remove\n",dev->minor); */
+ /* printk("comedi%d: pcl724: remove\n",dev->minor); */
- for (i = 0; i < dev->n_subdevices; i++) {
+ for (i = 0; i < dev->n_subdevices; i++)
subdev_8255_cleanup(dev, dev->subdevices + i);
- }
#ifdef PCL724_IRQ
- if (dev->irq) {
+ if (dev->irq)
free_irq(dev->irq, dev);
- }
#endif
release_region(dev->iobase, this_board->io_range);
diff --git a/drivers/staging/comedi/drivers/pcl725.c b/drivers/staging/comedi/drivers/pcl725.c
index 1da4941fce4..60261f4ba5b 100644
--- a/drivers/staging/comedi/drivers/pcl725.c
+++ b/drivers/staging/comedi/drivers/pcl725.c
@@ -66,7 +66,7 @@ static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it)
unsigned long iobase;
iobase = it->options[0];
- printk("comedi%d: pcl725: 0x%04lx ", dev->minor, iobase);
+ printk(KERN_INFO "comedi%d: pcl725: 0x%04lx ", dev->minor, iobase);
if (!request_region(iobase, PCL725_SIZE, "pcl725")) {
printk("I/O port conflict\n");
return -EIO;
@@ -96,14 +96,14 @@ static int pcl725_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->insn_bits = pcl725_di_insn;
s->range_table = &range_digital;
- printk("\n");
+ printk(KERN_INFO "\n");
return 0;
}
static int pcl725_detach(struct comedi_device *dev)
{
- printk("comedi%d: pcl725: remove\n", dev->minor);
+ printk(KERN_INFO "comedi%d: pcl725: remove\n", dev->minor);
if (dev->iobase)
release_region(dev->iobase, PCL725_SIZE);
diff --git a/drivers/staging/comedi/drivers/pcl730.c b/drivers/staging/comedi/drivers/pcl730.c
index c9859c90c15..e5e7bed21de 100644
--- a/drivers/staging/comedi/drivers/pcl730.c
+++ b/drivers/staging/comedi/drivers/pcl730.c
@@ -99,7 +99,7 @@ static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it)
iobase = it->options[0];
iorange = this_board->io_range;
- printk("comedi%d: pcl730: board=%s 0x%04lx ", dev->minor,
+ printk(KERN_INFO "comedi%d: pcl730: board=%s 0x%04lx ", dev->minor,
this_board->name, iobase);
if (!request_region(iobase, iorange, "pcl730")) {
printk("I/O port conflict\n");
@@ -152,14 +152,14 @@ static int pcl730_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->range_table = &range_digital;
s->private = (void *)PCL730_DIO_LO;
- printk("\n");
+ printk(KERN_INFO "\n");
return 0;
}
static int pcl730_detach(struct comedi_device *dev)
{
- printk("comedi%d: pcl730: remove\n", dev->minor);
+ printk(KERN_INFO "comedi%d: pcl730: remove\n", dev->minor);
if (dev->iobase)
release_region(dev->iobase, this_board->io_range);
diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
index 0a5bc3d6da8..d4634c4f02d 100644
--- a/drivers/staging/comedi/drivers/pcl812.c
+++ b/drivers/staging/comedi/drivers/pcl812.c
@@ -955,6 +955,7 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d)
unsigned int mask, timeout;
struct comedi_device *dev = d;
struct comedi_subdevice *s = dev->subdevices + 0;
+ unsigned int next_chan;
s->async->events = 0;
@@ -993,9 +994,18 @@ static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d)
((inb(dev->iobase + PCL812_AD_HI) << 8) |
inb(dev->iobase + PCL812_AD_LO)) & mask);
+ /* Set up next channel. Added by abbotti 2010-01-20, but untested. */
+ next_chan = s->async->cur_chan + 1;
+ if (next_chan >= devpriv->ai_n_chan)
+ next_chan = 0;
+ if (devpriv->ai_chanlist[s->async->cur_chan] !=
+ devpriv->ai_chanlist[next_chan])
+ setup_range_channel(dev, s, devpriv->ai_chanlist[next_chan], 0);
+
outb(0, dev->iobase + PCL812_CLRINT); /* clear INT request */
- if (s->async->cur_chan == 0) { /* one scan done */
+ s->async->cur_chan = next_chan;
+ if (next_chan == 0) { /* one scan done */
devpriv->ai_act_scan++;
if (!(devpriv->ai_neverending))
if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data sampled */
@@ -1021,7 +1031,9 @@ static void transfer_from_dma_buf(struct comedi_device *dev,
for (i = len; i; i--) {
comedi_buf_put(s->async, ptr[bufptr++]); /* get one sample */
- if (s->async->cur_chan == 0) {
+ s->async->cur_chan++;
+ if (s->async->cur_chan >= devpriv->ai_n_chan) {
+ s->async->cur_chan = 0;
devpriv->ai_act_scan++;
if (!devpriv->ai_neverending)
if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data sampled */
diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
index 852fe2458fd..9820759ec54 100644
--- a/drivers/staging/comedi/drivers/pcl816.c
+++ b/drivers/staging/comedi/drivers/pcl816.c
@@ -202,6 +202,7 @@ struct pcl816_private {
unsigned int ai_act_chanlist[16]; /* MUX setting for actual AI operations */
unsigned int ai_act_chanlist_len; /* how long is actual MUX list */
unsigned int ai_act_chanlist_pos; /* actual position in MUX list */
+ unsigned int ai_n_chan; /* how many channels per scan */
unsigned int ai_poll_ptr; /* how many sampes transfer poll */
struct comedi_subdevice *sub_ai; /* ptr to AI subdevice */
#ifdef unused
@@ -213,9 +214,12 @@ struct pcl816_private {
/*
==============================================================================
*/
-static int check_and_setup_channel_list(struct comedi_device *dev,
- struct comedi_subdevice *s,
- unsigned int *chanlist, int chanlen);
+static int check_channel_list(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned int *chanlist, unsigned int chanlen);
+static void setup_channel_list(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ unsigned int *chanlist, unsigned int seglen);
static int pcl816_ai_cancel(struct comedi_device *dev,
struct comedi_subdevice *s);
static void start_pacer(struct comedi_device *dev, int mode,
@@ -320,7 +324,9 @@ static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d)
if (++devpriv->ai_act_chanlist_pos >= devpriv->ai_act_chanlist_len)
devpriv->ai_act_chanlist_pos = 0;
- if (s->async->cur_chan == 0) {
+ s->async->cur_chan++;
+ if (s->async->cur_chan >= devpriv->ai_n_chan) {
+ s->async->cur_chan = 0;
devpriv->ai_act_scan++;
}
@@ -353,6 +359,11 @@ static void transfer_from_dma_buf(struct comedi_device *dev,
if (++devpriv->ai_act_chanlist_pos >=
devpriv->ai_act_chanlist_len) {
devpriv->ai_act_chanlist_pos = 0;
+ }
+
+ s->async->cur_chan++;
+ if (s->async->cur_chan >= devpriv->ai_n_chan) {
+ s->async->cur_chan = 0;
devpriv->ai_act_scan++;
}
@@ -558,14 +569,6 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev,
}
}
- if (!cmd->chanlist_len) {
- cmd->chanlist_len = 1;
- err++;
- }
- if (cmd->chanlist_len > this_board->n_aichan) {
- cmd->chanlist_len = this_board->n_aichan;
- err++;
- }
if (cmd->scan_end_arg != cmd->chanlist_len) {
cmd->scan_end_arg = cmd->chanlist_len;
err++;
@@ -603,6 +606,14 @@ static int pcl816_ai_cmdtest(struct comedi_device *dev,
return 4;
}
+ /* step 5: complain about special chanlist considerations */
+
+ if (cmd->chanlist) {
+ if (!check_channel_list(dev, s, cmd->chanlist,
+ cmd->chanlist_len))
+ return 5; /* incorrect channels list */
+ }
+
return 0;
}
@@ -610,6 +621,7 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
unsigned int divisor1 = 0, divisor2 = 0, dma_flags, bytes, dmairq;
struct comedi_cmd *cmd = &s->async->cmd;
+ unsigned int seglen;
if (cmd->start_src != TRIG_NOW)
return -EINVAL;
@@ -642,11 +654,13 @@ static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
start_pacer(dev, -1, 0, 0); /* stop pacer */
- if (!check_and_setup_channel_list(dev, s, cmd->chanlist,
- cmd->chanlist_len))
+ seglen = check_channel_list(dev, s, cmd->chanlist, cmd->chanlist_len);
+ if (seglen < 1)
return -EINVAL;
+ setup_channel_list(dev, s, cmd->chanlist, seglen);
udelay(1);
+ devpriv->ai_n_chan = cmd->chanlist_len;
devpriv->ai_act_scan = 0;
s->async->cur_chan = 0;
devpriv->irq_blocked = 1;
@@ -871,12 +885,12 @@ start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1,
/*
==============================================================================
Check if channel list from user is builded correctly
- If it's ok, then program scan/gain logic
+ If it's ok, then return non-zero length of repeated segment of channel list
*/
static int
-check_and_setup_channel_list(struct comedi_device *dev,
- struct comedi_subdevice *s, unsigned int *chanlist,
- int chanlen)
+check_channel_list(struct comedi_device *dev,
+ struct comedi_subdevice *s, unsigned int *chanlist,
+ unsigned int chanlen)
{
unsigned int chansegment[16];
unsigned int i, nowmustbechan, seglen, segpos;
@@ -930,6 +944,20 @@ check_and_setup_channel_list(struct comedi_device *dev,
seglen = 1;
}
+ return seglen; /* we can serve this with MUX logic */
+}
+
+/*
+==============================================================================
+ Program scan/gain logic with channel list.
+*/
+static void
+setup_channel_list(struct comedi_device *dev,
+ struct comedi_subdevice *s, unsigned int *chanlist,
+ unsigned int seglen)
+{
+ unsigned int i;
+
devpriv->ai_act_chanlist_len = seglen;
devpriv->ai_act_chanlist_pos = 0;
@@ -942,8 +970,6 @@ check_and_setup_channel_list(struct comedi_device *dev,
udelay(1);
outb(devpriv->ai_act_chanlist[0] | (devpriv->ai_act_chanlist[seglen - 1] << 4), dev->iobase + PCL816_MUX); /* select channel interval to scan */
-
- return 1; /* we can serve this with MUX logic */
}
#ifdef unused
diff --git a/drivers/staging/comedi/drivers/pcl818.c b/drivers/staging/comedi/drivers/pcl818.c
index d0481013a83..c9d75385755 100644
--- a/drivers/staging/comedi/drivers/pcl818.c
+++ b/drivers/staging/comedi/drivers/pcl818.c
@@ -557,8 +557,14 @@ conv_finish:
comedi_event(dev, s);
return IRQ_HANDLED;
}
- if (s->async->cur_chan == 0) {
+ devpriv->act_chanlist_pos++;
+ if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) {
+ devpriv->act_chanlist_pos = 0;
+ }
+ s->async->cur_chan++;
+ if (s->async->cur_chan >= devpriv->ai_n_chan) {
/* printk("E"); */
+ s->async->cur_chan = 0;
devpriv->ai_act_scan--;
}
@@ -627,9 +633,13 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
devpriv->act_chanlist_pos++;
if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) {
- devpriv->ai_act_scan--;
devpriv->act_chanlist_pos = 0;
}
+ s->async->cur_chan++;
+ if (s->async->cur_chan >= devpriv->ai_n_chan) {
+ s->async->cur_chan = 0;
+ devpriv->ai_act_scan--;
+ }
if (!devpriv->neverending_ai)
if (devpriv->ai_act_scan == 0) { /* all data sampled */
@@ -717,7 +727,14 @@ static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
comedi_buf_put(s->async, dmabuf[bufptr++] >> 4); /* get one sample */
bufptr &= (devpriv->dmasamplsize - 1);
- if (s->async->cur_chan == 0) {
+ devpriv->act_chanlist_pos++;
+ if (devpriv->act_chanlist_pos >=
+ devpriv->act_chanlist_len) {
+ devpriv->act_chanlist_pos = 0;
+ }
+ s->async->cur_chan++;
+ if (s->async->cur_chan >= devpriv->ai_n_chan) {
+ s->async->cur_chan = 0;
devpriv->ai_act_scan--;
}
@@ -796,7 +813,13 @@ static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
comedi_buf_put(s->async, (lo >> 4) | (inb(dev->iobase + PCL818_FI_DATAHI) << 4)); /* get one sample */
- if (s->async->cur_chan == 0) {
+ devpriv->act_chanlist_pos++;
+ if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) {
+ devpriv->act_chanlist_pos = 0;
+ }
+ s->async->cur_chan++;
+ if (s->async->cur_chan >= devpriv->ai_n_chan) {
+ s->async->cur_chan = 0;
devpriv->ai_act_scan--;
}
@@ -1369,14 +1392,6 @@ static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
}
}
- if (!cmd->chanlist_len) {
- cmd->chanlist_len = 1;
- err++;
- }
- if (cmd->chanlist_len > s->n_chan) {
- cmd->chanlist_len = s->n_chan;
- err++;
- }
if (cmd->scan_end_arg != cmd->chanlist_len) {
cmd->scan_end_arg = cmd->chanlist_len;
err++;
diff --git a/drivers/staging/comedi/drivers/pcm3724.c b/drivers/staging/comedi/drivers/pcm3724.c
index 52811824b05..ed610307923 100644
--- a/drivers/staging/comedi/drivers/pcm3724.c
+++ b/drivers/staging/comedi/drivers/pcm3724.c
@@ -121,25 +121,22 @@ static int compute_buffer(int config, int devno, struct comedi_subdevice *s)
{
/* 1 in io_bits indicates output */
if (s->io_bits & 0x0000ff) {
- if (devno == 0) {
+ if (devno == 0)
config |= BUF_A0;
- } else {
+ else
config |= BUF_A1;
- }
}
if (s->io_bits & 0x00ff00) {
- if (devno == 0) {
+ if (devno == 0)
config |= BUF_B0;
- } else {
+ else
config |= BUF_B1;
- }
}
if (s->io_bits & 0xff0000) {
- if (devno == 0) {
+ if (devno == 0)
config |= BUF_C0;
- } else {
+ else
config |= BUF_C1;
- }
}
return config;
}
@@ -155,26 +152,27 @@ static void do_3724_config(struct comedi_device *dev,
buffer_config = 0;
/* 1 in io_bits indicates output, 1 in config indicates input */
- if (!(s->io_bits & 0x0000ff)) {
+ if (!(s->io_bits & 0x0000ff))
config |= CR_A_IO;
- }
- if (!(s->io_bits & 0x00ff00)) {
+
+ if (!(s->io_bits & 0x00ff00))
config |= CR_B_IO;
- }
- if (!(s->io_bits & 0xff0000)) {
+
+ if (!(s->io_bits & 0xff0000))
config |= CR_C_IO;
- }
buffer_config = compute_buffer(0, 0, dev->subdevices);
buffer_config = compute_buffer(buffer_config, 1, (dev->subdevices) + 1);
- if (s == dev->subdevices) {
+ if (s == dev->subdevices)
port_8255_cfg = dev->iobase + _8255_CR;
- } else {
+ else
port_8255_cfg = dev->iobase + SIZE_8255 + _8255_CR;
- }
+
outb(buffer_config, dev->iobase + 8); /* update buffer register */
- /* printk("pcm3724 buffer_config (%lx) %d, %x\n", dev->iobase + _8255_CR, chanspec, buffer_config); */
+ /* printk("pcm3724 buffer_config (%lx) %d, %x\n",
+ dev->iobase + _8255_CR, chanspec, buffer_config); */
+
outb(config, port_8255_cfg);
}
@@ -189,29 +187,29 @@ static void enable_chan(struct comedi_device *dev, struct comedi_subdevice *s,
priv = (struct priv_pcm3724 *)(dev->private);
mask = 1 << CR_CHAN(chanspec);
- if (s == dev->subdevices) { /* subdev 0 */
+ if (s == dev->subdevices) /* subdev 0 */
priv->dio_1 |= mask;
- } else { /* subdev 1 */
+ else /* subdev 1 */
priv->dio_2 |= mask;
- }
- if (priv->dio_1 & 0xff0000) {
+
+ if (priv->dio_1 & 0xff0000)
gatecfg |= GATE_C0;
- }
- if (priv->dio_1 & 0xff00) {
+
+ if (priv->dio_1 & 0xff00)
gatecfg |= GATE_B0;
- }
- if (priv->dio_1 & 0xff) {
+
+ if (priv->dio_1 & 0xff)
gatecfg |= GATE_A0;
- }
- if (priv->dio_2 & 0xff0000) {
+
+ if (priv->dio_2 & 0xff0000)
gatecfg |= GATE_C1;
- }
- if (priv->dio_2 & 0xff00) {
+
+ if (priv->dio_2 & 0xff00)
gatecfg |= GATE_B1;
- }
- if (priv->dio_2 & 0xff) {
+
+ if (priv->dio_2 & 0xff)
gatecfg |= GATE_A1;
- }
+
/* printk("gate control %x\n", gatecfg); */
outb(gatecfg, dev->iobase + 9);
}
@@ -225,15 +223,14 @@ static int subdev_3724_insn_config(struct comedi_device *dev,
unsigned int bits;
mask = 1 << CR_CHAN(insn->chanspec);
- if (mask & 0x0000ff) {
+ if (mask & 0x0000ff)
bits = 0x0000ff;
- } else if (mask & 0x00ff00) {
+ else if (mask & 0x00ff00)
bits = 0x00ff00;
- } else if (mask & 0x0f0000) {
+ else if (mask & 0x0f0000)
bits = 0x0f0000;
- } else {
+ else
bits = 0xf00000;
- }
switch (data[0]) {
case INSN_CONFIG_DIO_INPUT:
@@ -272,7 +269,7 @@ static int pcm3724_attach(struct comedi_device *dev,
((struct priv_pcm3724 *)(dev->private))->dio_1 = 0;
((struct priv_pcm3724 *)(dev->private))->dio_2 = 0;
- printk("comedi%d: pcm3724: board=%s, 0x%03lx ", dev->minor,
+ printk(KERN_INFO "comedi%d: pcm3724: board=%s, 0x%03lx ", dev->minor,
this_board->name, iobase);
if (!iobase || !request_region(iobase, iorange, "pcm3724")) {
printk("I/O port conflict\n");
@@ -281,7 +278,7 @@ static int pcm3724_attach(struct comedi_device *dev,
dev->iobase = iobase;
dev->board_name = this_board->name;
- printk("\n");
+ printk(KERN_INFO "\n");
n_subdevices = this_board->numofports;
@@ -302,13 +299,11 @@ static int pcm3724_detach(struct comedi_device *dev)
int i;
if (dev->subdevices) {
- for (i = 0; i < dev->n_subdevices; i++) {
+ for (i = 0; i < dev->n_subdevices; i++)
subdev_8255_cleanup(dev, dev->subdevices + i);
- }
}
- if (dev->iobase) {
+ if (dev->iobase)
release_region(dev->iobase, this_board->io_range);
- }
return 0;
}
diff --git a/drivers/staging/comedi/drivers/pcm3730.c b/drivers/staging/comedi/drivers/pcm3730.c
index 9e4adbd89dd..22b7aae63ad 100644
--- a/drivers/staging/comedi/drivers/pcm3730.c
+++ b/drivers/staging/comedi/drivers/pcm3730.c
@@ -73,7 +73,7 @@ static int pcm3730_attach(struct comedi_device *dev,
unsigned long iobase;
iobase = it->options[0];
- printk("comedi%d: pcm3730: 0x%04lx ", dev->minor, iobase);
+ printk(KERN_INFO "comedi%d: pcm3730: 0x%04lx ", dev->minor, iobase);
if (!request_region(iobase, PCM3730_SIZE, "pcm3730")) {
printk("I/O port conflict\n");
return -EIO;
@@ -140,14 +140,14 @@ static int pcm3730_attach(struct comedi_device *dev,
s->range_table = &range_digital;
s->private = (void *)PCM3730_DIC;
- printk("\n");
+ printk(KERN_INFO "\n");
return 0;
}
static int pcm3730_detach(struct comedi_device *dev)
{
- printk("comedi%d: pcm3730: remove\n", dev->minor);
+ printk(KERN_INFO "comedi%d: pcm3730: remove\n", dev->minor);
if (dev->iobase)
release_region(dev->iobase, PCM3730_SIZE);
diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
index acac6709081..fab8092bd7a 100644
--- a/drivers/staging/comedi/drivers/pcmad.c
+++ b/drivers/staging/comedi/drivers/pcmad.c
@@ -34,11 +34,11 @@ Configuration options:
[0] - I/O port base
[1] - unused
[2] - Analog input reference
- 0 = single ended
- 1 = differential
+ 0 = single ended
+ 1 = differential
[3] - Analog input encoding (must match jumpers)
- 0 = straight binary
- 1 = two's complement
+ 0 = straight binary
+ 1 = two's complement
*/
#include <linux/interrupt.h>
@@ -113,9 +113,8 @@ static int pcmad_ai_insn_read(struct comedi_device *dev,
data[n] = inb(dev->iobase + PCMAD_LSB);
data[n] |= (inb(dev->iobase + PCMAD_MSB) << 8);
- if (devpriv->twos_comp) {
+ if (devpriv->twos_comp)
data[n] ^= (1 << (this_board->n_ai_bits - 1));
- }
}
return n;
@@ -135,11 +134,12 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it)
unsigned long iobase;
iobase = it->options[0];
- printk("comedi%d: pcmad: 0x%04lx ", dev->minor, iobase);
+ printk(KERN_INFO "comedi%d: pcmad: 0x%04lx ", dev->minor, iobase);
if (!request_region(iobase, PCMAD_SIZE, "pcmad")) {
- printk("I/O port conflict\n");
+ printk(KERN_CONT "I/O port conflict\n");
return -EIO;
}
+ printk(KERN_CONT "\n");
dev->iobase = iobase;
ret = alloc_subdevices(dev, 1);
@@ -166,11 +166,11 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it)
static int pcmad_detach(struct comedi_device *dev)
{
- printk("comedi%d: pcmad: remove\n", dev->minor);
+ printk(KERN_INFO "comedi%d: pcmad: remove\n", dev->minor);
- if (dev->irq) {
+ if (dev->irq)
free_irq(dev->irq, dev);
- }
+
if (dev->iobase)
release_region(dev->iobase, PCMAD_SIZE);
diff --git a/drivers/staging/comedi/drivers/pcmmio.c b/drivers/staging/comedi/drivers/pcmmio.c
index 35ba93989a3..6ca4105610c 100644
--- a/drivers/staging/comedi/drivers/pcmmio.c
+++ b/drivers/staging/comedi/drivers/pcmmio.c
@@ -550,7 +550,7 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
if (irq[0]) {
printk("irq: %u ", irq[0]);
- if (irq[1] && thisboard->dio_num_asics == 2)
+ if (thisboard->dio_num_asics == 2 && irq[1])
printk("second ASIC irq: %u ", irq[1]);
} else {
printk("(IRQ mode disabled) ");
diff --git a/drivers/staging/comedi/drivers/poc.c b/drivers/staging/comedi/drivers/poc.c
index d23e588d063..1ebc356ce40 100644
--- a/drivers/staging/comedi/drivers/poc.c
+++ b/drivers/staging/comedi/drivers/poc.c
@@ -122,22 +122,21 @@ static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
unsigned int iosize;
iobase = it->options[0];
- printk("comedi%d: poc: using %s iobase 0x%lx\n", dev->minor,
+ printk(KERN_INFO "comedi%d: poc: using %s iobase 0x%lx\n", dev->minor,
this_board->name, iobase);
dev->board_name = this_board->name;
if (iobase == 0) {
- printk("io base address required\n");
+ printk(KERN_ERR "io base address required\n");
return -EINVAL;
}
iosize = this_board->iosize;
/* check if io addresses are available */
if (!request_region(iobase, iosize, "dac02")) {
- printk
- ("I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n",
- iobase, iobase + iosize - 1);
+ printk(KERN_ERR "I/O port conflict: failed to allocate ports "
+ "0x%lx to 0x%lx\n", iobase, iobase + iosize - 1);
return -EIO;
}
dev->iobase = iobase;
@@ -156,9 +155,8 @@ static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->insn_write = this_board->winsn;
s->insn_read = this_board->rinsn;
s->insn_bits = this_board->insnbits;
- if (s->type == COMEDI_SUBD_AO || s->type == COMEDI_SUBD_DO) {
+ if (s->type == COMEDI_SUBD_AO || s->type == COMEDI_SUBD_DO)
s->subdev_flags = SDF_WRITABLE;
- }
return 0;
}
@@ -169,7 +167,7 @@ static int poc_detach(struct comedi_device *dev)
if (dev->iobase)
release_region(dev->iobase, this_board->iosize);
- printk("comedi%d: dac02: remove\n", dev->minor);
+ printk(KERN_INFO "comedi%d: dac02: remove\n", dev->minor);
return 0;
}
diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c
index 2c9d05bd288..028ed6f89c4 100644
--- a/drivers/staging/comedi/drivers/rti800.c
+++ b/drivers/staging/comedi/drivers/rti800.c
@@ -32,22 +32,22 @@ Configuration options:
[0] - I/O port base address
[1] - IRQ
[2] - A/D reference
- 0 = differential
- 1 = pseudodifferential (common)
- 2 = single-ended
+ 0 = differential
+ 1 = pseudodifferential (common)
+ 2 = single-ended
[3] - A/D range
- 0 = [-10,10]
- 1 = [-5,5]
- 2 = [0,10]
+ 0 = [-10,10]
+ 1 = [-5,5]
+ 2 = [0,10]
[4] - A/D encoding
- 0 = two's complement
- 1 = straight binary
+ 0 = two's complement
+ 1 = straight binary
[5] - DAC 0 range
- 0 = [-10,10]
- 1 = [0,10]
+ 0 = [-10,10]
+ 1 = [0,10]
[6] - DAC 0 encoding
- 0 = two's complement
- 1 = straight binary
+ 0 = two's complement
+ 1 = straight binary
[7] - DAC 1 range (same as DAC 0)
[8] - DAC 1 encoding (same as DAC 0)
*/
@@ -225,7 +225,7 @@ static int rti800_ai_insn_read(struct comedi_device *dev,
for (t = RTI800_TIMEOUT; t; t--) {
status = inb(dev->iobase + RTI800_CSR);
if (status & RTI800_OVERRUN) {
- printk("rti800: a/d overrun\n");
+ printk(KERN_WARNING "rti800: a/d overrun\n");
outb(0, dev->iobase + RTI800_CLRFLAGS);
return -EIO;
}
@@ -234,15 +234,14 @@ static int rti800_ai_insn_read(struct comedi_device *dev,
udelay(1);
}
if (t == 0) {
- printk("rti800: timeout\n");
+ printk(KERN_WARNING "rti800: timeout\n");
return -ETIME;
}
data[i] = inb(dev->iobase + RTI800_ADCLO);
data[i] |= (0xf & inb(dev->iobase + RTI800_ADCHI)) << 8;
- if (devpriv->adc_coding == adc_2comp) {
+ if (devpriv->adc_coding == adc_2comp)
data[i] ^= 0x800;
- }
}
return i;
@@ -271,9 +270,9 @@ static int rti800_ao_insn_write(struct comedi_device *dev,
for (i = 0; i < insn->n; i++) {
devpriv->ao_readback[chan] = d = data[i];
- if (devpriv->dac0_coding == dac_2comp) {
+ if (devpriv->dac0_coding == dac_2comp)
d ^= 0x800;
- }
+
outb(d & 0xff,
dev->iobase + (chan ? RTI800_DAC1LO : RTI800_DAC0LO));
outb(d >> 8,
@@ -315,15 +314,15 @@ static int rti800_do_insn_bits(struct comedi_device *dev,
options[0] - I/O port
options[1] - irq
options[2] - a/d mux
- 0=differential, 1=pseudodiff, 2=single
+ 0=differential, 1=pseudodiff, 2=single
options[3] - a/d range
- 0=bipolar10, 1=bipolar5, 2=unipolar10
+ 0=bipolar10, 1=bipolar5, 2=unipolar10
options[4] - a/d coding
- 0=2's comp, 1=straight binary
+ 0=2's comp, 1=straight binary
options[5] - dac0 range
- 0=bipolar10, 1=unipolar10
+ 0=bipolar10, 1=unipolar10
options[6] - dac0 coding
- 0=2's comp, 1=straight binary
+ 0=2's comp, 1=straight binary
options[7] - dac1 range
options[8] - dac1 coding
*/
@@ -336,15 +335,15 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
struct comedi_subdevice *s;
iobase = it->options[0];
- printk("comedi%d: rti800: 0x%04lx ", dev->minor, iobase);
+ printk(KERN_INFO "comedi%d: rti800: 0x%04lx\n", dev->minor, iobase);
if (!request_region(iobase, RTI800_SIZE, "rti800")) {
- printk("I/O port conflict\n");
+ printk(KERN_WARNING "I/O port conflict\n");
return -EIO;
}
dev->iobase = iobase;
#ifdef DEBUG
- printk("fingerprint=%x,%x,%x,%x,%x ",
+ printk(KERN_DEBUG "fingerprint=%x,%x,%x,%x,%x ",
inb(dev->iobase + 0),
inb(dev->iobase + 1),
inb(dev->iobase + 2),
@@ -357,15 +356,15 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
irq = it->options[1];
if (irq) {
- printk("( irq = %u )", irq);
+ printk(KERN_INFO "( irq = %u )\n", irq);
ret = request_irq(irq, rti800_interrupt, 0, "rti800", dev);
if (ret < 0) {
- printk(" Failed to allocate IRQ\n");
+ printk(KERN_WARNING " Failed to allocate IRQ\n");
return ret;
}
dev->irq = irq;
} else {
- printk("( no irq )");
+ printk(KERN_INFO "( no irq )\n");
}
dev->board_name = this_board->name;
@@ -461,14 +460,12 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->type = COMEDI_SUBD_TIMER;
#endif
- printk("\n");
-
return 0;
}
static int rti800_detach(struct comedi_device *dev)
{
- printk("comedi%d: rti800: remove\n", dev->minor);
+ printk(KERN_INFO "comedi%d: rti800: remove\n", dev->minor);
if (dev->iobase)
release_region(dev->iobase, RTI800_SIZE);
diff --git a/drivers/staging/comedi/drivers/rti802.c b/drivers/staging/comedi/drivers/rti802.c
index 2f75c737ea1..2157edcf799 100644
--- a/drivers/staging/comedi/drivers/rti802.c
+++ b/drivers/staging/comedi/drivers/rti802.c
@@ -106,9 +106,9 @@ static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it)
unsigned long iobase;
iobase = it->options[0];
- printk("comedi%d: rti802: 0x%04lx ", dev->minor, iobase);
+ printk(KERN_INFO "comedi%d: rti802: 0x%04lx ", dev->minor, iobase);
if (!request_region(iobase, RTI802_SIZE, "rti802")) {
- printk("I/O port conflict\n");
+ printk(KERN_WARNING "I/O port conflict\n");
return -EIO;
}
dev->iobase = iobase;
@@ -138,14 +138,12 @@ static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it)
? &range_unipolar10 : &range_bipolar10;
}
- printk("\n");
-
return 0;
}
static int rti802_detach(struct comedi_device *dev)
{
- printk("comedi%d: rti802: remove\n", dev->minor);
+ printk(KERN_INFO "comedi%d: rti802: remove\n", dev->minor);
if (dev->iobase)
release_region(dev->iobase, RTI802_SIZE);
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
index fdd7ab954d8..a3cc93362ec 100644
--- a/drivers/staging/comedi/drivers/s626.c
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -140,7 +140,7 @@ struct s626_private {
short allocatedBuf;
uint8_t ai_cmd_running; /* ai_cmd is running */
uint8_t ai_continous; /* continous aquisition */
- int ai_sample_count; /* number of samples to aquire */
+ int ai_sample_count; /* number of samples to acquire */
unsigned int ai_sample_timer;
/* time between samples in units of the timer */
int ai_convert_count; /* conversion counter */
diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
index db37dcdd98b..dd2b9037279 100644
--- a/drivers/staging/comedi/drivers/serial2002.c
+++ b/drivers/staging/comedi/drivers/serial2002.c
@@ -397,7 +397,7 @@ static void serial_2002_open(struct comedi_device *dev)
char port[20];
sprintf(port, "/dev/ttyS%d", devpriv->port);
- devpriv->tty = filp_open(port, 0, O_RDWR);
+ devpriv->tty = filp_open(port, O_RDWR, 0);
if (IS_ERR(devpriv->tty)) {
printk("serial_2002: file open error = %ld\n",
PTR_ERR(devpriv->tty));
diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c
index 4918fbfab5e..17c92a57b0d 100644
--- a/drivers/staging/comedi/drivers/ssv_dnp.c
+++ b/drivers/staging/comedi/drivers/ssv_dnp.c
@@ -300,11 +300,11 @@ static int dnp_dio_insn_config(struct comedi_device *dev,
/* read 'old' direction of the port and set bits (out=1, in=0) */
register_buffer = inb(CSCDR);
- if (data[0] == COMEDI_OUTPUT) {
+ if (data[0] == COMEDI_OUTPUT)
register_buffer |= (1 << chan);
- } else {
+ else
register_buffer &= ~(1 << chan);
- }
+
outb(register_buffer, CSCDR);
return 1;
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c
index 9a1b559c4b0..8942ae45708 100644
--- a/drivers/staging/comedi/drivers/usbdux.c
+++ b/drivers/staging/comedi/drivers/usbdux.c
@@ -95,7 +95,6 @@ sampling rate. If you sample two channels you get 4kHz and so on.
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/usb.h>
-#include <linux/smp_lock.h>
#include <linux/fcntl.h>
#include <linux/compiler.h>
#include <linux/firmware.h>
@@ -289,7 +288,7 @@ struct usbduxsub {
/* continous aquisition */
short int ai_continous;
short int ao_continous;
- /* number of samples to aquire */
+ /* number of samples to acquire */
int ai_sample_count;
int ao_sample_count;
/* time between samples in units of the timer */
@@ -2833,7 +2832,7 @@ static struct comedi_driver driver_usbdux = {
};
/* Table with the USB-devices: just now only testing IDs */
-static struct usb_device_id usbduxsub_table[] = {
+static const struct usb_device_id usbduxsub_table[] = {
{USB_DEVICE(0x13d8, 0x0001)},
{USB_DEVICE(0x13d8, 0x0002)},
{} /* Terminating entry */
diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c
index 2e675cce7db..e89b8181253 100644
--- a/drivers/staging/comedi/drivers/usbduxfast.c
+++ b/drivers/staging/comedi/drivers/usbduxfast.c
@@ -44,7 +44,6 @@
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/usb.h>
-#include <linux/smp_lock.h>
#include <linux/fcntl.h>
#include <linux/compiler.h>
#include "comedi_fc.h"
@@ -182,7 +181,7 @@ struct usbduxfastsub_s {
context */
short int ai_cmd_running; /* asynchronous command is running */
short int ai_continous; /* continous aquisition */
- long int ai_sample_count; /* number of samples to aquire */
+ long int ai_sample_count; /* number of samples to acquire */
uint8_t *dux_commands; /* commands */
int ignore; /* counter which ignores the first
buffers */
@@ -1769,7 +1768,7 @@ static struct comedi_driver driver_usbduxfast = {
/*
* Table with the USB-devices: just now only testing IDs
*/
-static struct usb_device_id usbduxfastsub_table[] = {
+static const struct usb_device_id usbduxfastsub_table[] = {
/* { USB_DEVICE(0x4b4, 0x8613) }, testing */
{USB_DEVICE(0x13d8, 0x0010)}, /* real ID */
{USB_DEVICE(0x13d8, 0x0011)}, /* real ID */
diff --git a/drivers/staging/comedi/drivers/vmk80xx.c b/drivers/staging/comedi/drivers/vmk80xx.c
index c34a0b9141e..6479c38d027 100644
--- a/drivers/staging/comedi/drivers/vmk80xx.c
+++ b/drivers/staging/comedi/drivers/vmk80xx.c
@@ -75,7 +75,7 @@ enum {
DEVICE_VMK8061
};
-static struct usb_device_id vmk80xx_id_table[] = {
+static const struct usb_device_id vmk80xx_id_table[] = {
{USB_DEVICE(0x10cf, 0x5500), .driver_info = DEVICE_VMK8055},
{USB_DEVICE(0x10cf, 0x5501), .driver_info = DEVICE_VMK8055},
{USB_DEVICE(0x10cf, 0x5502), .driver_info = DEVICE_VMK8055},
diff --git a/drivers/staging/crystalhd/Kconfig b/drivers/staging/crystalhd/Kconfig
new file mode 100644
index 00000000000..56b414bca1a
--- /dev/null
+++ b/drivers/staging/crystalhd/Kconfig
@@ -0,0 +1,6 @@
+config CRYSTALHD
+ tristate "Broadcom Crystal HD video decoder support"
+ depends on PCI
+ default n
+ help
+ Support for the Broadcom Crystal HD video decoder chipset
diff --git a/drivers/staging/crystalhd/Makefile b/drivers/staging/crystalhd/Makefile
new file mode 100644
index 00000000000..e2af0ce2e79
--- /dev/null
+++ b/drivers/staging/crystalhd/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_CRYSTALHD) += crystalhd.o
+
+crystalhd-objs := crystalhd_cmds.o \
+ crystalhd_hw.o \
+ crystalhd_lnx.o \
+ crystalhd_misc.o
diff --git a/drivers/staging/crystalhd/TODO b/drivers/staging/crystalhd/TODO
new file mode 100644
index 00000000000..69be5d0cb80
--- /dev/null
+++ b/drivers/staging/crystalhd/TODO
@@ -0,0 +1,16 @@
+- Testing
+- Cleanup return codes
+- Cleanup typedefs
+- Cleanup all WIN* references
+- Allocate an Accelerator device class specific Major number,
+ since we don't have any other open sourced accelerators, it is the only
+ one in that category for now.
+ A somewhat similar device is the DXR2/3
+
+Please send patches to:
+Greg Kroah-Hartman <greg@kroah.com>
+Naren Sankar <nsankar@broadcom.com>
+Jarod Wilson <jarod@wilsonet.com>
+Scott Davilla <davilla@4pi.com>
+Manu Abraham <abraham.manu@gmail.com>
+
diff --git a/drivers/staging/crystalhd/bc_dts_defs.h b/drivers/staging/crystalhd/bc_dts_defs.h
new file mode 100644
index 00000000000..c34cc07127b
--- /dev/null
+++ b/drivers/staging/crystalhd/bc_dts_defs.h
@@ -0,0 +1,498 @@
+/********************************************************************
+ * Copyright(c) 2006-2009 Broadcom Corporation.
+ *
+ * Name: bc_dts_defs.h
+ *
+ * Description: Common definitions for all components. Only types
+ * is allowed to be included from this file.
+ *
+ * AU
+ *
+ * HISTORY:
+ *
+ ********************************************************************
+ * This header is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 2.1 of the License.
+ *
+ * This header is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this header. If not, see <http://www.gnu.org/licenses/>.
+ *******************************************************************/
+
+#ifndef _BC_DTS_DEFS_H_
+#define _BC_DTS_DEFS_H_
+
+#include "bc_dts_types.h"
+
+/* BIT Mask */
+#define BC_BIT(_x) (1 << (_x))
+
+typedef enum _BC_STATUS {
+ BC_STS_SUCCESS = 0,
+ BC_STS_INV_ARG = 1,
+ BC_STS_BUSY = 2,
+ BC_STS_NOT_IMPL = 3,
+ BC_STS_PGM_QUIT = 4,
+ BC_STS_NO_ACCESS = 5,
+ BC_STS_INSUFF_RES = 6,
+ BC_STS_IO_ERROR = 7,
+ BC_STS_NO_DATA = 8,
+ BC_STS_VER_MISMATCH = 9,
+ BC_STS_TIMEOUT = 10,
+ BC_STS_FW_CMD_ERR = 11,
+ BC_STS_DEC_NOT_OPEN = 12,
+ BC_STS_ERR_USAGE = 13,
+ BC_STS_IO_USER_ABORT = 14,
+ BC_STS_IO_XFR_ERROR = 15,
+ BC_STS_DEC_NOT_STARTED = 16,
+ BC_STS_FWHEX_NOT_FOUND = 17,
+ BC_STS_FMT_CHANGE = 18,
+ BC_STS_HIF_ACCESS = 19,
+ BC_STS_CMD_CANCELLED = 20,
+ BC_STS_FW_AUTH_FAILED = 21,
+ BC_STS_BOOTLOADER_FAILED = 22,
+ BC_STS_CERT_VERIFY_ERROR = 23,
+ BC_STS_DEC_EXIST_OPEN = 24,
+ BC_STS_PENDING = 25,
+ BC_STS_CLK_NOCHG = 26,
+
+ /* Must be the last one.*/
+ BC_STS_ERROR = -1
+} BC_STATUS;
+
+/*------------------------------------------------------*
+ * Registry Key Definitions *
+ *------------------------------------------------------*/
+#define BC_REG_KEY_MAIN_PATH "Software\\Broadcom\\MediaPC\\70010"
+#define BC_REG_KEY_FWPATH "FirmwareFilePath"
+#define BC_REG_KEY_SEC_OPT "DbgOptions"
+
+/*
+ * Options:
+ *
+ * b[5] = Enable RSA KEY in EEPROM Support
+ * b[6] = Enable Old PIB scheme. (0 = Use PIB with video scheme)
+ *
+ * b[12] = Enable send message to NotifyIcon
+ *
+ */
+
+typedef enum _BC_SW_OPTIONS {
+ BC_OPT_DOSER_OUT_ENCRYPT = BC_BIT(3),
+ BC_OPT_LINK_OUT_ENCRYPT = BC_BIT(29),
+} BC_SW_OPTIONS;
+
+typedef struct _BC_REG_CONFIG{
+ uint32_t DbgOptions;
+} BC_REG_CONFIG;
+
+#if defined(__KERNEL__) || defined(__LINUX_USER__)
+#else
+/* Align data structures */
+#define ALIGN(x) __declspec(align(x))
+#endif
+
+/* mode
+ * b[0]..b[7] = _DtsDeviceOpenMode
+ * b[8] = Load new FW
+ * b[9] = Load file play back FW
+ * b[10] = Disk format (0 for HD DVD and 1 for BLU ray)
+ * b[11]-b[15] = default output resolution
+ * b[16] = Skip TX CPB Buffer Check
+ * b[17] = Adaptive Output Encrypt/Scramble Scheme
+ * b[18]-b[31] = reserved for future use
+ */
+
+/* To allow multiple apps to open the device. */
+enum _DtsDeviceOpenMode {
+ DTS_PLAYBACK_MODE = 0,
+ DTS_DIAG_MODE,
+ DTS_MONITOR_MODE,
+ DTS_HWINIT_MODE
+};
+
+/* To enable the filter to selectively enable/disable fixes or erratas */
+enum _DtsDeviceFixMode {
+ DTS_LOAD_NEW_FW = BC_BIT(8),
+ DTS_LOAD_FILE_PLAY_FW = BC_BIT(9),
+ DTS_DISK_FMT_BD = BC_BIT(10),
+ /* b[11]-b[15] : Default output resolution */
+ DTS_SKIP_TX_CHK_CPB = BC_BIT(16),
+ DTS_ADAPTIVE_OUTPUT_PER = BC_BIT(17),
+ DTS_INTELLIMAP = BC_BIT(18),
+ /* b[19]-b[21] : select clock frequency */
+ DTS_PLAYBACK_DROP_RPT_MODE = BC_BIT(22)
+};
+
+#define DTS_DFLT_RESOLUTION(x) (x<<11)
+
+#define DTS_DFLT_CLOCK(x) (x<<19)
+
+/* F/W File Version corresponding to S/W Releases */
+enum _FW_FILE_VER {
+ /* S/W release: 02.04.02 F/W release 2.12.2.0 */
+ BC_FW_VER_020402 = ((12<<16) | (2<<8) | (0))
+};
+
+/*------------------------------------------------------*
+ * Stream Types for DtsOpenDecoder() *
+ *------------------------------------------------------*/
+enum _DtsOpenDecStreamTypes {
+ BC_STREAM_TYPE_ES = 0,
+ BC_STREAM_TYPE_PES = 1,
+ BC_STREAM_TYPE_TS = 2,
+ BC_STREAM_TYPE_ES_TSTAMP = 6,
+};
+
+/*------------------------------------------------------*
+ * Video Algorithms for DtsSetVideoParams() *
+ *------------------------------------------------------*/
+enum _DtsSetVideoParamsAlgo {
+ BC_VID_ALGO_H264 = 0,
+ BC_VID_ALGO_MPEG2 = 1,
+ BC_VID_ALGO_VC1 = 4,
+ BC_VID_ALGO_VC1MP = 7,
+};
+
+/*------------------------------------------------------*
+ * MPEG Extension to the PPB *
+ *------------------------------------------------------*/
+#define BC_MPEG_VALID_PANSCAN (1)
+
+typedef struct _BC_PIB_EXT_MPEG {
+ uint32_t valid;
+ /* Always valid, defaults to picture size if no
+ * sequence display extension in the stream. */
+ uint32_t display_horizontal_size;
+ uint32_t display_vertical_size;
+
+ /* MPEG_VALID_PANSCAN
+ * Offsets are a copy values from the MPEG stream. */
+ uint32_t offset_count;
+ int32_t horizontal_offset[3];
+ int32_t vertical_offset[3];
+
+} BC_PIB_EXT_MPEG;
+
+/*------------------------------------------------------*
+ * H.264 Extension to the PPB *
+ *------------------------------------------------------*/
+/* Bit definitions for 'other.h264.valid' field */
+#define H264_VALID_PANSCAN (1)
+#define H264_VALID_SPS_CROP (2)
+#define H264_VALID_VUI (4)
+
+typedef struct _BC_PIB_EXT_H264 {
+ /* 'valid' specifies which fields (or sets of
+ * fields) below are valid. If the corresponding
+ * bit in 'valid' is NOT set then that field(s)
+ * is (are) not initialized. */
+ uint32_t valid;
+
+ /* H264_VALID_PANSCAN */
+ uint32_t pan_scan_count;
+ int32_t pan_scan_left[3];
+ int32_t pan_scan_right[3];
+ int32_t pan_scan_top[3];
+ int32_t pan_scan_bottom[3];
+
+ /* H264_VALID_SPS_CROP */
+ int32_t sps_crop_left;
+ int32_t sps_crop_right;
+ int32_t sps_crop_top;
+ int32_t sps_crop_bottom;
+
+ /* H264_VALID_VUI */
+ uint32_t chroma_top;
+ uint32_t chroma_bottom;
+
+} BC_PIB_EXT_H264;
+
+/*------------------------------------------------------*
+ * VC1 Extension to the PPB *
+ *------------------------------------------------------*/
+#define VC1_VALID_PANSCAN (1)
+
+typedef struct _BC_PIB_EXT_VC1 {
+ uint32_t valid;
+
+ /* Always valid, defaults to picture size if no
+ * sequence display extension in the stream. */
+ uint32_t display_horizontal_size;
+ uint32_t display_vertical_size;
+
+ /* VC1 pan scan windows */
+ uint32_t num_panscan_windows;
+ int32_t ps_horiz_offset[4];
+ int32_t ps_vert_offset[4];
+ int32_t ps_width[4];
+ int32_t ps_height[4];
+
+} BC_PIB_EXT_VC1;
+
+
+/*------------------------------------------------------*
+ * Picture Information Block *
+ *------------------------------------------------------*/
+#if defined(_WIN32) || defined(_WIN64) || defined(__LINUX_USER__)
+/* Values for 'pulldown' field. '0' means no pulldown information
+ * was present for this picture. */
+enum {
+ vdecNoPulldownInfo = 0,
+ vdecTop = 1,
+ vdecBottom = 2,
+ vdecTopBottom = 3,
+ vdecBottomTop = 4,
+ vdecTopBottomTop = 5,
+ vdecBottomTopBottom = 6,
+ vdecFrame_X2 = 7,
+ vdecFrame_X3 = 8,
+ vdecFrame_X1 = 9,
+ vdecFrame_X4 = 10,
+};
+
+/* Values for the 'frame_rate' field. */
+enum {
+ vdecFrameRateUnknown = 0,
+ vdecFrameRate23_97,
+ vdecFrameRate24,
+ vdecFrameRate25,
+ vdecFrameRate29_97,
+ vdecFrameRate30,
+ vdecFrameRate50,
+ vdecFrameRate59_94,
+ vdecFrameRate60,
+};
+
+/* Values for the 'aspect_ratio' field. */
+enum {
+ vdecAspectRatioUnknown = 0,
+ vdecAspectRatioSquare,
+ vdecAspectRatio12_11,
+ vdecAspectRatio10_11,
+ vdecAspectRatio16_11,
+ vdecAspectRatio40_33,
+ vdecAspectRatio24_11,
+ vdecAspectRatio20_11,
+ vdecAspectRatio32_11,
+ vdecAspectRatio80_33,
+ vdecAspectRatio18_11,
+ vdecAspectRatio15_11,
+ vdecAspectRatio64_33,
+ vdecAspectRatio160_99,
+ vdecAspectRatio4_3,
+ vdecAspectRatio16_9,
+ vdecAspectRatio221_1,
+ vdecAspectRatioOther = 255,
+};
+
+/* Values for the 'colour_primaries' field. */
+enum {
+ vdecColourPrimariesUnknown = 0,
+ vdecColourPrimariesBT709,
+ vdecColourPrimariesUnspecified,
+ vdecColourPrimariesReserved,
+ vdecColourPrimariesBT470_2M = 4,
+ vdecColourPrimariesBT470_2BG,
+ vdecColourPrimariesSMPTE170M,
+ vdecColourPrimariesSMPTE240M,
+ vdecColourPrimariesGenericFilm,
+};
+
+enum {
+ vdecRESOLUTION_CUSTOM = 0x00000000, /* custom */
+ vdecRESOLUTION_480i = 0x00000001, /* 480i */
+ vdecRESOLUTION_1080i = 0x00000002, /* 1080i (1920x1080, 60i) */
+ vdecRESOLUTION_NTSC = 0x00000003, /* NTSC (720x483, 60i) */
+ vdecRESOLUTION_480p = 0x00000004, /* 480p (720x480, 60p) */
+ vdecRESOLUTION_720p = 0x00000005, /* 720p (1280x720, 60p) */
+ vdecRESOLUTION_PAL1 = 0x00000006, /* PAL_1 (720x576, 50i) */
+ vdecRESOLUTION_1080i25 = 0x00000007, /* 1080i25 (1920x1080, 50i) */
+ vdecRESOLUTION_720p50 = 0x00000008, /* 720p50 (1280x720, 50p) */
+ vdecRESOLUTION_576p = 0x00000009, /* 576p (720x576, 50p) */
+ vdecRESOLUTION_1080i29_97 = 0x0000000A, /* 1080i (1920x1080, 59.94i) */
+ vdecRESOLUTION_720p59_94 = 0x0000000B, /* 720p (1280x720, 59.94p) */
+ vdecRESOLUTION_SD_DVD = 0x0000000C, /* SD DVD (720x483, 60i) */
+ vdecRESOLUTION_480p656 = 0x0000000D, /* 480p (720x480, 60p), output bus width 8 bit, clock 74.25MHz */
+ vdecRESOLUTION_1080p23_976 = 0x0000000E, /* 1080p23_976 (1920x1080, 23.976p) */
+ vdecRESOLUTION_720p23_976 = 0x0000000F, /* 720p23_976 (1280x720p, 23.976p) */
+ vdecRESOLUTION_240p29_97 = 0x00000010, /* 240p (1440x240, 29.97p ) */
+ vdecRESOLUTION_240p30 = 0x00000011, /* 240p (1440x240, 30p) */
+ vdecRESOLUTION_288p25 = 0x00000012, /* 288p (1440x288p, 25p) */
+ vdecRESOLUTION_1080p29_97 = 0x00000013, /* 1080p29_97 (1920x1080, 29.97p) */
+ vdecRESOLUTION_1080p30 = 0x00000014, /* 1080p30 (1920x1080, 30p) */
+ vdecRESOLUTION_1080p24 = 0x00000015, /* 1080p24 (1920x1080, 24p) */
+ vdecRESOLUTION_1080p25 = 0x00000016, /* 1080p25 (1920x1080, 25p) */
+ vdecRESOLUTION_720p24 = 0x00000017, /* 720p24 (1280x720, 25p) */
+ vdecRESOLUTION_720p29_97 = 0x00000018, /* 720p29.97 (1280x720, 29.97p) */
+ vdecRESOLUTION_480p23_976 = 0x00000019, /* 480p23.976 (720*480, 23.976) */
+ vdecRESOLUTION_480p29_97 = 0x0000001A, /* 480p29.976 (720*480, 29.97p) */
+ vdecRESOLUTION_576p25 = 0x0000001B, /* 576p25 (720*576, 25p) */
+ /* For Zero Frame Rate */
+ vdecRESOLUTION_480p0 = 0x0000001C, /* 480p (720x480, 0p) */
+ vdecRESOLUTION_480i0 = 0x0000001D, /* 480i (720x480, 0i) */
+ vdecRESOLUTION_576p0 = 0x0000001E, /* 576p (720x576, 0p) */
+ vdecRESOLUTION_720p0 = 0x0000001F, /* 720p (1280x720, 0p) */
+ vdecRESOLUTION_1080p0 = 0x00000020, /* 1080p (1920x1080, 0p) */
+ vdecRESOLUTION_1080i0 = 0x00000021, /* 1080i (1920x1080, 0i) */
+};
+
+/* Bit definitions for 'flags' field */
+#define VDEC_FLAG_EOS (0x0004)
+
+#define VDEC_FLAG_FRAME (0x0000)
+#define VDEC_FLAG_FIELDPAIR (0x0008)
+#define VDEC_FLAG_TOPFIELD (0x0010)
+#define VDEC_FLAG_BOTTOMFIELD (0x0018)
+
+#define VDEC_FLAG_PROGRESSIVE_SRC (0x0000)
+#define VDEC_FLAG_INTERLACED_SRC (0x0020)
+#define VDEC_FLAG_UNKNOWN_SRC (0x0040)
+
+#define VDEC_FLAG_BOTTOM_FIRST (0x0080)
+#define VDEC_FLAG_LAST_PICTURE (0x0100)
+
+#define VDEC_FLAG_PICTURE_META_DATA_PRESENT (0x40000)
+
+#endif /* _WIN32 || _WIN64 */
+
+enum _BC_OUTPUT_FORMAT {
+ MODE420 = 0x0,
+ MODE422_YUY2 = 0x1,
+ MODE422_UYVY = 0x2,
+};
+
+typedef struct _BC_PIC_INFO_BLOCK {
+ /* Common fields. */
+ uint64_t timeStamp; /* Timestamp */
+ uint32_t picture_number; /* Ordinal display number */
+ uint32_t width; /* pixels */
+ uint32_t height; /* pixels */
+ uint32_t chroma_format; /* 0x420, 0x422 or 0x444 */
+ uint32_t pulldown;
+ uint32_t flags;
+ uint32_t frame_rate;
+ uint32_t aspect_ratio;
+ uint32_t colour_primaries;
+ uint32_t picture_meta_payload;
+ uint32_t sess_num;
+ uint32_t ycom;
+ uint32_t custom_aspect_ratio_width_height;
+ uint32_t n_drop; /* number of non-reference frames remaining to be dropped */
+
+ /* Protocol-specific extensions. */
+ union {
+ BC_PIB_EXT_H264 h264;
+ BC_PIB_EXT_MPEG mpeg;
+ BC_PIB_EXT_VC1 vc1;
+ } other;
+
+} BC_PIC_INFO_BLOCK, *PBC_PIC_INFO_BLOCK;
+
+/*------------------------------------------------------*
+ * ProcOut Info *
+ *------------------------------------------------------*/
+/* Optional flags for ProcOut Interface.*/
+enum _POUT_OPTIONAL_IN_FLAGS_{
+ /* Flags from App to Device */
+ BC_POUT_FLAGS_YV12 = 0x01, /* Copy Data in YV12 format */
+ BC_POUT_FLAGS_STRIDE = 0x02, /* Stride size is valid. */
+ BC_POUT_FLAGS_SIZE = 0x04, /* Take size information from Application */
+ BC_POUT_FLAGS_INTERLACED = 0x08, /* copy only half the bytes */
+ BC_POUT_FLAGS_INTERLEAVED = 0x10, /* interleaved frame */
+
+ /* Flags from Device to APP */
+ BC_POUT_FLAGS_FMT_CHANGE = 0x10000, /* Data is not VALID when this flag is set */
+ BC_POUT_FLAGS_PIB_VALID = 0x20000, /* PIB Information valid */
+ BC_POUT_FLAGS_ENCRYPTED = 0x40000, /* Data is encrypted. */
+ BC_POUT_FLAGS_FLD_BOT = 0x80000, /* Bottom Field data */
+};
+
+#if defined(__KERNEL__) || defined(__LINUX_USER__)
+typedef BC_STATUS(*dts_pout_callback)(void *shnd, uint32_t width, uint32_t height, uint32_t stride, void *pOut);
+#else
+typedef BC_STATUS(*dts_pout_callback)(void *shnd, uint32_t width, uint32_t height, uint32_t stride, struct _BC_DTS_PROC_OUT *pOut);
+#endif
+
+/* Line 21 Closed Caption */
+/* User Data */
+#define MAX_UD_SIZE 1792 /* 1920 - 128 */
+
+typedef struct _BC_DTS_PROC_OUT {
+ uint8_t *Ybuff; /* Caller Supplied buffer for Y data */
+ uint32_t YbuffSz; /* Caller Supplied Y buffer size */
+ uint32_t YBuffDoneSz; /* Transferred Y datasize */
+
+ uint8_t *UVbuff; /* Caller Supplied buffer for UV data */
+ uint32_t UVbuffSz; /* Caller Supplied UV buffer size */
+ uint32_t UVBuffDoneSz; /* Transferred UV data size */
+
+ uint32_t StrideSz; /* Caller supplied Stride Size */
+ uint32_t PoutFlags; /* Call IN Flags */
+
+ uint32_t discCnt; /* Picture discontinuity count */
+
+ BC_PIC_INFO_BLOCK PicInfo; /* Picture Information Block Data */
+
+ /* Line 21 Closed Caption */
+ /* User Data */
+ uint32_t UserDataSz;
+ uint8_t UserData[MAX_UD_SIZE];
+
+ void *hnd;
+ dts_pout_callback AppCallBack;
+ uint8_t DropFrames;
+ uint8_t b422Mode; /* Picture output Mode */
+ uint8_t bPibEnc; /* PIB encrypted */
+ uint8_t bRevertScramble;
+
+} BC_DTS_PROC_OUT;
+
+typedef struct _BC_DTS_STATUS {
+ uint8_t ReadyListCount; /* Number of frames in ready list (reported by driver) */
+ uint8_t FreeListCount; /* Number of frame buffers free. (reported by driver) */
+ uint8_t PowerStateChange; /* Number of active state power transitions (reported by driver) */
+ uint8_t reserved_[1];
+
+ uint32_t FramesDropped; /* Number of frames dropped. (reported by DIL) */
+ uint32_t FramesCaptured; /* Number of frames captured. (reported by DIL) */
+ uint32_t FramesRepeated; /* Number of frames repeated. (reported by DIL) */
+
+ uint32_t InputCount; /* Times compressed video has been sent to the HW.
+ * i.e. Successful DtsProcInput() calls (reported by DIL) */
+ uint64_t InputTotalSize; /* Amount of compressed video that has been sent to the HW.
+ * (reported by DIL) */
+ uint32_t InputBusyCount; /* Times compressed video has attempted to be sent to the HW
+ * but the input FIFO was full. (reported by DIL) */
+
+ uint32_t PIBMissCount; /* Amount of times a PIB is invalid. (reported by DIL) */
+
+ uint32_t cpbEmptySize; /* supported only for H.264, specifically changed for
+ * Adobe. Report size of CPB buffer available.
+ * Reported by DIL */
+ uint64_t NextTimeStamp; /* TimeStamp of the next picture that will be returned
+ * by a call to ProcOutput. Added for Adobe. Reported
+ * back from the driver */
+ uint8_t reserved__[16];
+
+} BC_DTS_STATUS;
+
+#define BC_SWAP32(_v) \
+ ((((_v) & 0xFF000000)>>24)| \
+ (((_v) & 0x00FF0000)>>8)| \
+ (((_v) & 0x0000FF00)<<8)| \
+ (((_v) & 0x000000FF)<<24))
+
+#define WM_AGENT_TRAYICON_DECODER_OPEN 10001
+#define WM_AGENT_TRAYICON_DECODER_CLOSE 10002
+#define WM_AGENT_TRAYICON_DECODER_START 10003
+#define WM_AGENT_TRAYICON_DECODER_STOP 10004
+#define WM_AGENT_TRAYICON_DECODER_RUN 10005
+#define WM_AGENT_TRAYICON_DECODER_PAUSE 10006
+
+
+#endif /* _BC_DTS_DEFS_H_ */
diff --git a/drivers/staging/crystalhd/bc_dts_glob_lnx.h b/drivers/staging/crystalhd/bc_dts_glob_lnx.h
new file mode 100644
index 00000000000..b3125e3e037
--- /dev/null
+++ b/drivers/staging/crystalhd/bc_dts_glob_lnx.h
@@ -0,0 +1,299 @@
+/********************************************************************
+ * Copyright(c) 2006-2009 Broadcom Corporation.
+ *
+ * Name: bc_dts_glob_lnx.h
+ *
+ * Description: Wrapper to Windows dts_glob.h for Link-Linux usage.
+ * The idea is to define additional Linux related defs
+ * in this file to avoid changes to existing Windows
+ * glob file.
+ *
+ * AU
+ *
+ * HISTORY:
+ *
+ ********************************************************************
+ * This header is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 2.1 of the License.
+ *
+ * This header is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this header. If not, see <http://www.gnu.org/licenses/>.
+ *******************************************************************/
+
+#ifndef _BC_DTS_GLOB_LNX_H_
+#define _BC_DTS_GLOB_LNX_H_
+
+#ifdef __LINUX_USER__
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+#include <netdb.h>
+#include <sys/time.h>
+#include <time.h>
+#include <arpa/inet.h>
+#include <asm/param.h>
+#include <linux/ioctl.h>
+#include <sys/select.h>
+
+#define DRVIFLIB_INT_API
+
+#endif
+
+#include "bc_dts_defs.h"
+#include "bcm_70012_regs.h" /* Link Register defs */
+
+#define CRYSTALHD_API_NAME "crystalhd"
+#define CRYSTALHD_API_DEV_NAME "/dev/crystalhd"
+
+/*
+ * These are SW stack tunable parameters shared
+ * between the driver and the application.
+ */
+enum _BC_DTS_GLOBALS {
+ BC_MAX_FW_CMD_BUFF_SZ = 0x40, /* FW passthrough cmd/rsp buffer size */
+ PCI_CFG_SIZE = 256, /* PCI config size buffer */
+ BC_IOCTL_DATA_POOL_SIZE = 8, /* BC_IOCTL_DATA Pool size */
+ BC_LINK_MAX_OPENS = 3, /* Maximum simultaneous opens*/
+ BC_LINK_MAX_SGLS = 1024, /* Maximum SG elements 4M/4K */
+ BC_TX_LIST_CNT = 2, /* Max Tx DMA Rings */
+ BC_RX_LIST_CNT = 8, /* Max Rx DMA Rings*/
+ BC_PROC_OUTPUT_TIMEOUT = 3000, /* Milliseconds */
+ BC_INFIFO_THRESHOLD = 0x10000,
+};
+
+typedef struct _BC_CMD_REG_ACC {
+ uint32_t Offset;
+ uint32_t Value;
+} BC_CMD_REG_ACC;
+
+typedef struct _BC_CMD_DEV_MEM {
+ uint32_t StartOff;
+ uint32_t NumDwords;
+ uint32_t Rsrd;
+} BC_CMD_DEV_MEM;
+
+/* FW Passthrough command structure */
+enum _bc_fw_cmd_flags {
+ BC_FW_CMD_FLAGS_NONE = 0,
+ BC_FW_CMD_PIB_QS = 0x01,
+};
+
+typedef struct _BC_FW_CMD {
+ uint32_t cmd[BC_MAX_FW_CMD_BUFF_SZ];
+ uint32_t rsp[BC_MAX_FW_CMD_BUFF_SZ];
+ uint32_t flags;
+ uint32_t add_data;
+} BC_FW_CMD, *PBC_FW_CMD;
+
+typedef struct _BC_HW_TYPE {
+ uint16_t PciDevId;
+ uint16_t PciVenId;
+ uint8_t HwRev;
+ uint8_t Align[3];
+} BC_HW_TYPE;
+
+typedef struct _BC_PCI_CFG {
+ uint32_t Size;
+ uint32_t Offset;
+ uint8_t pci_cfg_space[PCI_CFG_SIZE];
+} BC_PCI_CFG;
+
+typedef struct _BC_VERSION_INFO_ {
+ uint8_t DriverMajor;
+ uint8_t DriverMinor;
+ uint16_t DriverRevision;
+} BC_VERSION_INFO;
+
+typedef struct _BC_START_RX_CAP_ {
+ uint32_t Rsrd;
+ uint32_t StartDeliveryThsh;
+ uint32_t PauseThsh;
+ uint32_t ResumeThsh;
+} BC_START_RX_CAP;
+
+typedef struct _BC_FLUSH_RX_CAP_ {
+ uint32_t Rsrd;
+ uint32_t bDiscardOnly;
+} BC_FLUSH_RX_CAP;
+
+typedef struct _BC_DTS_STATS {
+ uint8_t drvRLL;
+ uint8_t drvFLL;
+ uint8_t eosDetected;
+ uint8_t pwr_state_change;
+
+ /* Stats from App */
+ uint32_t opFrameDropped;
+ uint32_t opFrameCaptured;
+ uint32_t ipSampleCnt;
+ uint64_t ipTotalSize;
+ uint32_t reptdFrames;
+ uint32_t pauseCount;
+ uint32_t pibMisses;
+ uint32_t discCounter;
+
+ /* Stats from Driver */
+ uint32_t TxFifoBsyCnt;
+ uint32_t intCount;
+ uint32_t DrvIgnIntrCnt;
+ uint32_t DrvTotalFrmDropped;
+ uint32_t DrvTotalHWErrs;
+ uint32_t DrvTotalPIBFlushCnt;
+ uint32_t DrvTotalFrmCaptured;
+ uint32_t DrvPIBMisses;
+ uint32_t DrvPauseTime;
+ uint32_t DrvRepeatedFrms;
+ uint32_t res1[13];
+
+} BC_DTS_STATS;
+
+typedef struct _BC_PROC_INPUT_ {
+ uint8_t *pDmaBuff;
+ uint32_t BuffSz;
+ uint8_t Mapped;
+ uint8_t Encrypted;
+ uint8_t Rsrd[2];
+ uint32_t DramOffset; /* For debug use only */
+} BC_PROC_INPUT, *PBC_PROC_INPUT;
+
+typedef struct _BC_DEC_YUV_BUFFS {
+ uint32_t b422Mode;
+ uint8_t *YuvBuff;
+ uint32_t YuvBuffSz;
+ uint32_t UVbuffOffset;
+ uint32_t YBuffDoneSz;
+ uint32_t UVBuffDoneSz;
+ uint32_t RefCnt;
+} BC_DEC_YUV_BUFFS;
+
+enum _DECOUT_COMPLETION_FLAGS{
+ COMP_FLAG_NO_INFO = 0x00,
+ COMP_FLAG_FMT_CHANGE = 0x01,
+ COMP_FLAG_PIB_VALID = 0x02,
+ COMP_FLAG_DATA_VALID = 0x04,
+ COMP_FLAG_DATA_ENC = 0x08,
+ COMP_FLAG_DATA_BOT = 0x10,
+};
+
+typedef struct _BC_DEC_OUT_BUFF{
+ BC_DEC_YUV_BUFFS OutPutBuffs;
+ BC_PIC_INFO_BLOCK PibInfo;
+ uint32_t Flags;
+ uint32_t BadFrCnt;
+} BC_DEC_OUT_BUFF;
+
+typedef struct _BC_NOTIFY_MODE {
+ uint32_t Mode;
+ uint32_t Rsvr[3];
+} BC_NOTIFY_MODE;
+
+typedef struct _BC_CLOCK {
+ uint32_t clk;
+ uint32_t Rsvr[3];
+} BC_CLOCK;
+
+typedef struct _BC_IOCTL_DATA {
+ BC_STATUS RetSts;
+ uint32_t IoctlDataSz;
+ uint32_t Timeout;
+ union {
+ BC_CMD_REG_ACC regAcc;
+ BC_CMD_DEV_MEM devMem;
+ BC_FW_CMD fwCmd;
+ BC_HW_TYPE hwType;
+ BC_PCI_CFG pciCfg;
+ BC_VERSION_INFO VerInfo;
+ BC_PROC_INPUT ProcInput;
+ BC_DEC_YUV_BUFFS RxBuffs;
+ BC_DEC_OUT_BUFF DecOutData;
+ BC_START_RX_CAP RxCap;
+ BC_FLUSH_RX_CAP FlushRxCap;
+ BC_DTS_STATS drvStat;
+ BC_NOTIFY_MODE NotifyMode;
+ BC_CLOCK clockValue;
+ } u;
+ struct _BC_IOCTL_DATA *next;
+} BC_IOCTL_DATA;
+
+typedef enum _BC_DRV_CMD{
+ DRV_CMD_VERSION = 0, /* Get SW version */
+ DRV_CMD_GET_HWTYPE, /* Get HW version and type Dozer/Tank */
+ DRV_CMD_REG_RD, /* Read Device Register */
+ DRV_CMD_REG_WR, /* Write Device Register */
+ DRV_CMD_FPGA_RD, /* Read FPGA Register */
+ DRV_CMD_FPGA_WR, /* Wrtie FPGA Reister */
+ DRV_CMD_MEM_RD, /* Read Device Memory */
+ DRV_CMD_MEM_WR, /* Write Device Memory */
+ DRV_CMD_RD_PCI_CFG, /* Read PCI Config Space */
+ DRV_CMD_WR_PCI_CFG, /* Write the PCI Configuration Space*/
+ DRV_CMD_FW_DOWNLOAD, /* Download Firmware */
+ DRV_ISSUE_FW_CMD, /* Issue FW Cmd (pass through mode) */
+ DRV_CMD_PROC_INPUT, /* Process Input Sample */
+ DRV_CMD_ADD_RXBUFFS, /* Add Rx side buffers to driver pool */
+ DRV_CMD_FETCH_RXBUFF, /* Get Rx DMAed buffer */
+ DRV_CMD_START_RX_CAP, /* Start Rx Buffer Capture */
+ DRV_CMD_FLUSH_RX_CAP, /* Stop the capture for now...we will enhance this later*/
+ DRV_CMD_GET_DRV_STAT, /* Get Driver Internal Statistics */
+ DRV_CMD_RST_DRV_STAT, /* Reset Driver Internal Statistics */
+ DRV_CMD_NOTIFY_MODE, /* Notify the Mode to driver in which the application is Operating*/
+ DRV_CMD_CHANGE_CLOCK, /* Change the core clock to either save power or improve performance */
+
+ /* MUST be the last one.. */
+ DRV_CMD_END, /* End of the List.. */
+} BC_DRV_CMD;
+
+#define BC_IOC_BASE 'b'
+#define BC_IOC_VOID _IOC_NONE
+#define BC_IOC_IOWR(nr, type) _IOWR(BC_IOC_BASE, nr, type)
+#define BC_IOCTL_MB BC_IOCTL_DATA
+
+#define BCM_IOC_GET_VERSION BC_IOC_IOWR(DRV_CMD_VERSION, BC_IOCTL_MB)
+#define BCM_IOC_GET_HWTYPE BC_IOC_IOWR(DRV_CMD_GET_HWTYPE, BC_IOCTL_MB)
+#define BCM_IOC_REG_RD BC_IOC_IOWR(DRV_CMD_REG_RD, BC_IOCTL_MB)
+#define BCM_IOC_REG_WR BC_IOC_IOWR(DRV_CMD_REG_WR, BC_IOCTL_MB)
+#define BCM_IOC_MEM_RD BC_IOC_IOWR(DRV_CMD_MEM_RD, BC_IOCTL_MB)
+#define BCM_IOC_MEM_WR BC_IOC_IOWR(DRV_CMD_MEM_WR, BC_IOCTL_MB)
+#define BCM_IOC_FPGA_RD BC_IOC_IOWR(DRV_CMD_FPGA_RD, BC_IOCTL_MB)
+#define BCM_IOC_FPGA_WR BC_IOC_IOWR(DRV_CMD_FPGA_WR, BC_IOCTL_MB)
+#define BCM_IOC_RD_PCI_CFG BC_IOC_IOWR(DRV_CMD_RD_PCI_CFG, BC_IOCTL_MB)
+#define BCM_IOC_WR_PCI_CFG BC_IOC_IOWR(DRV_CMD_WR_PCI_CFG, BC_IOCTL_MB)
+#define BCM_IOC_PROC_INPUT BC_IOC_IOWR(DRV_CMD_PROC_INPUT, BC_IOCTL_MB)
+#define BCM_IOC_ADD_RXBUFFS BC_IOC_IOWR(DRV_CMD_ADD_RXBUFFS, BC_IOCTL_MB)
+#define BCM_IOC_FETCH_RXBUFF BC_IOC_IOWR(DRV_CMD_FETCH_RXBUFF, BC_IOCTL_MB)
+#define BCM_IOC_FW_CMD BC_IOC_IOWR(DRV_ISSUE_FW_CMD, BC_IOCTL_MB)
+#define BCM_IOC_START_RX_CAP BC_IOC_IOWR(DRV_CMD_START_RX_CAP, BC_IOCTL_MB)
+#define BCM_IOC_FLUSH_RX_CAP BC_IOC_IOWR(DRV_CMD_FLUSH_RX_CAP, BC_IOCTL_MB)
+#define BCM_IOC_GET_DRV_STAT BC_IOC_IOWR(DRV_CMD_GET_DRV_STAT, BC_IOCTL_MB)
+#define BCM_IOC_RST_DRV_STAT BC_IOC_IOWR(DRV_CMD_RST_DRV_STAT, BC_IOCTL_MB)
+#define BCM_IOC_NOTIFY_MODE BC_IOC_IOWR(DRV_CMD_NOTIFY_MODE, BC_IOCTL_MB)
+#define BCM_IOC_FW_DOWNLOAD BC_IOC_IOWR(DRV_CMD_FW_DOWNLOAD, BC_IOCTL_MB)
+#define BCM_IOC_CHG_CLK BC_IOC_IOWR(DRV_CMD_CHANGE_CLOCK, BC_IOCTL_MB)
+#define BCM_IOC_END BC_IOC_VOID
+
+/* Wrapper for main IOCTL data */
+typedef struct _crystalhd_ioctl_data {
+ BC_IOCTL_DATA udata; /* IOCTL from App..*/
+ uint32_t u_id; /* Driver specific user ID */
+ uint32_t cmd; /* Cmd ID for driver's use. */
+ void *add_cdata; /* Additional command specific data..*/
+ uint32_t add_cdata_sz; /* Additional command specific data size */
+ struct _crystalhd_ioctl_data *next; /* List/Fifo management */
+} crystalhd_ioctl_data;
+
+
+enum _crystalhd_kmod_ver{
+ crystalhd_kmod_major = 0,
+ crystalhd_kmod_minor = 9,
+ crystalhd_kmod_rev = 27,
+};
+
+#endif
diff --git a/drivers/staging/crystalhd/bc_dts_types.h b/drivers/staging/crystalhd/bc_dts_types.h
new file mode 100644
index 00000000000..ac0c8171738
--- /dev/null
+++ b/drivers/staging/crystalhd/bc_dts_types.h
@@ -0,0 +1,121 @@
+/********************************************************************
+ * Copyright(c) 2006-2009 Broadcom Corporation.
+ *
+ * Name: bc_dts_types.h
+ *
+ * Description: Data types
+ *
+ * AU
+ *
+ * HISTORY:
+ *
+ ********************************************************************
+ * This header is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 2.1 of the License.
+ *
+ * This header is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this header. If not, see <http://www.gnu.org/licenses/>.
+ *******************************************************************/
+
+#ifndef _BC_DTS_TYPES_H_
+#define _BC_DTS_TYPES_H_
+
+#ifdef __LINUX_USER__ // Don't include these for KERNEL..
+#include <stdint.h>
+#endif
+
+#if defined(_WIN64) || defined(_WIN32)
+typedef uint32_t U32;
+typedef int32_t S32;
+typedef uint16_t U16;
+typedef int16_t S16;
+typedef unsigned char U8;
+typedef char S8;
+#endif
+
+#ifndef PVOID
+typedef void *PVOID;
+#endif
+
+#ifndef BOOL
+typedef int BOOL;
+#endif
+
+#ifdef WIN32
+ typedef unsigned __int64 U64;
+#elif defined(_WIN64)
+ typedef uint64_t U64;
+#endif
+
+#ifdef _WIN64
+#if !(defined(POINTER_32))
+#define POINTER_32 __ptr32
+#endif
+#else /* _WIN32 */
+#define POINTER_32
+#endif
+
+#if defined(__KERNEL__) || defined(__LINUX_USER__)
+
+#ifdef __LINUX_USER__ /* Don't include these for KERNEL */
+typedef uint32_t ULONG;
+typedef int32_t LONG;
+typedef void *HANDLE;
+#ifndef VOID
+typedef void VOID;
+#endif
+typedef void *LPVOID;
+typedef uint32_t DWORD;
+typedef uint32_t UINT32;
+typedef uint32_t *LPDWORD;
+typedef unsigned char *PUCHAR;
+
+#ifndef TRUE
+ #define TRUE 1
+#endif
+
+#ifndef FALSE
+ #define FALSE 0
+#endif
+
+#define TEXT
+
+#else
+
+/* For Kernel usage.. */
+typedef bool bc_bool_t;
+#endif
+
+#else
+
+#ifndef uint64_t
+typedef struct _uint64_t {
+ uint32_t low_dw;
+ uint32_t hi_dw;
+} uint64_t;
+#endif
+
+#ifndef int32_t
+typedef signed long int32_t;
+#endif
+
+#ifndef uint32_t
+typedef unsigned long uint32_t;
+#endif
+
+#ifndef uint16_t
+typedef unsigned short uint16_t;
+#endif
+
+#ifndef uint8_t
+typedef unsigned char uint8_t;
+#endif
+#endif
+
+#endif
+
diff --git a/drivers/staging/crystalhd/bcm_70012_regs.h b/drivers/staging/crystalhd/bcm_70012_regs.h
new file mode 100644
index 00000000000..6922f54e432
--- /dev/null
+++ b/drivers/staging/crystalhd/bcm_70012_regs.h
@@ -0,0 +1,757 @@
+/***************************************************************************
+ * Copyright (c) 1999-2009, Broadcom Corporation.
+ *
+ * Name: bcm_70012_regs.h
+ *
+ * Description: BCM70012 registers
+ *
+ ********************************************************************
+ * This header is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation, either version 2.1 of the License.
+ *
+ * This header is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this header. If not, see <http://www.gnu.org/licenses/>.
+ ***************************************************************************/
+
+#ifndef MACFILE_H__
+#define MACFILE_H__
+
+/**
+ * m = memory, c = core, r = register, f = field, d = data.
+ */
+#if !defined(GET_FIELD) && !defined(SET_FIELD)
+#define BRCM_ALIGN(c,r,f) c##_##r##_##f##_ALIGN
+#define BRCM_BITS(c,r,f) c##_##r##_##f##_BITS
+#define BRCM_MASK(c,r,f) c##_##r##_##f##_MASK
+#define BRCM_SHIFT(c,r,f) c##_##r##_##f##_SHIFT
+
+#define GET_FIELD(m,c,r,f) \
+ ((((m) & BRCM_MASK(c,r,f)) >> BRCM_SHIFT(c,r,f)) << BRCM_ALIGN(c,r,f))
+
+#define SET_FIELD(m,c,r,f,d) \
+ ((m) = (((m) & ~BRCM_MASK(c,r,f)) | ((((d) >> BRCM_ALIGN(c,r,f)) << \
+ BRCM_SHIFT(c,r,f)) & BRCM_MASK(c,r,f))) \
+ )
+
+#define SET_TYPE_FIELD(m,c,r,f,d) SET_FIELD(m,c,r,f,c##_##d)
+#define SET_NAME_FIELD(m,c,r,f,d) SET_FIELD(m,c,r,f,c##_##r##_##f##_##d)
+#define SET_VALUE_FIELD(m,c,r,f,d) SET_FIELD(m,c,r,f,d)
+
+#endif /* GET & SET */
+
+/****************************************************************************
+ * Core Enums.
+ ***************************************************************************/
+/****************************************************************************
+ * Enums: AES_RGR_BRIDGE_RESET_CTRL
+ ***************************************************************************/
+#define AES_RGR_BRIDGE_RESET_CTRL_DEASSERT 0
+#define AES_RGR_BRIDGE_RESET_CTRL_ASSERT 1
+
+/****************************************************************************
+ * Enums: CCE_RGR_BRIDGE_RESET_CTRL
+ ***************************************************************************/
+#define CCE_RGR_BRIDGE_RESET_CTRL_DEASSERT 0
+#define CCE_RGR_BRIDGE_RESET_CTRL_ASSERT 1
+
+/****************************************************************************
+ * Enums: DBU_RGR_BRIDGE_RESET_CTRL
+ ***************************************************************************/
+#define DBU_RGR_BRIDGE_RESET_CTRL_DEASSERT 0
+#define DBU_RGR_BRIDGE_RESET_CTRL_ASSERT 1
+
+/****************************************************************************
+ * Enums: DCI_RGR_BRIDGE_RESET_CTRL
+ ***************************************************************************/
+#define DCI_RGR_BRIDGE_RESET_CTRL_DEASSERT 0
+#define DCI_RGR_BRIDGE_RESET_CTRL_ASSERT 1
+
+/****************************************************************************
+ * Enums: GISB_ARBITER_DEASSERT_ASSERT
+ ***************************************************************************/
+#define GISB_ARBITER_DEASSERT_ASSERT_DEASSERT 0
+#define GISB_ARBITER_DEASSERT_ASSERT_ASSERT 1
+
+/****************************************************************************
+ * Enums: GISB_ARBITER_UNMASK_MASK
+ ***************************************************************************/
+#define GISB_ARBITER_UNMASK_MASK_UNMASK 0
+#define GISB_ARBITER_UNMASK_MASK_MASK 1
+
+/****************************************************************************
+ * Enums: GISB_ARBITER_DISABLE_ENABLE
+ ***************************************************************************/
+#define GISB_ARBITER_DISABLE_ENABLE_DISABLE 0
+#define GISB_ARBITER_DISABLE_ENABLE_ENABLE 1
+
+/****************************************************************************
+ * Enums: I2C_GR_BRIDGE_RESET_CTRL
+ ***************************************************************************/
+#define I2C_GR_BRIDGE_RESET_CTRL_DEASSERT 0
+#define I2C_GR_BRIDGE_RESET_CTRL_ASSERT 1
+
+/****************************************************************************
+ * Enums: MISC_GR_BRIDGE_RESET_CTRL
+ ***************************************************************************/
+#define MISC_GR_BRIDGE_RESET_CTRL_DEASSERT 0
+#define MISC_GR_BRIDGE_RESET_CTRL_ASSERT 1
+
+/****************************************************************************
+ * Enums: OTP_GR_BRIDGE_RESET_CTRL
+ ***************************************************************************/
+#define OTP_GR_BRIDGE_RESET_CTRL_DEASSERT 0
+#define OTP_GR_BRIDGE_RESET_CTRL_ASSERT 1
+
+/****************************************************************************
+ * BCM70012_TGT_TOP_PCIE_CFG
+ ***************************************************************************/
+#define PCIE_CFG_DEVICE_VENDOR_ID 0x00000000 /* DEVICE_VENDOR_ID Register */
+#define PCIE_CFG_STATUS_COMMAND 0x00000004 /* STATUS_COMMAND Register */
+#define PCIE_CFG_PCI_CLASSCODE_AND_REVISION_ID 0x00000008 /* PCI_CLASSCODE_AND_REVISION_ID Register */
+#define PCIE_CFG_BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE_SIZE 0x0000000c /* BIST_HEADER_TYPE_LATENCY_TIMER_CACHE_LINE_SIZE Register */
+#define PCIE_CFG_BASE_ADDRESS_1 0x00000010 /* BASE_ADDRESS_1 Register */
+#define PCIE_CFG_BASE_ADDRESS_2 0x00000014 /* BASE_ADDRESS_2 Register */
+#define PCIE_CFG_BASE_ADDRESS_3 0x00000018 /* BASE_ADDRESS_3 Register */
+#define PCIE_CFG_BASE_ADDRESS_4 0x0000001c /* BASE_ADDRESS_4 Register */
+#define PCIE_CFG_CARDBUS_CIS_POINTER 0x00000028 /* CARDBUS_CIS_POINTER Register */
+#define PCIE_CFG_SUBSYSTEM_DEVICE_VENDOR_ID 0x0000002c /* SUBSYSTEM_DEVICE_VENDOR_ID Register */
+#define PCIE_CFG_EXPANSION_ROM_BASE_ADDRESS 0x00000030 /* EXPANSION_ROM_BASE_ADDRESS Register */
+#define PCIE_CFG_CAPABILITIES_POINTER 0x00000034 /* CAPABILITIES_POINTER Register */
+#define PCIE_CFG_INTERRUPT 0x0000003c /* INTERRUPT Register */
+#define PCIE_CFG_VPD_CAPABILITIES 0x00000040 /* VPD_CAPABILITIES Register */
+#define PCIE_CFG_VPD_DATA 0x00000044 /* VPD_DATA Register */
+#define PCIE_CFG_POWER_MANAGEMENT_CAPABILITY 0x00000048 /* POWER_MANAGEMENT_CAPABILITY Register */
+#define PCIE_CFG_POWER_MANAGEMENT_CONTROL_STATUS 0x0000004c /* POWER_MANAGEMENT_CONTROL_STATUS Register */
+#define PCIE_CFG_MSI_CAPABILITY_HEADER 0x00000050 /* MSI_CAPABILITY_HEADER Register */
+#define PCIE_CFG_MSI_LOWER_ADDRESS 0x00000054 /* MSI_LOWER_ADDRESS Register */
+#define PCIE_CFG_MSI_UPPER_ADDRESS_REGISTER 0x00000058 /* MSI_UPPER_ADDRESS_REGISTER Register */
+#define PCIE_CFG_MSI_DATA 0x0000005c /* MSI_DATA Register */
+#define PCIE_CFG_BROADCOM_VENDOR_SPECIFIC_CAPABILITY_HEADER 0x00000060 /* BROADCOM_VENDOR_SPECIFIC_CAPABILITY_HEADER Register */
+#define PCIE_CFG_RESET_COUNTERS_INITIAL_VALUES 0x00000064 /* RESET_COUNTERS_INITIAL_VALUES Register */
+#define PCIE_CFG_MISCELLANEOUS_HOST_CONTROL 0x00000068 /* MISCELLANEOUS_HOST_CONTROL Register */
+#define PCIE_CFG_SPARE 0x0000006c /* SPARE Register */
+#define PCIE_CFG_PCI_STATE 0x00000070 /* PCI_STATE Register */
+#define PCIE_CFG_CLOCK_CONTROL 0x00000074 /* CLOCK_CONTROL Register */
+#define PCIE_CFG_REGISTER_BASE 0x00000078 /* REGISTER_BASE Register */
+#define PCIE_CFG_MEMORY_BASE 0x0000007c /* MEMORY_BASE Register */
+#define PCIE_CFG_REGISTER_DATA 0x00000080 /* REGISTER_DATA Register */
+#define PCIE_CFG_MEMORY_DATA 0x00000084 /* MEMORY_DATA Register */
+#define PCIE_CFG_EXPANSION_ROM_BAR_SIZE 0x00000088 /* EXPANSION_ROM_BAR_SIZE Register */
+#define PCIE_CFG_EXPANSION_ROM_ADDRESS 0x0000008c /* EXPANSION_ROM_ADDRESS Register */
+#define PCIE_CFG_EXPANSION_ROM_DATA 0x00000090 /* EXPANSION_ROM_DATA Register */
+#define PCIE_CFG_VPD_INTERFACE 0x00000094 /* VPD_INTERFACE Register */
+#define PCIE_CFG_UNDI_RECEIVE_BD_STANDARD_PRODUCER_RING_PRODUCER_INDEX_MAILBOX_UPPER 0x00000098 /* UNDI_RECEIVE_BD_STANDARD_PRODUCER_RING_PRODUCER_INDEX_MAILBOX_UPPER Register */
+#define PCIE_CFG_UNDI_RECEIVE_BD_STANDARD_PRODUCER_RING_PRODUCER_INDEX_MAILBOX_LOWER 0x0000009c /* UNDI_RECEIVE_BD_STANDARD_PRODUCER_RING_PRODUCER_INDEX_MAILBOX_LOWER Register */
+#define PCIE_CFG_UNDI_RECEIVE_RETURN_RING_CONSUMER_INDEX_UPPER 0x000000a0 /* UNDI_RECEIVE_RETURN_RING_CONSUMER_INDEX_UPPER Register */
+#define PCIE_CFG_UNDI_RECEIVE_RETURN_RING_CONSUMER_INDEX_LOWER 0x000000a4 /* UNDI_RECEIVE_RETURN_RING_CONSUMER_INDEX_LOWER Register */
+#define PCIE_CFG_UNDI_SEND_BD_PRODUCER_INDEX_MAILBOX_UPPER 0x000000a8 /* UNDI_SEND_BD_PRODUCER_INDEX_MAILBOX_UPPER Register */
+#define PCIE_CFG_UNDI_SEND_BD_PRODUCER_INDEX_MAILBOX_LOWER 0x000000ac /* UNDI_SEND_BD_PRODUCER_INDEX_MAILBOX_LOWER Register */
+#define PCIE_CFG_INT_MAILBOX_UPPER 0x000000b0 /* INT_MAILBOX_UPPER Register */
+#define PCIE_CFG_INT_MAILBOX_LOWER 0x000000b4 /* INT_MAILBOX_LOWER Register */
+#define PCIE_CFG_PRODUCT_ID_AND_ASIC_REVISION 0x000000bc /* PRODUCT_ID_AND_ASIC_REVISION Register */
+#define PCIE_CFG_FUNCTION_EVENT 0x000000c0 /* FUNCTION_EVENT Register */
+#define PCIE_CFG_FUNCTION_EVENT_MASK 0x000000c4 /* FUNCTION_EVENT_MASK Register */
+#define PCIE_CFG_FUNCTION_PRESENT 0x000000c8 /* FUNCTION_PRESENT Register */
+#define PCIE_CFG_PCIE_CAPABILITIES 0x000000cc /* PCIE_CAPABILITIES Register */
+#define PCIE_CFG_DEVICE_CAPABILITIES 0x000000d0 /* DEVICE_CAPABILITIES Register */
+#define PCIE_CFG_DEVICE_STATUS_CONTROL 0x000000d4 /* DEVICE_STATUS_CONTROL Register */
+#define PCIE_CFG_LINK_CAPABILITY 0x000000d8 /* LINK_CAPABILITY Register */
+#define PCIE_CFG_LINK_STATUS_CONTROL 0x000000dc /* LINK_STATUS_CONTROL Register */
+#define PCIE_CFG_DEVICE_CAPABILITIES_2 0x000000f0 /* DEVICE_CAPABILITIES_2 Register */
+#define PCIE_CFG_DEVICE_STATUS_CONTROL_2 0x000000f4 /* DEVICE_STATUS_CONTROL_2 Register */
+#define PCIE_CFG_LINK_CAPABILITIES_2 0x000000f8 /* LINK_CAPABILITIES_2 Register */
+#define PCIE_CFG_LINK_STATUS_CONTROL_2 0x000000fc /* LINK_STATUS_CONTROL_2 Register */
+#define PCIE_CFG_ADVANCED_ERROR_REPORTING_ENHANCED_CAPABILITY_HEADER 0x00000100 /* ADVANCED_ERROR_REPORTING_ENHANCED_CAPABILITY_HEADER Register */
+#define PCIE_CFG_UNCORRECTABLE_ERROR_STATUS 0x00000104 /* UNCORRECTABLE_ERROR_STATUS Register */
+#define PCIE_CFG_UNCORRECTABLE_ERROR_MASK 0x00000108 /* UNCORRECTABLE_ERROR_MASK Register */
+#define PCIE_CFG_UNCORRECTABLE_ERROR_SEVERITY 0x0000010c /* UNCORRECTABLE_ERROR_SEVERITY Register */
+#define PCIE_CFG_CORRECTABLE_ERROR_STATUS 0x00000110 /* CORRECTABLE_ERROR_STATUS Register */
+#define PCIE_CFG_CORRECTABLE_ERROR_MASK 0x00000114 /* CORRECTABLE_ERROR_MASK Register */
+#define PCIE_CFG_ADVANCED_ERROR_CAPABILITIES_AND_CONTROL 0x00000118 /* ADVANCED_ERROR_CAPABILITIES_AND_CONTROL Register */
+#define PCIE_CFG_HEADER_LOG_1 0x0000011c /* HEADER_LOG_1 Register */
+#define PCIE_CFG_HEADER_LOG_2 0x00000120 /* HEADER_LOG_2 Register */
+#define PCIE_CFG_HEADER_LOG_3 0x00000124 /* HEADER_LOG_3 Register */
+#define PCIE_CFG_HEADER_LOG_4 0x00000128 /* HEADER_LOG_4 Register */
+#define PCIE_CFG_VIRTUAL_CHANNEL_ENHANCED_CAPABILITY_HEADER 0x0000013c /* VIRTUAL_CHANNEL_ENHANCED_CAPABILITY_HEADER Register */
+#define PCIE_CFG_PORT_VC_CAPABILITY 0x00000140 /* PORT_VC_CAPABILITY Register */
+#define PCIE_CFG_PORT_VC_CAPABILITY_2 0x00000144 /* PORT_VC_CAPABILITY_2 Register */
+#define PCIE_CFG_PORT_VC_STATUS_CONTROL 0x00000148 /* PORT_VC_STATUS_CONTROL Register */
+#define PCIE_CFG_VC_RESOURCE_CAPABILITY 0x0000014c /* VC_RESOURCE_CAPABILITY Register */
+#define PCIE_CFG_VC_RESOURCE_CONTROL 0x00000150 /* VC_RESOURCE_CONTROL Register */
+#define PCIE_CFG_VC_RESOURCE_STATUS 0x00000154 /* VC_RESOURCE_STATUS Register */
+#define PCIE_CFG_DEVICE_SERIAL_NO_ENHANCED_CAPABILITY_HEADER 0x00000160 /* DEVICE_SERIAL_NO_ENHANCED_CAPABILITY_HEADER Register */
+#define PCIE_CFG_DEVICE_SERIAL_NO_LOWER_DW 0x00000164 /* DEVICE_SERIAL_NO_LOWER_DW Register */
+#define PCIE_CFG_DEVICE_SERIAL_NO_UPPER_DW 0x00000168 /* DEVICE_SERIAL_NO_UPPER_DW Register */
+#define PCIE_CFG_POWER_BUDGETING_ENHANCED_CAPABILITY_HEADER 0x0000016c /* POWER_BUDGETING_ENHANCED_CAPABILITY_HEADER Register */
+#define PCIE_CFG_POWER_BUDGETING_DATA_SELECT 0x00000170 /* POWER_BUDGETING_DATA_SELECT Register */
+#define PCIE_CFG_POWER_BUDGETING_DATA 0x00000174 /* POWER_BUDGETING_DATA Register */
+#define PCIE_CFG_POWER_BUDGETING_CAPABILITY 0x00000178 /* POWER_BUDGETING_CAPABILITY Register */
+#define PCIE_CFG_FIRMWARE_POWER_BUDGETING_2_1 0x0000017c /* FIRMWARE_POWER_BUDGETING_2_1 Register */
+#define PCIE_CFG_FIRMWARE_POWER_BUDGETING_4_3 0x00000180 /* FIRMWARE_POWER_BUDGETING_4_3 Register */
+#define PCIE_CFG_FIRMWARE_POWER_BUDGETING_6_5 0x00000184 /* FIRMWARE_POWER_BUDGETING_6_5 Register */
+#define PCIE_CFG_FIRMWARE_POWER_BUDGETING_8_7 0x00000188 /* FIRMWARE_POWER_BUDGETING_8_7 Register */
+#define PCIE_CFG_PCIE_1_1_ADVISORY_NON_FATAL_ERROR_MASKING 0x0000018c /* PCIE_1_1_ADVISORY_NON_FATAL_ERROR_MASKING Register */
+
+
+/****************************************************************************
+ * BCM70012_TGT_TOP_PCIE_TL
+ ***************************************************************************/
+#define PCIE_TL_TL_CONTROL 0x00000400 /* TL_CONTROL Register */
+#define PCIE_TL_TRANSACTION_CONFIGURATION 0x00000404 /* TRANSACTION_CONFIGURATION Register */
+
+
+/****************************************************************************
+ * BCM70012_TGT_TOP_PCIE_DLL
+ ***************************************************************************/
+#define PCIE_DLL_DATA_LINK_CONTROL 0x00000500 /* DATA_LINK_CONTROL Register */
+#define PCIE_DLL_DATA_LINK_STATUS 0x00000504 /* DATA_LINK_STATUS Register */
+
+
+/****************************************************************************
+ * BCM70012_TGT_TOP_INTR
+ ***************************************************************************/
+#define INTR_INTR_STATUS 0x00000700 /* Interrupt Status Register */
+#define INTR_INTR_SET 0x00000704 /* Interrupt Set Register */
+#define INTR_INTR_CLR_REG 0x00000708 /* Interrupt Clear Register */
+#define INTR_INTR_MSK_STS_REG 0x0000070c /* Interrupt Mask Status Register */
+#define INTR_INTR_MSK_SET_REG 0x00000710 /* Interrupt Mask Set Register */
+#define INTR_INTR_MSK_CLR_REG 0x00000714 /* Interrupt Mask Clear Register */
+#define INTR_EOI_CTRL 0x00000720 /* End of interrupt control register */
+
+
+/****************************************************************************
+ * BCM70012_MISC_TOP_MISC1
+ ***************************************************************************/
+#define MISC1_TX_FIRST_DESC_L_ADDR_LIST0 0x00000c00 /* Tx DMA Descriptor List0 First Descriptor lower Address */
+#define MISC1_TX_FIRST_DESC_U_ADDR_LIST0 0x00000c04 /* Tx DMA Descriptor List0 First Descriptor Upper Address */
+#define MISC1_TX_FIRST_DESC_L_ADDR_LIST1 0x00000c08 /* Tx DMA Descriptor List1 First Descriptor Lower Address */
+#define MISC1_TX_FIRST_DESC_U_ADDR_LIST1 0x00000c0c /* Tx DMA Descriptor List1 First Descriptor Upper Address */
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS 0x00000c10 /* Tx DMA Software Descriptor List Control and Status */
+#define MISC1_TX_DMA_ERROR_STATUS 0x00000c18 /* Tx DMA Engine Error Status */
+#define MISC1_TX_DMA_LIST0_CUR_DESC_L_ADDR 0x00000c1c /* Tx DMA List0 Current Descriptor Lower Address */
+#define MISC1_TX_DMA_LIST0_CUR_DESC_U_ADDR 0x00000c20 /* Tx DMA List0 Current Descriptor Upper Address */
+#define MISC1_TX_DMA_LIST0_CUR_BYTE_CNT_REM 0x00000c24 /* Tx DMA List0 Current Descriptor Upper Address */
+#define MISC1_TX_DMA_LIST1_CUR_DESC_L_ADDR 0x00000c28 /* Tx DMA List1 Current Descriptor Lower Address */
+#define MISC1_TX_DMA_LIST1_CUR_DESC_U_ADDR 0x00000c2c /* Tx DMA List1 Current Descriptor Upper Address */
+#define MISC1_TX_DMA_LIST1_CUR_BYTE_CNT_REM 0x00000c30 /* Tx DMA List1 Current Descriptor Upper Address */
+#define MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST0 0x00000c34 /* Y Rx Descriptor List0 First Descriptor Lower Address */
+#define MISC1_Y_RX_FIRST_DESC_U_ADDR_LIST0 0x00000c38 /* Y Rx Descriptor List0 First Descriptor Upper Address */
+#define MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST1 0x00000c3c /* Y Rx Descriptor List1 First Descriptor Lower Address */
+#define MISC1_Y_RX_FIRST_DESC_U_ADDR_LIST1 0x00000c40 /* Y Rx Descriptor List1 First Descriptor Upper Address */
+#define MISC1_Y_RX_SW_DESC_LIST_CTRL_STS 0x00000c44 /* Y Rx Software Descriptor List Control and Status */
+#define MISC1_Y_RX_ERROR_STATUS 0x00000c4c /* Y Rx Engine Error Status */
+#define MISC1_Y_RX_LIST0_CUR_DESC_L_ADDR 0x00000c50 /* Y Rx List0 Current Descriptor Lower Address */
+#define MISC1_Y_RX_LIST0_CUR_DESC_U_ADDR 0x00000c54 /* Y Rx List0 Current Descriptor Upper Address */
+#define MISC1_Y_RX_LIST0_CUR_BYTE_CNT 0x00000c58 /* Y Rx List0 Current Descriptor Byte Count */
+#define MISC1_Y_RX_LIST1_CUR_DESC_L_ADDR 0x00000c5c /* Y Rx List1 Current Descriptor Lower address */
+#define MISC1_Y_RX_LIST1_CUR_DESC_U_ADDR 0x00000c60 /* Y Rx List1 Current Descriptor Upper address */
+#define MISC1_Y_RX_LIST1_CUR_BYTE_CNT 0x00000c64 /* Y Rx List1 Current Descriptor Byte Count */
+#define MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST0 0x00000c68 /* UV Rx Descriptor List0 First Descriptor lower Address */
+#define MISC1_UV_RX_FIRST_DESC_U_ADDR_LIST0 0x00000c6c /* UV Rx Descriptor List0 First Descriptor Upper Address */
+#define MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST1 0x00000c70 /* UV Rx Descriptor List1 First Descriptor Lower Address */
+#define MISC1_UV_RX_FIRST_DESC_U_ADDR_LIST1 0x00000c74 /* UV Rx Descriptor List1 First Descriptor Upper Address */
+#define MISC1_UV_RX_SW_DESC_LIST_CTRL_STS 0x00000c78 /* UV Rx Software Descriptor List Control and Status */
+#define MISC1_UV_RX_ERROR_STATUS 0x00000c7c /* UV Rx Engine Error Status */
+#define MISC1_UV_RX_LIST0_CUR_DESC_L_ADDR 0x00000c80 /* UV Rx List0 Current Descriptor Lower Address */
+#define MISC1_UV_RX_LIST0_CUR_DESC_U_ADDR 0x00000c84 /* UV Rx List0 Current Descriptor Upper Address */
+#define MISC1_UV_RX_LIST0_CUR_BYTE_CNT 0x00000c88 /* UV Rx List0 Current Descriptor Byte Count */
+#define MISC1_UV_RX_LIST1_CUR_DESC_L_ADDR 0x00000c8c /* UV Rx List1 Current Descriptor Lower Address */
+#define MISC1_UV_RX_LIST1_CUR_DESC_U_ADDR 0x00000c90 /* UV Rx List1 Current Descriptor Upper Address */
+#define MISC1_UV_RX_LIST1_CUR_BYTE_CNT 0x00000c94 /* UV Rx List1 Current Descriptor Byte Count */
+#define MISC1_DMA_DEBUG_OPTIONS_REG 0x00000c98 /* DMA Debug Options Register */
+#define MISC1_READ_CHANNEL_ERROR_STATUS 0x00000c9c /* Read Channel Error Status */
+#define MISC1_PCIE_DMA_CTRL 0x00000ca0 /* PCIE DMA Control Register */
+
+
+/****************************************************************************
+ * BCM70012_MISC_TOP_MISC2
+ ***************************************************************************/
+#define MISC2_GLOBAL_CTRL 0x00000d00 /* Global Control Register */
+#define MISC2_INTERNAL_STATUS 0x00000d04 /* Internal Status Register */
+#define MISC2_INTERNAL_STATUS_MUX_CTRL 0x00000d08 /* Internal Debug Mux Control */
+#define MISC2_DEBUG_FIFO_LENGTH 0x00000d0c /* Debug FIFO Length */
+
+
+/****************************************************************************
+ * BCM70012_MISC_TOP_MISC3
+ ***************************************************************************/
+#define MISC3_RESET_CTRL 0x00000e00 /* Reset Control Register */
+#define MISC3_BIST_CTRL 0x00000e04 /* BIST Control Register */
+#define MISC3_BIST_STATUS 0x00000e08 /* BIST Status Register */
+#define MISC3_RX_CHECKSUM 0x00000e0c /* Receive Checksum */
+#define MISC3_TX_CHECKSUM 0x00000e10 /* Transmit Checksum */
+#define MISC3_ECO_CTRL_CORE 0x00000e14 /* ECO Core Reset Control Register */
+#define MISC3_CSI_TEST_CTRL 0x00000e18 /* CSI Test Control Register */
+#define MISC3_HD_DVI_TEST_CTRL 0x00000e1c /* HD DVI Test Control Register */
+
+
+/****************************************************************************
+ * BCM70012_MISC_TOP_MISC_PERST
+ ***************************************************************************/
+#define MISC_PERST_ECO_CTRL_PERST 0x00000e80 /* ECO PCIE Reset Control Register */
+#define MISC_PERST_DECODER_CTRL 0x00000e84 /* Decoder Control Register */
+#define MISC_PERST_CCE_STATUS 0x00000e88 /* Config Copy Engine Status */
+#define MISC_PERST_PCIE_DEBUG 0x00000e8c /* PCIE Debug Control Register */
+#define MISC_PERST_PCIE_DEBUG_STATUS 0x00000e90 /* PCIE Debug Status Register */
+#define MISC_PERST_VREG_CTRL 0x00000e94 /* Voltage Regulator Control Register */
+#define MISC_PERST_MEM_CTRL 0x00000e98 /* Memory Control Register */
+#define MISC_PERST_CLOCK_CTRL 0x00000e9c /* Clock Control Register */
+
+
+/****************************************************************************
+ * BCM70012_MISC_TOP_GISB_ARBITER
+ ***************************************************************************/
+#define GISB_ARBITER_REVISION 0x00000f00 /* GISB ARBITER REVISION */
+#define GISB_ARBITER_SCRATCH 0x00000f04 /* GISB ARBITER Scratch Register */
+#define GISB_ARBITER_REQ_MASK 0x00000f08 /* GISB ARBITER Master Request Mask Register */
+#define GISB_ARBITER_TIMER 0x00000f0c /* GISB ARBITER Timer Value Register */
+
+
+/****************************************************************************
+ * BCM70012_OTP_TOP_OTP
+ ***************************************************************************/
+#define OTP_CONFIG_INFO 0x00001400 /* OTP Configuration Register */
+#define OTP_CMD 0x00001404 /* OTP Command Register */
+#define OTP_STATUS 0x00001408 /* OTP Status Register */
+#define OTP_CONTENT_MISC 0x0000140c /* Content : Miscellaneous Register */
+#define OTP_CONTENT_AES_0 0x00001410 /* Content : AES Key 0 Register */
+#define OTP_CONTENT_AES_1 0x00001414 /* Content : AES Key 1 Register */
+#define OTP_CONTENT_AES_2 0x00001418 /* Content : AES Key 2 Register */
+#define OTP_CONTENT_AES_3 0x0000141c /* Content : AES Key 3 Register */
+#define OTP_CONTENT_SHA_0 0x00001420 /* Content : SHA Key 0 Register */
+#define OTP_CONTENT_SHA_1 0x00001424 /* Content : SHA Key 1 Register */
+#define OTP_CONTENT_SHA_2 0x00001428 /* Content : SHA Key 2 Register */
+#define OTP_CONTENT_SHA_3 0x0000142c /* Content : SHA Key 3 Register */
+#define OTP_CONTENT_SHA_4 0x00001430 /* Content : SHA Key 4 Register */
+#define OTP_CONTENT_SHA_5 0x00001434 /* Content : SHA Key 5 Register */
+#define OTP_CONTENT_SHA_6 0x00001438 /* Content : SHA Key 6 Register */
+#define OTP_CONTENT_SHA_7 0x0000143c /* Content : SHA Key 7 Register */
+#define OTP_CONTENT_CHECKSUM 0x00001440 /* Content : Checksum Register */
+#define OTP_PROG_CTRL 0x00001444 /* Programming Control Register */
+#define OTP_PROG_STATUS 0x00001448 /* Programming Status Register */
+#define OTP_PROG_PULSE 0x0000144c /* Program Pulse Width Register */
+#define OTP_VERIFY_PULSE 0x00001450 /* Verify Pulse Width Register */
+#define OTP_PROG_MASK 0x00001454 /* Program Mask Register */
+#define OTP_DATA_INPUT 0x00001458 /* Data Input Register */
+#define OTP_DATA_OUTPUT 0x0000145c /* Data Output Register */
+
+
+/****************************************************************************
+ * BCM70012_AES_TOP_AES
+ ***************************************************************************/
+#define AES_CONFIG_INFO 0x00001800 /* AES Configuration Information Register */
+#define AES_CMD 0x00001804 /* AES Command Register */
+#define AES_STATUS 0x00001808 /* AES Status Register */
+#define AES_EEPROM_CONFIG 0x0000180c /* AES EEPROM Configuration Register */
+#define AES_EEPROM_DATA_0 0x00001810 /* AES EEPROM Data Register 0 */
+#define AES_EEPROM_DATA_1 0x00001814 /* AES EEPROM Data Register 1 */
+#define AES_EEPROM_DATA_2 0x00001818 /* AES EEPROM Data Register 2 */
+#define AES_EEPROM_DATA_3 0x0000181c /* AES EEPROM Data Register 3 */
+
+
+/****************************************************************************
+ * BCM70012_DCI_TOP_DCI
+ ***************************************************************************/
+#define DCI_CMD 0x00001c00 /* DCI Command Register */
+#define DCI_STATUS 0x00001c04 /* DCI Status Register */
+#define DCI_DRAM_BASE_ADDR 0x00001c08 /* DRAM Base Address Register */
+#define DCI_FIRMWARE_ADDR 0x00001c0c /* Firmware Address Register */
+#define DCI_FIRMWARE_DATA 0x00001c10 /* Firmware Data Register */
+#define DCI_SIGNATURE_DATA_0 0x00001c14 /* Signature Data Register 0 */
+#define DCI_SIGNATURE_DATA_1 0x00001c18 /* Signature Data Register 1 */
+#define DCI_SIGNATURE_DATA_2 0x00001c1c /* Signature Data Register 2 */
+#define DCI_SIGNATURE_DATA_3 0x00001c20 /* Signature Data Register 3 */
+#define DCI_SIGNATURE_DATA_4 0x00001c24 /* Signature Data Register 4 */
+#define DCI_SIGNATURE_DATA_5 0x00001c28 /* Signature Data Register 5 */
+#define DCI_SIGNATURE_DATA_6 0x00001c2c /* Signature Data Register 6 */
+#define DCI_SIGNATURE_DATA_7 0x00001c30 /* Signature Data Register 7 */
+
+
+/****************************************************************************
+ * BCM70012_TGT_TOP_INTR
+ ***************************************************************************/
+/****************************************************************************
+ * INTR :: INTR_STATUS
+ ***************************************************************************/
+/* INTR :: INTR_STATUS :: reserved0 [31:26] */
+#define INTR_INTR_STATUS_reserved0_MASK 0xfc000000
+#define INTR_INTR_STATUS_reserved0_ALIGN 0
+#define INTR_INTR_STATUS_reserved0_BITS 6
+#define INTR_INTR_STATUS_reserved0_SHIFT 26
+
+/* INTR :: INTR_STATUS :: PCIE_TGT_CA_ATTN [25:25] */
+#define INTR_INTR_STATUS_PCIE_TGT_CA_ATTN_MASK 0x02000000
+#define INTR_INTR_STATUS_PCIE_TGT_CA_ATTN_ALIGN 0
+#define INTR_INTR_STATUS_PCIE_TGT_CA_ATTN_BITS 1
+#define INTR_INTR_STATUS_PCIE_TGT_CA_ATTN_SHIFT 25
+
+/* INTR :: INTR_STATUS :: PCIE_TGT_UR_ATTN [24:24] */
+#define INTR_INTR_STATUS_PCIE_TGT_UR_ATTN_MASK 0x01000000
+#define INTR_INTR_STATUS_PCIE_TGT_UR_ATTN_ALIGN 0
+#define INTR_INTR_STATUS_PCIE_TGT_UR_ATTN_BITS 1
+#define INTR_INTR_STATUS_PCIE_TGT_UR_ATTN_SHIFT 24
+
+/* INTR :: INTR_STATUS :: reserved1 [23:14] */
+#define INTR_INTR_STATUS_reserved1_MASK 0x00ffc000
+#define INTR_INTR_STATUS_reserved1_ALIGN 0
+#define INTR_INTR_STATUS_reserved1_BITS 10
+#define INTR_INTR_STATUS_reserved1_SHIFT 14
+
+/* INTR :: INTR_STATUS :: L1_UV_RX_DMA_ERR_INTR [13:13] */
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_ERR_INTR_MASK 0x00002000
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_ERR_INTR_ALIGN 0
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_ERR_INTR_BITS 1
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_ERR_INTR_SHIFT 13
+
+/* INTR :: INTR_STATUS :: L1_UV_RX_DMA_DONE_INTR [12:12] */
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_MASK 0x00001000
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_ALIGN 0
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_BITS 1
+#define INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_SHIFT 12
+
+/* INTR :: INTR_STATUS :: L1_Y_RX_DMA_ERR_INTR [11:11] */
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_ERR_INTR_MASK 0x00000800
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_ERR_INTR_ALIGN 0
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_ERR_INTR_BITS 1
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_ERR_INTR_SHIFT 11
+
+/* INTR :: INTR_STATUS :: L1_Y_RX_DMA_DONE_INTR [10:10] */
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_MASK 0x00000400
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_ALIGN 0
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_BITS 1
+#define INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_SHIFT 10
+
+/* INTR :: INTR_STATUS :: L1_TX_DMA_ERR_INTR [09:09] */
+#define INTR_INTR_STATUS_L1_TX_DMA_ERR_INTR_MASK 0x00000200
+#define INTR_INTR_STATUS_L1_TX_DMA_ERR_INTR_ALIGN 0
+#define INTR_INTR_STATUS_L1_TX_DMA_ERR_INTR_BITS 1
+#define INTR_INTR_STATUS_L1_TX_DMA_ERR_INTR_SHIFT 9
+
+/* INTR :: INTR_STATUS :: L1_TX_DMA_DONE_INTR [08:08] */
+#define INTR_INTR_STATUS_L1_TX_DMA_DONE_INTR_MASK 0x00000100
+#define INTR_INTR_STATUS_L1_TX_DMA_DONE_INTR_ALIGN 0
+#define INTR_INTR_STATUS_L1_TX_DMA_DONE_INTR_BITS 1
+#define INTR_INTR_STATUS_L1_TX_DMA_DONE_INTR_SHIFT 8
+
+/* INTR :: INTR_STATUS :: reserved2 [07:06] */
+#define INTR_INTR_STATUS_reserved2_MASK 0x000000c0
+#define INTR_INTR_STATUS_reserved2_ALIGN 0
+#define INTR_INTR_STATUS_reserved2_BITS 2
+#define INTR_INTR_STATUS_reserved2_SHIFT 6
+
+/* INTR :: INTR_STATUS :: L0_UV_RX_DMA_ERR_INTR [05:05] */
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_ERR_INTR_MASK 0x00000020
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_ERR_INTR_ALIGN 0
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_ERR_INTR_BITS 1
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_ERR_INTR_SHIFT 5
+
+/* INTR :: INTR_STATUS :: L0_UV_RX_DMA_DONE_INTR [04:04] */
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_MASK 0x00000010
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_ALIGN 0
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_BITS 1
+#define INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_SHIFT 4
+
+/* INTR :: INTR_STATUS :: L0_Y_RX_DMA_ERR_INTR [03:03] */
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_ERR_INTR_MASK 0x00000008
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_ERR_INTR_ALIGN 0
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_ERR_INTR_BITS 1
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_ERR_INTR_SHIFT 3
+
+/* INTR :: INTR_STATUS :: L0_Y_RX_DMA_DONE_INTR [02:02] */
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_MASK 0x00000004
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_ALIGN 0
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_BITS 1
+#define INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_SHIFT 2
+
+/* INTR :: INTR_STATUS :: L0_TX_DMA_ERR_INTR [01:01] */
+#define INTR_INTR_STATUS_L0_TX_DMA_ERR_INTR_MASK 0x00000002
+#define INTR_INTR_STATUS_L0_TX_DMA_ERR_INTR_ALIGN 0
+#define INTR_INTR_STATUS_L0_TX_DMA_ERR_INTR_BITS 1
+#define INTR_INTR_STATUS_L0_TX_DMA_ERR_INTR_SHIFT 1
+
+/* INTR :: INTR_STATUS :: L0_TX_DMA_DONE_INTR [00:00] */
+#define INTR_INTR_STATUS_L0_TX_DMA_DONE_INTR_MASK 0x00000001
+#define INTR_INTR_STATUS_L0_TX_DMA_DONE_INTR_ALIGN 0
+#define INTR_INTR_STATUS_L0_TX_DMA_DONE_INTR_BITS 1
+#define INTR_INTR_STATUS_L0_TX_DMA_DONE_INTR_SHIFT 0
+
+
+/****************************************************************************
+ * MISC1 :: TX_SW_DESC_LIST_CTRL_STS
+ ***************************************************************************/
+/* MISC1 :: TX_SW_DESC_LIST_CTRL_STS :: reserved0 [31:04] */
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_reserved0_MASK 0xfffffff0
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_reserved0_ALIGN 0
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_reserved0_BITS 28
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_reserved0_SHIFT 4
+
+/* MISC1 :: TX_SW_DESC_LIST_CTRL_STS :: DMA_DATA_SERV_PTR [03:03] */
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DMA_DATA_SERV_PTR_MASK 0x00000008
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DMA_DATA_SERV_PTR_ALIGN 0
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DMA_DATA_SERV_PTR_BITS 1
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DMA_DATA_SERV_PTR_SHIFT 3
+
+/* MISC1 :: TX_SW_DESC_LIST_CTRL_STS :: DESC_SERV_PTR [02:02] */
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DESC_SERV_PTR_MASK 0x00000004
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DESC_SERV_PTR_ALIGN 0
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DESC_SERV_PTR_BITS 1
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_DESC_SERV_PTR_SHIFT 2
+
+/* MISC1 :: TX_SW_DESC_LIST_CTRL_STS :: TX_DMA_HALT_ON_ERROR [01:01] */
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_HALT_ON_ERROR_MASK 0x00000002
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_HALT_ON_ERROR_ALIGN 0
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_HALT_ON_ERROR_BITS 1
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_HALT_ON_ERROR_SHIFT 1
+
+/* MISC1 :: TX_SW_DESC_LIST_CTRL_STS :: TX_DMA_RUN_STOP [00:00] */
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_MASK 0x00000001
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_ALIGN 0
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_BITS 1
+#define MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_SHIFT 0
+
+
+/****************************************************************************
+ * MISC1 :: TX_DMA_ERROR_STATUS
+ ***************************************************************************/
+/* MISC1 :: TX_DMA_ERROR_STATUS :: reserved0 [31:10] */
+#define MISC1_TX_DMA_ERROR_STATUS_reserved0_MASK 0xfffffc00
+#define MISC1_TX_DMA_ERROR_STATUS_reserved0_ALIGN 0
+#define MISC1_TX_DMA_ERROR_STATUS_reserved0_BITS 22
+#define MISC1_TX_DMA_ERROR_STATUS_reserved0_SHIFT 10
+
+/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L1_DESC_TX_ABORT_ERRORS [09:09] */
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DESC_TX_ABORT_ERRORS_MASK 0x00000200
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DESC_TX_ABORT_ERRORS_ALIGN 0
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DESC_TX_ABORT_ERRORS_BITS 1
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DESC_TX_ABORT_ERRORS_SHIFT 9
+
+/* MISC1 :: TX_DMA_ERROR_STATUS :: reserved1 [08:08] */
+#define MISC1_TX_DMA_ERROR_STATUS_reserved1_MASK 0x00000100
+#define MISC1_TX_DMA_ERROR_STATUS_reserved1_ALIGN 0
+#define MISC1_TX_DMA_ERROR_STATUS_reserved1_BITS 1
+#define MISC1_TX_DMA_ERROR_STATUS_reserved1_SHIFT 8
+
+/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L0_DESC_TX_ABORT_ERRORS [07:07] */
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DESC_TX_ABORT_ERRORS_MASK 0x00000080
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DESC_TX_ABORT_ERRORS_ALIGN 0
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DESC_TX_ABORT_ERRORS_BITS 1
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DESC_TX_ABORT_ERRORS_SHIFT 7
+
+/* MISC1 :: TX_DMA_ERROR_STATUS :: reserved2 [06:06] */
+#define MISC1_TX_DMA_ERROR_STATUS_reserved2_MASK 0x00000040
+#define MISC1_TX_DMA_ERROR_STATUS_reserved2_ALIGN 0
+#define MISC1_TX_DMA_ERROR_STATUS_reserved2_BITS 1
+#define MISC1_TX_DMA_ERROR_STATUS_reserved2_SHIFT 6
+
+/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L1_DMA_DATA_TX_ABORT_ERRORS [05:05] */
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DMA_DATA_TX_ABORT_ERRORS_MASK 0x00000020
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DMA_DATA_TX_ABORT_ERRORS_ALIGN 0
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DMA_DATA_TX_ABORT_ERRORS_BITS 1
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_DMA_DATA_TX_ABORT_ERRORS_SHIFT 5
+
+/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L1_FIFO_FULL_ERRORS [04:04] */
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_MASK 0x00000010
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_ALIGN 0
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_BITS 1
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_SHIFT 4
+
+/* MISC1 :: TX_DMA_ERROR_STATUS :: reserved3 [03:03] */
+#define MISC1_TX_DMA_ERROR_STATUS_reserved3_MASK 0x00000008
+#define MISC1_TX_DMA_ERROR_STATUS_reserved3_ALIGN 0
+#define MISC1_TX_DMA_ERROR_STATUS_reserved3_BITS 1
+#define MISC1_TX_DMA_ERROR_STATUS_reserved3_SHIFT 3
+
+/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L0_DMA_DATA_TX_ABORT_ERRORS [02:02] */
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DMA_DATA_TX_ABORT_ERRORS_MASK 0x00000004
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DMA_DATA_TX_ABORT_ERRORS_ALIGN 0
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DMA_DATA_TX_ABORT_ERRORS_BITS 1
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_DMA_DATA_TX_ABORT_ERRORS_SHIFT 2
+
+/* MISC1 :: TX_DMA_ERROR_STATUS :: TX_L0_FIFO_FULL_ERRORS [01:01] */
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_MASK 0x00000002
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_ALIGN 0
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_BITS 1
+#define MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_SHIFT 1
+
+/* MISC1 :: TX_DMA_ERROR_STATUS :: reserved4 [00:00] */
+#define MISC1_TX_DMA_ERROR_STATUS_reserved4_MASK 0x00000001
+#define MISC1_TX_DMA_ERROR_STATUS_reserved4_ALIGN 0
+#define MISC1_TX_DMA_ERROR_STATUS_reserved4_BITS 1
+#define MISC1_TX_DMA_ERROR_STATUS_reserved4_SHIFT 0
+
+
+/****************************************************************************
+ * MISC1 :: Y_RX_ERROR_STATUS
+ ***************************************************************************/
+/* MISC1 :: Y_RX_ERROR_STATUS :: reserved0 [31:14] */
+#define MISC1_Y_RX_ERROR_STATUS_reserved0_MASK 0xffffc000
+#define MISC1_Y_RX_ERROR_STATUS_reserved0_ALIGN 0
+#define MISC1_Y_RX_ERROR_STATUS_reserved0_BITS 18
+#define MISC1_Y_RX_ERROR_STATUS_reserved0_SHIFT 14
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L1_UNDERRUN_ERROR [13:13] */
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK 0x00002000
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_ALIGN 0
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_BITS 1
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_SHIFT 13
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L1_OVERRUN_ERROR [12:12] */
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_MASK 0x00001000
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_ALIGN 0
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_BITS 1
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_SHIFT 12
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L0_UNDERRUN_ERROR [11:11] */
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK 0x00000800
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_ALIGN 0
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_BITS 1
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_SHIFT 11
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L0_OVERRUN_ERROR [10:10] */
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_MASK 0x00000400
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_ALIGN 0
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_BITS 1
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_SHIFT 10
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L1_DESC_TX_ABORT_ERRORS [09:09] */
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_MASK 0x00000200
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_ALIGN 0
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_BITS 1
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_SHIFT 9
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: reserved1 [08:08] */
+#define MISC1_Y_RX_ERROR_STATUS_reserved1_MASK 0x00000100
+#define MISC1_Y_RX_ERROR_STATUS_reserved1_ALIGN 0
+#define MISC1_Y_RX_ERROR_STATUS_reserved1_BITS 1
+#define MISC1_Y_RX_ERROR_STATUS_reserved1_SHIFT 8
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L0_DESC_TX_ABORT_ERRORS [07:07] */
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_MASK 0x00000080
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_ALIGN 0
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_BITS 1
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_SHIFT 7
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: reserved2 [06:05] */
+#define MISC1_Y_RX_ERROR_STATUS_reserved2_MASK 0x00000060
+#define MISC1_Y_RX_ERROR_STATUS_reserved2_ALIGN 0
+#define MISC1_Y_RX_ERROR_STATUS_reserved2_BITS 2
+#define MISC1_Y_RX_ERROR_STATUS_reserved2_SHIFT 5
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L1_FIFO_FULL_ERRORS [04:04] */
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK 0x00000010
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_ALIGN 0
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_BITS 1
+#define MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_SHIFT 4
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: reserved3 [03:02] */
+#define MISC1_Y_RX_ERROR_STATUS_reserved3_MASK 0x0000000c
+#define MISC1_Y_RX_ERROR_STATUS_reserved3_ALIGN 0
+#define MISC1_Y_RX_ERROR_STATUS_reserved3_BITS 2
+#define MISC1_Y_RX_ERROR_STATUS_reserved3_SHIFT 2
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: RX_L0_FIFO_FULL_ERRORS [01:01] */
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK 0x00000002
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_ALIGN 0
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_BITS 1
+#define MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_SHIFT 1
+
+/* MISC1 :: Y_RX_ERROR_STATUS :: reserved4 [00:00] */
+#define MISC1_Y_RX_ERROR_STATUS_reserved4_MASK 0x00000001
+#define MISC1_Y_RX_ERROR_STATUS_reserved4_ALIGN 0
+#define MISC1_Y_RX_ERROR_STATUS_reserved4_BITS 1
+#define MISC1_Y_RX_ERROR_STATUS_reserved4_SHIFT 0
+
+
+/****************************************************************************
+ * MISC1 :: UV_RX_ERROR_STATUS
+ ***************************************************************************/
+/* MISC1 :: UV_RX_ERROR_STATUS :: reserved0 [31:14] */
+#define MISC1_UV_RX_ERROR_STATUS_reserved0_MASK 0xffffc000
+#define MISC1_UV_RX_ERROR_STATUS_reserved0_ALIGN 0
+#define MISC1_UV_RX_ERROR_STATUS_reserved0_BITS 18
+#define MISC1_UV_RX_ERROR_STATUS_reserved0_SHIFT 14
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L1_UNDERRUN_ERROR [13:13] */
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK 0x00002000
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_ALIGN 0
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_BITS 1
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_SHIFT 13
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L1_OVERRUN_ERROR [12:12] */
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_MASK 0x00001000
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_ALIGN 0
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_BITS 1
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_SHIFT 12
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L0_UNDERRUN_ERROR [11:11] */
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK 0x00000800
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_ALIGN 0
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_BITS 1
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_SHIFT 11
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L0_OVERRUN_ERROR [10:10] */
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_MASK 0x00000400
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_ALIGN 0
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_BITS 1
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_SHIFT 10
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L1_DESC_TX_ABORT_ERRORS [09:09] */
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_MASK 0x00000200
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_ALIGN 0
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_BITS 1
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_SHIFT 9
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: reserved1 [08:08] */
+#define MISC1_UV_RX_ERROR_STATUS_reserved1_MASK 0x00000100
+#define MISC1_UV_RX_ERROR_STATUS_reserved1_ALIGN 0
+#define MISC1_UV_RX_ERROR_STATUS_reserved1_BITS 1
+#define MISC1_UV_RX_ERROR_STATUS_reserved1_SHIFT 8
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L0_DESC_TX_ABORT_ERRORS [07:07] */
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_MASK 0x00000080
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_ALIGN 0
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_BITS 1
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_SHIFT 7
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: reserved2 [06:05] */
+#define MISC1_UV_RX_ERROR_STATUS_reserved2_MASK 0x00000060
+#define MISC1_UV_RX_ERROR_STATUS_reserved2_ALIGN 0
+#define MISC1_UV_RX_ERROR_STATUS_reserved2_BITS 2
+#define MISC1_UV_RX_ERROR_STATUS_reserved2_SHIFT 5
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L1_FIFO_FULL_ERRORS [04:04] */
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK 0x00000010
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_ALIGN 0
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_BITS 1
+#define MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_SHIFT 4
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: reserved3 [03:02] */
+#define MISC1_UV_RX_ERROR_STATUS_reserved3_MASK 0x0000000c
+#define MISC1_UV_RX_ERROR_STATUS_reserved3_ALIGN 0
+#define MISC1_UV_RX_ERROR_STATUS_reserved3_BITS 2
+#define MISC1_UV_RX_ERROR_STATUS_reserved3_SHIFT 2
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: RX_L0_FIFO_FULL_ERRORS [01:01] */
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK 0x00000002
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_ALIGN 0
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_BITS 1
+#define MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_SHIFT 1
+
+/* MISC1 :: UV_RX_ERROR_STATUS :: reserved4 [00:00] */
+#define MISC1_UV_RX_ERROR_STATUS_reserved4_MASK 0x00000001
+#define MISC1_UV_RX_ERROR_STATUS_reserved4_ALIGN 0
+#define MISC1_UV_RX_ERROR_STATUS_reserved4_BITS 1
+#define MISC1_UV_RX_ERROR_STATUS_reserved4_SHIFT 0
+
+/****************************************************************************
+ * Datatype Definitions.
+ ***************************************************************************/
+#endif /* #ifndef MACFILE_H__ */
+
+/* End of File */
+
diff --git a/drivers/staging/crystalhd/crystalhd_cmds.c b/drivers/staging/crystalhd/crystalhd_cmds.c
new file mode 100644
index 00000000000..26145a8d0f7
--- /dev/null
+++ b/drivers/staging/crystalhd/crystalhd_cmds.c
@@ -0,0 +1,1058 @@
+/***************************************************************************
+ * Copyright (c) 2005-2009, Broadcom Corporation.
+ *
+ * Name: crystalhd_cmds . c
+ *
+ * Description:
+ * BCM70010 Linux driver user command interfaces.
+ *
+ * HISTORY:
+ *
+ **********************************************************************
+ * This file is part of the crystalhd device driver.
+ *
+ * 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, version 2 of the License.
+ *
+ * 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 driver. If not, see <http://www.gnu.org/licenses/>.
+ **********************************************************************/
+
+#include "crystalhd_cmds.h"
+#include "crystalhd_hw.h"
+
+static struct crystalhd_user *bc_cproc_get_uid(struct crystalhd_cmd *ctx)
+{
+ struct crystalhd_user *user = NULL;
+ int i;
+
+ for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
+ if (!ctx->user[i].in_use) {
+ user = &ctx->user[i];
+ break;
+ }
+ }
+
+ return user;
+}
+
+static int bc_cproc_get_user_count(struct crystalhd_cmd *ctx)
+{
+ int i, count = 0;
+
+ for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
+ if (ctx->user[i].in_use)
+ count++;
+ }
+
+ return count;
+}
+
+static void bc_cproc_mark_pwr_state(struct crystalhd_cmd *ctx)
+{
+ int i;
+
+ for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
+ if (!ctx->user[i].in_use)
+ continue;
+ if (ctx->user[i].mode == DTS_DIAG_MODE ||
+ ctx->user[i].mode == DTS_PLAYBACK_MODE) {
+ ctx->pwr_state_change = 1;
+ break;
+ }
+ }
+}
+
+static BC_STATUS bc_cproc_notify_mode(struct crystalhd_cmd *ctx,
+ crystalhd_ioctl_data *idata)
+{
+ int rc = 0, i = 0;
+
+ if (!ctx || !idata) {
+ BCMLOG_ERR("Invalid Arg!!\n");
+ return BC_STS_INV_ARG;
+ }
+
+ if (ctx->user[idata->u_id].mode != DTS_MODE_INV) {
+ BCMLOG_ERR("Close the handle first..\n");
+ return BC_STS_ERR_USAGE;
+ }
+ if (idata->udata.u.NotifyMode.Mode == DTS_MONITOR_MODE) {
+ ctx->user[idata->u_id].mode = idata->udata.u.NotifyMode.Mode;
+ return BC_STS_SUCCESS;
+ }
+ if (ctx->state != BC_LINK_INVALID) {
+ BCMLOG_ERR("Link invalid state %d \n", ctx->state);
+ return BC_STS_ERR_USAGE;
+ }
+ /* Check for duplicate playback sessions..*/
+ for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
+ if (ctx->user[i].mode == DTS_DIAG_MODE ||
+ ctx->user[i].mode == DTS_PLAYBACK_MODE) {
+ BCMLOG_ERR("multiple playback sessions are not "
+ "supported..\n");
+ return BC_STS_ERR_USAGE;
+ }
+ }
+ ctx->cin_wait_exit = 0;
+ ctx->user[idata->u_id].mode = idata->udata.u.NotifyMode.Mode;
+ /* Setup mmap pool for uaddr sgl mapping..*/
+ rc = crystalhd_create_dio_pool(ctx->adp, BC_LINK_MAX_SGLS);
+ if (rc)
+ return BC_STS_ERROR;
+
+ /* Setup Hardware DMA rings */
+ return crystalhd_hw_setup_dma_rings(&ctx->hw_ctx);
+}
+
+static BC_STATUS bc_cproc_get_version(struct crystalhd_cmd *ctx,
+ crystalhd_ioctl_data *idata)
+{
+
+ if (!ctx || !idata) {
+ BCMLOG_ERR("Invalid Arg!!\n");
+ return BC_STS_INV_ARG;
+ }
+ idata->udata.u.VerInfo.DriverMajor = crystalhd_kmod_major;
+ idata->udata.u.VerInfo.DriverMinor = crystalhd_kmod_minor;
+ idata->udata.u.VerInfo.DriverRevision = crystalhd_kmod_rev;
+ return BC_STS_SUCCESS;
+}
+
+
+static BC_STATUS bc_cproc_get_hwtype(struct crystalhd_cmd *ctx, crystalhd_ioctl_data *idata)
+{
+ if (!ctx || !idata) {
+ BCMLOG_ERR("Invalid Arg!!\n");
+ return BC_STS_INV_ARG;
+ }
+
+ crystalhd_pci_cfg_rd(ctx->adp, 0, 2,
+ (uint32_t *)&idata->udata.u.hwType.PciVenId);
+ crystalhd_pci_cfg_rd(ctx->adp, 2, 2,
+ (uint32_t *)&idata->udata.u.hwType.PciDevId);
+ crystalhd_pci_cfg_rd(ctx->adp, 8, 1,
+ (uint32_t *)&idata->udata.u.hwType.HwRev);
+
+ return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_reg_rd(struct crystalhd_cmd *ctx,
+ crystalhd_ioctl_data *idata)
+{
+ if (!ctx || !idata)
+ return BC_STS_INV_ARG;
+ idata->udata.u.regAcc.Value = bc_dec_reg_rd(ctx->adp,
+ idata->udata.u.regAcc.Offset);
+ return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_reg_wr(struct crystalhd_cmd *ctx,
+ crystalhd_ioctl_data *idata)
+{
+ if (!ctx || !idata)
+ return BC_STS_INV_ARG;
+
+ bc_dec_reg_wr(ctx->adp, idata->udata.u.regAcc.Offset,
+ idata->udata.u.regAcc.Value);
+
+ return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_link_reg_rd(struct crystalhd_cmd *ctx,
+ crystalhd_ioctl_data *idata)
+{
+ if (!ctx || !idata)
+ return BC_STS_INV_ARG;
+
+ idata->udata.u.regAcc.Value = crystalhd_reg_rd(ctx->adp,
+ idata->udata.u.regAcc.Offset);
+ return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_link_reg_wr(struct crystalhd_cmd *ctx,
+ crystalhd_ioctl_data *idata)
+{
+ if (!ctx || !idata)
+ return BC_STS_INV_ARG;
+
+ crystalhd_reg_wr(ctx->adp, idata->udata.u.regAcc.Offset,
+ idata->udata.u.regAcc.Value);
+
+ return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_mem_rd(struct crystalhd_cmd *ctx,
+ crystalhd_ioctl_data *idata)
+{
+ BC_STATUS sts = BC_STS_SUCCESS;
+
+ if (!ctx || !idata || !idata->add_cdata)
+ return BC_STS_INV_ARG;
+
+ if (idata->udata.u.devMem.NumDwords > (idata->add_cdata_sz / 4)) {
+ BCMLOG_ERR("insufficient buffer\n");
+ return BC_STS_INV_ARG;
+ }
+ sts = crystalhd_mem_rd(ctx->adp, idata->udata.u.devMem.StartOff,
+ idata->udata.u.devMem.NumDwords,
+ (uint32_t *)idata->add_cdata);
+ return sts;
+
+}
+
+static BC_STATUS bc_cproc_mem_wr(struct crystalhd_cmd *ctx,
+ crystalhd_ioctl_data *idata)
+{
+ BC_STATUS sts = BC_STS_SUCCESS;
+
+ if (!ctx || !idata || !idata->add_cdata)
+ return BC_STS_INV_ARG;
+
+ if (idata->udata.u.devMem.NumDwords > (idata->add_cdata_sz / 4)) {
+ BCMLOG_ERR("insufficient buffer\n");
+ return BC_STS_INV_ARG;
+ }
+
+ sts = crystalhd_mem_wr(ctx->adp, idata->udata.u.devMem.StartOff,
+ idata->udata.u.devMem.NumDwords,
+ (uint32_t *)idata->add_cdata);
+ return sts;
+}
+
+static BC_STATUS bc_cproc_cfg_rd(struct crystalhd_cmd *ctx,
+ crystalhd_ioctl_data *idata)
+{
+ uint32_t ix, cnt, off, len;
+ BC_STATUS sts = BC_STS_SUCCESS;
+ uint32_t *temp;
+
+ if (!ctx || !idata)
+ return BC_STS_INV_ARG;
+
+ temp = (uint32_t *) idata->udata.u.pciCfg.pci_cfg_space;
+ off = idata->udata.u.pciCfg.Offset;
+ len = idata->udata.u.pciCfg.Size;
+
+ if (len <= 4)
+ return crystalhd_pci_cfg_rd(ctx->adp, off, len, temp);
+
+ /* Truncate to dword alignment..*/
+ len = 4;
+ cnt = idata->udata.u.pciCfg.Size / len;
+ for (ix = 0; ix < cnt; ix++) {
+ sts = crystalhd_pci_cfg_rd(ctx->adp, off, len, &temp[ix]);
+ if (sts != BC_STS_SUCCESS) {
+ BCMLOG_ERR("config read : %d\n", sts);
+ return sts;
+ }
+ off += len;
+ }
+
+ return sts;
+}
+
+static BC_STATUS bc_cproc_cfg_wr(struct crystalhd_cmd *ctx,
+ crystalhd_ioctl_data *idata)
+{
+ uint32_t ix, cnt, off, len;
+ BC_STATUS sts = BC_STS_SUCCESS;
+ uint32_t *temp;
+
+ if (!ctx || !idata)
+ return BC_STS_INV_ARG;
+
+ temp = (uint32_t *) idata->udata.u.pciCfg.pci_cfg_space;
+ off = idata->udata.u.pciCfg.Offset;
+ len = idata->udata.u.pciCfg.Size;
+
+ if (len <= 4)
+ return crystalhd_pci_cfg_wr(ctx->adp, off, len, temp[0]);
+
+ /* Truncate to dword alignment..*/
+ len = 4;
+ cnt = idata->udata.u.pciCfg.Size / len;
+ for (ix = 0; ix < cnt; ix++) {
+ sts = crystalhd_pci_cfg_wr(ctx->adp, off, len, temp[ix]);
+ if (sts != BC_STS_SUCCESS) {
+ BCMLOG_ERR("config write : %d\n", sts);
+ return sts;
+ }
+ off += len;
+ }
+
+ return sts;
+}
+
+static BC_STATUS bc_cproc_download_fw(struct crystalhd_cmd *ctx,
+ crystalhd_ioctl_data *idata)
+{
+ BC_STATUS sts = BC_STS_SUCCESS;
+
+ if (!ctx || !idata || !idata->add_cdata || !idata->add_cdata_sz) {
+ BCMLOG_ERR("Invalid Arg!!\n");
+ return BC_STS_INV_ARG;
+ }
+
+ if (ctx->state != BC_LINK_INVALID) {
+ BCMLOG_ERR("Link invalid state %d \n", ctx->state);
+ return BC_STS_ERR_USAGE;
+ }
+
+ sts = crystalhd_download_fw(ctx->adp, (uint8_t *)idata->add_cdata,
+ idata->add_cdata_sz);
+
+ if (sts != BC_STS_SUCCESS) {
+ BCMLOG_ERR("Firmware Download Failure!! - %d\n", sts);
+ } else
+ ctx->state |= BC_LINK_INIT;
+
+ return sts;
+}
+
+/*
+ * We use the FW_CMD interface to sync up playback state with application
+ * and firmware. This function will perform the required pre and post
+ * processing of the Firmware commands.
+ *
+ * Pause -
+ * Disable capture after decoder pause.
+ * Resume -
+ * First enable capture and issue decoder resume command.
+ * Flush -
+ * Abort pending input transfers and issue decoder flush command.
+ *
+ */
+static BC_STATUS bc_cproc_do_fw_cmd(struct crystalhd_cmd *ctx, crystalhd_ioctl_data *idata)
+{
+ BC_STATUS sts;
+ uint32_t *cmd;
+
+ if (!(ctx->state & BC_LINK_INIT)) {
+ BCMLOG_ERR("Link invalid state %d \n", ctx->state);
+ return BC_STS_ERR_USAGE;
+ }
+
+ cmd = idata->udata.u.fwCmd.cmd;
+
+ /* Pre-Process */
+ if (cmd[0] == eCMD_C011_DEC_CHAN_PAUSE) {
+ if (!cmd[3]) {
+ ctx->state &= ~BC_LINK_PAUSED;
+ crystalhd_hw_unpause(&ctx->hw_ctx);
+ }
+ } else if (cmd[0] == eCMD_C011_DEC_CHAN_FLUSH) {
+ BCMLOG(BCMLOG_INFO, "Flush issued\n");
+ if (cmd[3])
+ ctx->cin_wait_exit = 1;
+ }
+
+ sts = crystalhd_do_fw_cmd(&ctx->hw_ctx, &idata->udata.u.fwCmd);
+
+ if (sts != BC_STS_SUCCESS) {
+ BCMLOG(BCMLOG_INFO, "fw cmd %x failed\n", cmd[0]);
+ return sts;
+ }
+
+ /* Post-Process */
+ if (cmd[0] == eCMD_C011_DEC_CHAN_PAUSE) {
+ if (cmd[3]) {
+ ctx->state |= BC_LINK_PAUSED;
+ crystalhd_hw_pause(&ctx->hw_ctx);
+ }
+ }
+
+ return sts;
+}
+
+static void bc_proc_in_completion(crystalhd_dio_req *dio_hnd,
+ wait_queue_head_t *event, BC_STATUS sts)
+{
+ if (!dio_hnd || !event) {
+ BCMLOG_ERR("Invalid Arg!!\n");
+ return;
+ }
+ if (sts == BC_STS_IO_USER_ABORT)
+ return;
+
+ dio_hnd->uinfo.comp_sts = sts;
+ dio_hnd->uinfo.ev_sts = 1;
+ crystalhd_set_event(event);
+}
+
+static BC_STATUS bc_cproc_codein_sleep(struct crystalhd_cmd *ctx)
+{
+ wait_queue_head_t sleep_ev;
+ int rc = 0;
+
+ if (ctx->state & BC_LINK_SUSPEND)
+ return BC_STS_IO_USER_ABORT;
+
+ if (ctx->cin_wait_exit) {
+ ctx->cin_wait_exit = 0;
+ return BC_STS_CMD_CANCELLED;
+ }
+ crystalhd_create_event(&sleep_ev);
+ crystalhd_wait_on_event(&sleep_ev, 0, 100, rc, 0);
+ if (rc == -EINTR)
+ return BC_STS_IO_USER_ABORT;
+
+ return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_hw_txdma(struct crystalhd_cmd *ctx,
+ crystalhd_ioctl_data *idata,
+ crystalhd_dio_req *dio)
+{
+ uint32_t tx_listid = 0;
+ BC_STATUS sts = BC_STS_SUCCESS;
+ wait_queue_head_t event;
+ int rc = 0;
+
+ if (!ctx || !idata || !dio) {
+ BCMLOG_ERR("Invalid Arg!!\n");
+ return BC_STS_INV_ARG;
+ }
+
+ crystalhd_create_event(&event);
+
+ ctx->tx_list_id = 0;
+ /* msleep_interruptible(2000); */
+ sts = crystalhd_hw_post_tx(&ctx->hw_ctx, dio, bc_proc_in_completion,
+ &event, &tx_listid,
+ idata->udata.u.ProcInput.Encrypted);
+
+ while (sts == BC_STS_BUSY) {
+ sts = bc_cproc_codein_sleep(ctx);
+ if (sts != BC_STS_SUCCESS)
+ break;
+ sts = crystalhd_hw_post_tx(&ctx->hw_ctx, dio,
+ bc_proc_in_completion,
+ &event, &tx_listid,
+ idata->udata.u.ProcInput.Encrypted);
+ }
+ if (sts != BC_STS_SUCCESS) {
+ BCMLOG(BCMLOG_DBG, "_hw_txdma returning sts:%d\n", sts);
+ return sts;
+ }
+ if (ctx->cin_wait_exit)
+ ctx->cin_wait_exit = 0;
+
+ ctx->tx_list_id = tx_listid;
+
+ /* _post() succeeded.. wait for the completion. */
+ crystalhd_wait_on_event(&event, (dio->uinfo.ev_sts), 3000, rc, 0);
+ ctx->tx_list_id = 0;
+ if (!rc) {
+ return dio->uinfo.comp_sts;
+ } else if (rc == -EBUSY) {
+ BCMLOG(BCMLOG_DBG, "_tx_post() T/O \n");
+ sts = BC_STS_TIMEOUT;
+ } else if (rc == -EINTR) {
+ BCMLOG(BCMLOG_DBG, "Tx Wait Signal int.\n");
+ sts = BC_STS_IO_USER_ABORT;
+ } else {
+ sts = BC_STS_IO_ERROR;
+ }
+
+ /* We are cancelling the IO from the same context as the _post().
+ * so no need to wait on the event again.. the return itself
+ * ensures the release of our resources.
+ */
+ crystalhd_hw_cancel_tx(&ctx->hw_ctx, tx_listid);
+
+ return sts;
+}
+
+/* Helper function to check on user buffers */
+static BC_STATUS bc_cproc_check_inbuffs(bool pin, void *ubuff, uint32_t ub_sz,
+ uint32_t uv_off, bool en_422)
+{
+ if (!ubuff || !ub_sz) {
+ BCMLOG_ERR("%s->Invalid Arg %p %x\n",
+ ((pin) ? "TX" : "RX"), ubuff, ub_sz);
+ return BC_STS_INV_ARG;
+ }
+
+ /* Check for alignment */
+ if (((uintptr_t)ubuff) & 0x03) {
+ BCMLOG_ERR("%s-->Un-aligned address not implemented yet.. %p \n",
+ ((pin) ? "TX" : "RX"), ubuff);
+ return BC_STS_NOT_IMPL;
+ }
+ if (pin)
+ return BC_STS_SUCCESS;
+
+ if (!en_422 && !uv_off) {
+ BCMLOG_ERR("Need UV offset for 420 mode.\n");
+ return BC_STS_INV_ARG;
+ }
+
+ if (en_422 && uv_off) {
+ BCMLOG_ERR("UV offset in 422 mode ??\n");
+ return BC_STS_INV_ARG;
+ }
+
+ return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_proc_input(struct crystalhd_cmd *ctx, crystalhd_ioctl_data *idata)
+{
+ void *ubuff;
+ uint32_t ub_sz;
+ crystalhd_dio_req *dio_hnd = NULL;
+ BC_STATUS sts = BC_STS_SUCCESS;
+
+ if (!ctx || !idata) {
+ BCMLOG_ERR("Invalid Arg!!\n");
+ return BC_STS_INV_ARG;
+ }
+
+ ubuff = idata->udata.u.ProcInput.pDmaBuff;
+ ub_sz = idata->udata.u.ProcInput.BuffSz;
+
+ sts = bc_cproc_check_inbuffs(1, ubuff, ub_sz, 0, 0);
+ if (sts != BC_STS_SUCCESS)
+ return sts;
+
+ sts = crystalhd_map_dio(ctx->adp, ubuff, ub_sz, 0, 0, 1, &dio_hnd);
+ if (sts != BC_STS_SUCCESS) {
+ BCMLOG_ERR("dio map - %d \n", sts);
+ return sts;
+ }
+
+ if (!dio_hnd)
+ return BC_STS_ERROR;
+
+ sts = bc_cproc_hw_txdma(ctx, idata, dio_hnd);
+
+ crystalhd_unmap_dio(ctx->adp, dio_hnd);
+
+ return sts;
+}
+
+static BC_STATUS bc_cproc_add_cap_buff(struct crystalhd_cmd *ctx,
+ crystalhd_ioctl_data *idata)
+{
+ void *ubuff;
+ uint32_t ub_sz, uv_off;
+ bool en_422;
+ crystalhd_dio_req *dio_hnd = NULL;
+ BC_STATUS sts = BC_STS_SUCCESS;
+
+ if (!ctx || !idata) {
+ BCMLOG_ERR("Invalid Arg!!\n");
+ return BC_STS_INV_ARG;
+ }
+
+ ubuff = idata->udata.u.RxBuffs.YuvBuff;
+ ub_sz = idata->udata.u.RxBuffs.YuvBuffSz;
+ uv_off = idata->udata.u.RxBuffs.UVbuffOffset;
+ en_422 = idata->udata.u.RxBuffs.b422Mode;
+
+ sts = bc_cproc_check_inbuffs(0, ubuff, ub_sz, uv_off, en_422);
+ if (sts != BC_STS_SUCCESS)
+ return sts;
+
+ sts = crystalhd_map_dio(ctx->adp, ubuff, ub_sz, uv_off,
+ en_422, 0, &dio_hnd);
+ if (sts != BC_STS_SUCCESS) {
+ BCMLOG_ERR("dio map - %d \n", sts);
+ return sts;
+ }
+
+ if (!dio_hnd)
+ return BC_STS_ERROR;
+
+ sts = crystalhd_hw_add_cap_buffer(&ctx->hw_ctx, dio_hnd, (ctx->state == BC_LINK_READY));
+ if ((sts != BC_STS_SUCCESS) && (sts != BC_STS_BUSY)) {
+ crystalhd_unmap_dio(ctx->adp, dio_hnd);
+ return sts;
+ }
+
+ return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_fmt_change(struct crystalhd_cmd *ctx,
+ crystalhd_dio_req *dio)
+{
+ BC_STATUS sts = BC_STS_SUCCESS;
+
+ sts = crystalhd_hw_add_cap_buffer(&ctx->hw_ctx, dio, 0);
+ if (sts != BC_STS_SUCCESS)
+ return sts;
+
+ ctx->state |= BC_LINK_FMT_CHG;
+ if (ctx->state == BC_LINK_READY)
+ sts = crystalhd_hw_start_capture(&ctx->hw_ctx);
+
+ return sts;
+}
+
+static BC_STATUS bc_cproc_fetch_frame(struct crystalhd_cmd *ctx,
+ crystalhd_ioctl_data *idata)
+{
+ crystalhd_dio_req *dio = NULL;
+ BC_STATUS sts = BC_STS_SUCCESS;
+ BC_DEC_OUT_BUFF *frame;
+
+ if (!ctx || !idata) {
+ BCMLOG_ERR("Invalid Arg!!\n");
+ return BC_STS_INV_ARG;
+ }
+
+ if (!(ctx->state & BC_LINK_CAP_EN)) {
+ BCMLOG(BCMLOG_DBG, "Capture not enabled..%x\n", ctx->state);
+ return BC_STS_ERR_USAGE;
+ }
+
+ frame = &idata->udata.u.DecOutData;
+
+ sts = crystalhd_hw_get_cap_buffer(&ctx->hw_ctx, &frame->PibInfo, &dio);
+ if (sts != BC_STS_SUCCESS)
+ return (ctx->state & BC_LINK_SUSPEND) ? BC_STS_IO_USER_ABORT : sts;
+
+ frame->Flags = dio->uinfo.comp_flags;
+
+ if (frame->Flags & COMP_FLAG_FMT_CHANGE)
+ return bc_cproc_fmt_change(ctx, dio);
+
+ frame->OutPutBuffs.YuvBuff = dio->uinfo.xfr_buff;
+ frame->OutPutBuffs.YuvBuffSz = dio->uinfo.xfr_len;
+ frame->OutPutBuffs.UVbuffOffset = dio->uinfo.uv_offset;
+ frame->OutPutBuffs.b422Mode = dio->uinfo.b422mode;
+
+ frame->OutPutBuffs.YBuffDoneSz = dio->uinfo.y_done_sz;
+ frame->OutPutBuffs.UVBuffDoneSz = dio->uinfo.uv_done_sz;
+
+ crystalhd_unmap_dio(ctx->adp, dio);
+
+ return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_start_capture(struct crystalhd_cmd *ctx,
+ crystalhd_ioctl_data *idata)
+{
+ ctx->state |= BC_LINK_CAP_EN;
+ if (ctx->state == BC_LINK_READY)
+ return crystalhd_hw_start_capture(&ctx->hw_ctx);
+
+ return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_flush_cap_buffs(struct crystalhd_cmd *ctx,
+ crystalhd_ioctl_data *idata)
+{
+ crystalhd_dio_req *dio = NULL;
+ BC_STATUS sts = BC_STS_SUCCESS;
+ BC_DEC_OUT_BUFF *frame;
+ uint32_t count;
+
+ if (!ctx || !idata) {
+ BCMLOG_ERR("Invalid Arg!!\n");
+ return BC_STS_INV_ARG;
+ }
+
+ if (!(ctx->state & BC_LINK_CAP_EN))
+ return BC_STS_ERR_USAGE;
+
+ /* We should ack flush even when we are in paused/suspend state */
+ if (!(ctx->state & BC_LINK_READY))
+ return crystalhd_hw_stop_capture(&ctx->hw_ctx);
+
+ ctx->state &= ~(BC_LINK_CAP_EN|BC_LINK_FMT_CHG);
+
+ frame = &idata->udata.u.DecOutData;
+ for (count = 0; count < BC_RX_LIST_CNT; count++) {
+
+ sts = crystalhd_hw_get_cap_buffer(&ctx->hw_ctx, &frame->PibInfo, &dio);
+ if (sts != BC_STS_SUCCESS)
+ break;
+
+ crystalhd_unmap_dio(ctx->adp, dio);
+ }
+
+ return crystalhd_hw_stop_capture(&ctx->hw_ctx);
+}
+
+static BC_STATUS bc_cproc_get_stats(struct crystalhd_cmd *ctx,
+ crystalhd_ioctl_data *idata)
+{
+ BC_DTS_STATS *stats;
+ struct crystalhd_hw_stats hw_stats;
+
+ if (!ctx || !idata) {
+ BCMLOG_ERR("Invalid Arg!!\n");
+ return BC_STS_INV_ARG;
+ }
+
+ crystalhd_hw_stats(&ctx->hw_ctx, &hw_stats);
+
+ stats = &idata->udata.u.drvStat;
+ stats->drvRLL = hw_stats.rdyq_count;
+ stats->drvFLL = hw_stats.freeq_count;
+ stats->DrvTotalFrmDropped = hw_stats.rx_errors;
+ stats->DrvTotalHWErrs = hw_stats.rx_errors + hw_stats.tx_errors;
+ stats->intCount = hw_stats.num_interrupts;
+ stats->DrvIgnIntrCnt = hw_stats.num_interrupts -
+ hw_stats.dev_interrupts;
+ stats->TxFifoBsyCnt = hw_stats.cin_busy;
+ stats->pauseCount = hw_stats.pause_cnt;
+
+ if (ctx->pwr_state_change)
+ stats->pwr_state_change = 1;
+ if (ctx->state & BC_LINK_PAUSED)
+ stats->DrvPauseTime = 1;
+
+ return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_reset_stats(struct crystalhd_cmd *ctx,
+ crystalhd_ioctl_data *idata)
+{
+ crystalhd_hw_stats(&ctx->hw_ctx, NULL);
+
+ return BC_STS_SUCCESS;
+}
+
+static BC_STATUS bc_cproc_chg_clk(struct crystalhd_cmd *ctx,
+ crystalhd_ioctl_data *idata)
+{
+ BC_CLOCK *clock;
+ uint32_t oldClk;
+ BC_STATUS sts = BC_STS_SUCCESS;
+
+ if (!ctx || !idata) {
+ BCMLOG_ERR("Invalid Arg!!\n");
+ return BC_STS_INV_ARG;
+ }
+
+ clock = &idata->udata.u.clockValue;
+ oldClk = ctx->hw_ctx.core_clock_mhz;
+ ctx->hw_ctx.core_clock_mhz = clock->clk;
+
+ if (ctx->state & BC_LINK_READY) {
+ sts = crystalhd_hw_set_core_clock(&ctx->hw_ctx);
+ if (sts == BC_STS_CLK_NOCHG)
+ ctx->hw_ctx.core_clock_mhz = oldClk;
+ }
+
+ clock->clk = ctx->hw_ctx.core_clock_mhz;
+
+ return sts;
+}
+
+/*=============== Cmd Proc Table.. ======================================*/
+static const crystalhd_cmd_tbl_t g_crystalhd_cproc_tbl[] = {
+ { BCM_IOC_GET_VERSION, bc_cproc_get_version, 0},
+ { BCM_IOC_GET_HWTYPE, bc_cproc_get_hwtype, 0},
+ { BCM_IOC_REG_RD, bc_cproc_reg_rd, 0},
+ { BCM_IOC_REG_WR, bc_cproc_reg_wr, 0},
+ { BCM_IOC_FPGA_RD, bc_cproc_link_reg_rd, 0},
+ { BCM_IOC_FPGA_WR, bc_cproc_link_reg_wr, 0},
+ { BCM_IOC_MEM_RD, bc_cproc_mem_rd, 0},
+ { BCM_IOC_MEM_WR, bc_cproc_mem_wr, 0},
+ { BCM_IOC_RD_PCI_CFG, bc_cproc_cfg_rd, 0},
+ { BCM_IOC_WR_PCI_CFG, bc_cproc_cfg_wr, 1},
+ { BCM_IOC_FW_DOWNLOAD, bc_cproc_download_fw, 1},
+ { BCM_IOC_FW_CMD, bc_cproc_do_fw_cmd, 1},
+ { BCM_IOC_PROC_INPUT, bc_cproc_proc_input, 1},
+ { BCM_IOC_ADD_RXBUFFS, bc_cproc_add_cap_buff, 1},
+ { BCM_IOC_FETCH_RXBUFF, bc_cproc_fetch_frame, 1},
+ { BCM_IOC_START_RX_CAP, bc_cproc_start_capture, 1},
+ { BCM_IOC_FLUSH_RX_CAP, bc_cproc_flush_cap_buffs, 1},
+ { BCM_IOC_GET_DRV_STAT, bc_cproc_get_stats, 0},
+ { BCM_IOC_RST_DRV_STAT, bc_cproc_reset_stats, 0},
+ { BCM_IOC_NOTIFY_MODE, bc_cproc_notify_mode, 0},
+ { BCM_IOC_CHG_CLK, bc_cproc_chg_clk, 0},
+ { BCM_IOC_END, NULL},
+};
+
+/*=============== Cmd Proc Functions.. ===================================*/
+
+/**
+ * crystalhd_suspend - Power management suspend request.
+ * @ctx: Command layer context.
+ * @idata: Iodata - required for internal use.
+ *
+ * Return:
+ * status
+ *
+ * 1. Set the state to Suspend.
+ * 2. Flush the Rx Buffers it will unmap all the buffers and
+ * stop the RxDMA engine.
+ * 3. Cancel The TX Io and Stop Dma Engine.
+ * 4. Put the DDR in to deep sleep.
+ * 5. Stop the hardware putting it in to Reset State.
+ *
+ * Current gstreamer frame work does not provide any power management
+ * related notification to user mode decoder plug-in. As a work-around
+ * we pass on the power mangement notification to our plug-in by completing
+ * all outstanding requests with BC_STS_IO_USER_ABORT return code.
+ */
+BC_STATUS crystalhd_suspend(struct crystalhd_cmd *ctx, crystalhd_ioctl_data *idata)
+{
+ BC_STATUS sts = BC_STS_SUCCESS;
+
+ if (!ctx || !idata) {
+ BCMLOG_ERR("Invalid Parameters\n");
+ return BC_STS_ERROR;
+ }
+
+ if (ctx->state & BC_LINK_SUSPEND)
+ return BC_STS_SUCCESS;
+
+ if (ctx->state == BC_LINK_INVALID) {
+ BCMLOG(BCMLOG_DBG, "Nothing To Do Suspend Success\n");
+ return BC_STS_SUCCESS;
+ }
+
+ ctx->state |= BC_LINK_SUSPEND;
+
+ bc_cproc_mark_pwr_state(ctx);
+
+ if (ctx->state & BC_LINK_CAP_EN) {
+ sts = bc_cproc_flush_cap_buffs(ctx, idata);
+ if (sts != BC_STS_SUCCESS)
+ return sts;
+ }
+
+ if (ctx->tx_list_id) {
+ sts = crystalhd_hw_cancel_tx(&ctx->hw_ctx, ctx->tx_list_id);
+ if (sts != BC_STS_SUCCESS)
+ return sts;
+ }
+
+ sts = crystalhd_hw_suspend(&ctx->hw_ctx);
+ if (sts != BC_STS_SUCCESS)
+ return sts;
+
+ BCMLOG(BCMLOG_DBG, "BCM70012 suspend success\n");
+
+ return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_resume - Resume frame capture.
+ * @ctx: Command layer contextx.
+ *
+ * Return:
+ * status
+ *
+ *
+ * Resume frame capture.
+ *
+ * PM_Resume can't resume the playback state back to pre-suspend state
+ * because we don't keep video clip related information within driver.
+ * To get back to the pre-suspend state App will re-open the device and
+ * start a new playback session from the pre-suspend clip position.
+ *
+ */
+BC_STATUS crystalhd_resume(struct crystalhd_cmd *ctx)
+{
+ BCMLOG(BCMLOG_DBG, "crystalhd_resume Success %x\n", ctx->state);
+
+ bc_cproc_mark_pwr_state(ctx);
+
+ return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_user_open - Create application handle.
+ * @ctx: Command layer contextx.
+ * @user_ctx: User ID context.
+ *
+ * Return:
+ * status
+ *
+ * Creates an application specific UID and allocates
+ * application specific resources. HW layer initialization
+ * is done for the first open request.
+ */
+BC_STATUS crystalhd_user_open(struct crystalhd_cmd *ctx,
+ struct crystalhd_user **user_ctx)
+{
+ struct crystalhd_user *uc;
+
+ if (!ctx || !user_ctx) {
+ BCMLOG_ERR("Invalid arg..\n");
+ return BC_STS_INV_ARG;
+ }
+
+ uc = bc_cproc_get_uid(ctx);
+ if (!uc) {
+ BCMLOG(BCMLOG_INFO, "No free user context...\n");
+ return BC_STS_BUSY;
+ }
+
+ BCMLOG(BCMLOG_INFO, "Opening new user[%x] handle\n", uc->uid);
+
+ crystalhd_hw_open(&ctx->hw_ctx, ctx->adp);
+
+ uc->in_use = 1;
+
+ *user_ctx = uc;
+
+ return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_user_close - Close application handle.
+ * @ctx: Command layer contextx.
+ * @uc: User ID context.
+ *
+ * Return:
+ * status
+ *
+ * Closer aplication handle and release app specific
+ * resources.
+ */
+BC_STATUS crystalhd_user_close(struct crystalhd_cmd *ctx, struct crystalhd_user *uc)
+{
+ uint32_t mode = uc->mode;
+
+ ctx->user[uc->uid].mode = DTS_MODE_INV;
+ ctx->user[uc->uid].in_use = 0;
+ ctx->cin_wait_exit = 1;
+ ctx->pwr_state_change = 0;
+
+ BCMLOG(BCMLOG_INFO, "Closing user[%x] handle\n", uc->uid);
+
+ if ((mode == DTS_DIAG_MODE) || (mode == DTS_PLAYBACK_MODE)) {
+ crystalhd_hw_free_dma_rings(&ctx->hw_ctx);
+ crystalhd_destroy_dio_pool(ctx->adp);
+ } else if (bc_cproc_get_user_count(ctx)) {
+ return BC_STS_SUCCESS;
+ }
+
+ crystalhd_hw_close(&ctx->hw_ctx);
+
+ ctx->state = BC_LINK_INVALID;
+
+ return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_setup_cmd_context - Setup Command layer resources.
+ * @ctx: Command layer contextx.
+ * @adp: Adapter context
+ *
+ * Return:
+ * status
+ *
+ * Called at the time of driver load.
+ */
+BC_STATUS __devinit crystalhd_setup_cmd_context(struct crystalhd_cmd *ctx,
+ struct crystalhd_adp *adp)
+{
+ int i = 0;
+
+ if (!ctx || !adp) {
+ BCMLOG_ERR("Invalid arg!!\n");
+ return BC_STS_INV_ARG;
+ }
+
+ if (ctx->adp)
+ BCMLOG(BCMLOG_DBG, "Resetting Cmd context delete missing..\n");
+
+ ctx->adp = adp;
+ for (i = 0; i < BC_LINK_MAX_OPENS; i++) {
+ ctx->user[i].uid = i;
+ ctx->user[i].in_use = 0;
+ ctx->user[i].mode = DTS_MODE_INV;
+ }
+
+ /*Open and Close the Hardware to put it in to sleep state*/
+ crystalhd_hw_open(&ctx->hw_ctx, ctx->adp);
+ crystalhd_hw_close(&ctx->hw_ctx);
+ return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_delete_cmd_context - Release Command layer resources.
+ * @ctx: Command layer contextx.
+ *
+ * Return:
+ * status
+ *
+ * Called at the time of driver un-load.
+ */
+BC_STATUS __devexit crystalhd_delete_cmd_context(struct crystalhd_cmd *ctx)
+{
+ BCMLOG(BCMLOG_DBG, "Deleting Command context..\n");
+
+ ctx->adp = NULL;
+
+ return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_get_cmd_proc - Cproc table lookup.
+ * @ctx: Command layer contextx.
+ * @cmd: IOCTL command code.
+ * @uc: User ID context.
+ *
+ * Return:
+ * command proc function pointer
+ *
+ * This function checks the process context, application's
+ * mode of operation and returns the function pointer
+ * from the cproc table.
+ */
+crystalhd_cmd_proc crystalhd_get_cmd_proc(struct crystalhd_cmd *ctx, uint32_t cmd,
+ struct crystalhd_user *uc)
+{
+ crystalhd_cmd_proc cproc = NULL;
+ unsigned int i, tbl_sz;
+
+ if (!ctx) {
+ BCMLOG_ERR("Invalid arg.. Cmd[%d]\n", cmd);
+ return NULL;
+ }
+
+ if ((cmd != BCM_IOC_GET_DRV_STAT) && (ctx->state & BC_LINK_SUSPEND)) {
+ BCMLOG_ERR("Invalid State [suspend Set].. Cmd[%d]\n", cmd);
+ return NULL;
+ }
+
+ tbl_sz = sizeof(g_crystalhd_cproc_tbl) / sizeof(crystalhd_cmd_tbl_t);
+ for (i = 0; i < tbl_sz; i++) {
+ if (g_crystalhd_cproc_tbl[i].cmd_id == cmd) {
+ if ((uc->mode == DTS_MONITOR_MODE) &&
+ (g_crystalhd_cproc_tbl[i].block_mon)) {
+ BCMLOG(BCMLOG_INFO, "Blocking cmd %d \n", cmd);
+ break;
+ }
+ cproc = g_crystalhd_cproc_tbl[i].cmd_proc;
+ break;
+ }
+ }
+
+ return cproc;
+}
+
+/**
+ * crystalhd_cmd_interrupt - ISR entry point
+ * @ctx: Command layer contextx.
+ *
+ * Return:
+ * TRUE: If interrupt from bcm70012 device.
+ *
+ *
+ * ISR entry point from OS layer.
+ */
+bool crystalhd_cmd_interrupt(struct crystalhd_cmd *ctx)
+{
+ if (!ctx) {
+ BCMLOG_ERR("Invalid arg..\n");
+ return 0;
+ }
+
+ return crystalhd_hw_interrupt(ctx->adp, &ctx->hw_ctx);
+}
diff --git a/drivers/staging/crystalhd/crystalhd_cmds.h b/drivers/staging/crystalhd/crystalhd_cmds.h
new file mode 100644
index 00000000000..6b290aed8e0
--- /dev/null
+++ b/drivers/staging/crystalhd/crystalhd_cmds.h
@@ -0,0 +1,88 @@
+/***************************************************************************
+ * Copyright (c) 2005-2009, Broadcom Corporation.
+ *
+ * Name: crystalhd_cmds . h
+ *
+ * Description:
+ * BCM70010 Linux driver user command interfaces.
+ *
+ * HISTORY:
+ *
+ **********************************************************************
+ * This file is part of the crystalhd device driver.
+ *
+ * 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, version 2 of the License.
+ *
+ * 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 driver. If not, see <http://www.gnu.org/licenses/>.
+ **********************************************************************/
+
+#ifndef _CRYSTALHD_CMDS_H_
+#define _CRYSTALHD_CMDS_H_
+
+/*
+ * NOTE:: This is the main interface file between the Linux layer
+ * and the harware layer. This file will use the definitions
+ * from _dts_glob and dts_defs etc.. which are defined for
+ * windows.
+ */
+#include "crystalhd_misc.h"
+#include "crystalhd_hw.h"
+
+enum _crystalhd_state{
+ BC_LINK_INVALID = 0x00,
+ BC_LINK_INIT = 0x01,
+ BC_LINK_CAP_EN = 0x02,
+ BC_LINK_FMT_CHG = 0x04,
+ BC_LINK_SUSPEND = 0x10,
+ BC_LINK_PAUSED = 0x20,
+ BC_LINK_READY = (BC_LINK_INIT | BC_LINK_CAP_EN | BC_LINK_FMT_CHG),
+};
+
+struct crystalhd_user {
+ uint32_t uid;
+ uint32_t in_use;
+ uint32_t mode;
+};
+
+#define DTS_MODE_INV (-1)
+
+struct crystalhd_cmd {
+ uint32_t state;
+ struct crystalhd_adp *adp;
+ struct crystalhd_user user[BC_LINK_MAX_OPENS];
+
+ spinlock_t ctx_lock;
+ uint32_t tx_list_id;
+ uint32_t cin_wait_exit;
+ uint32_t pwr_state_change;
+ struct crystalhd_hw hw_ctx;
+};
+
+typedef BC_STATUS (*crystalhd_cmd_proc)(struct crystalhd_cmd *, crystalhd_ioctl_data *);
+
+typedef struct _crystalhd_cmd_tbl {
+ uint32_t cmd_id;
+ const crystalhd_cmd_proc cmd_proc;
+ uint32_t block_mon;
+} crystalhd_cmd_tbl_t;
+
+
+BC_STATUS crystalhd_suspend(struct crystalhd_cmd *ctx, crystalhd_ioctl_data *idata);
+BC_STATUS crystalhd_resume(struct crystalhd_cmd *ctx);
+crystalhd_cmd_proc crystalhd_get_cmd_proc(struct crystalhd_cmd *ctx, uint32_t cmd,
+ struct crystalhd_user *uc);
+BC_STATUS crystalhd_user_open(struct crystalhd_cmd *ctx, struct crystalhd_user **user_ctx);
+BC_STATUS crystalhd_user_close(struct crystalhd_cmd *ctx, struct crystalhd_user *uc);
+BC_STATUS crystalhd_setup_cmd_context(struct crystalhd_cmd *ctx, struct crystalhd_adp *adp);
+BC_STATUS crystalhd_delete_cmd_context(struct crystalhd_cmd *ctx);
+bool crystalhd_cmd_interrupt(struct crystalhd_cmd *ctx);
+
+#endif
diff --git a/drivers/staging/crystalhd/crystalhd_fw_if.h b/drivers/staging/crystalhd/crystalhd_fw_if.h
new file mode 100644
index 00000000000..261cd19a0ee
--- /dev/null
+++ b/drivers/staging/crystalhd/crystalhd_fw_if.h
@@ -0,0 +1,369 @@
+/***************************************************************************
+ * Copyright (c) 2005-2009, Broadcom Corporation.
+ *
+ * Name: crystalhd_fw_if . h
+ *
+ * Description:
+ * BCM70012 Firmware interface definitions.
+ *
+ * HISTORY:
+ *
+ **********************************************************************
+ * This file is part of the crystalhd device driver.
+ *
+ * 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, version 2 of the License.
+ *
+ * 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 driver. If not, see <http://www.gnu.org/licenses/>.
+ **********************************************************************/
+
+#ifndef _CRYSTALHD_FW_IF_H_
+#define _CRYSTALHD_FW_IF_H_
+
+/* TBD: Pull in only required defs into this file.. */
+
+
+
+/* User Data Header */
+typedef struct user_data {
+ struct user_data *next;
+ uint32_t type;
+ uint32_t size;
+} UD_HDR;
+
+
+
+/*------------------------------------------------------*
+ * MPEG Extension to the PPB *
+ *------------------------------------------------------*/
+typedef struct {
+ uint32_t to_be_defined;
+ uint32_t valid;
+
+ /* Always valid, defaults to picture size if no
+ sequence display extension in the stream. */
+ uint32_t display_horizontal_size;
+ uint32_t display_vertical_size;
+
+ /* MPEG_VALID_PANSCAN
+ Offsets are a copy values from the MPEG stream. */
+ uint32_t offset_count;
+ int32_t horizontal_offset[3];
+ int32_t vertical_offset[3];
+
+ /* MPEG_VALID_USERDATA
+ User data is in the form of a linked list. */
+ int32_t userDataSize;
+ UD_HDR *userData;
+
+} PPB_MPEG;
+
+
+/*------------------------------------------------------*
+ * VC1 Extension to the PPB *
+ *------------------------------------------------------*/
+typedef struct {
+ uint32_t to_be_defined;
+ uint32_t valid;
+
+ /* Always valid, defaults to picture size if no
+ sequence display extension in the stream. */
+ uint32_t display_horizontal_size;
+ uint32_t display_vertical_size;
+
+ /* VC1 pan scan windows */
+ uint32_t num_panscan_windows;
+ int32_t ps_horiz_offset[4];
+ int32_t ps_vert_offset[4];
+ int32_t ps_width[4];
+ int32_t ps_height[4];
+
+ /* VC1_VALID_USERDATA
+ User data is in the form of a linked list. */
+ int32_t userDataSize;
+ UD_HDR *userData;
+
+} PPB_VC1;
+
+/*------------------------------------------------------*
+ * H.264 Extension to the PPB *
+ *------------------------------------------------------*/
+
+/**
+ * @brief Film grain SEI message.
+ *
+ * Content of the film grain SEI message.
+ */
+
+/* maximum number of model-values as for Thomson spec(standard says 5) */
+#define MAX_FGT_MODEL_VALUE (3)
+
+/* maximum number of intervals(as many as 256 intervals?) */
+#define MAX_FGT_VALUE_INTERVAL (256)
+
+typedef struct FGT_SEI {
+ struct FGT_SEI *next;
+ unsigned char model_values[3][MAX_FGT_VALUE_INTERVAL][MAX_FGT_MODEL_VALUE];
+ unsigned char upper_bound[3][MAX_FGT_VALUE_INTERVAL];
+ unsigned char lower_bound[3][MAX_FGT_VALUE_INTERVAL];
+
+ unsigned char cancel_flag; /* Cancel flag: 1 no film grain. */
+ unsigned char model_id; /* Model id. */
+
+ /* +unused SE based on Thomson spec */
+ unsigned char color_desc_flag; /* Separate color descrition flag. */
+ unsigned char bit_depth_luma; /* Bit depth luma minus 8. */
+ unsigned char bit_depth_chroma; /* Bit depth chroma minus 8. */
+ unsigned char full_range_flag; /* Full range flag. */
+ unsigned char color_primaries; /* Color primaries. */
+ unsigned char transfer_charact; /* Transfer characteristics. */
+ unsigned char matrix_coeff; /*< Matrix coefficients. */
+ /* -unused SE based on Thomson spec */
+
+ unsigned char blending_mode_id; /* Blending mode. */
+ unsigned char log2_scale_factor; /* Log2 scale factor (2-7). */
+ unsigned char comp_flag[3]; /* Components [0,2] parameters present flag. */
+ unsigned char num_intervals_minus1[3]; /* Number of intensity level intervals. */
+ unsigned char num_model_values[3]; /* Number of model values. */
+ uint16_t repetition_period; /* Repetition period (0-16384) */
+
+} FGT_SEI;
+
+typedef struct {
+ /* 'valid' specifies which fields (or sets of
+ * fields) below are valid. If the corresponding
+ * bit in 'valid' is NOT set then that field(s)
+ * is (are) not initialized. */
+ uint32_t valid;
+
+ int32_t poc_top; /* POC for Top Field/Frame */
+ int32_t poc_bottom; /* POC for Bottom Field */
+ uint32_t idr_pic_id;
+
+ /* H264_VALID_PANSCAN */
+ uint32_t pan_scan_count;
+ int32_t pan_scan_left[3];
+ int32_t pan_scan_right[3];
+ int32_t pan_scan_top[3];
+ int32_t pan_scan_bottom[3];
+
+ /* H264_VALID_CT_TYPE */
+ uint32_t ct_type_count;
+ uint32_t ct_type[3];
+
+ /* H264_VALID_SPS_CROP */
+ int32_t sps_crop_left;
+ int32_t sps_crop_right;
+ int32_t sps_crop_top;
+ int32_t sps_crop_bottom;
+
+ /* H264_VALID_VUI */
+ uint32_t chroma_top;
+ uint32_t chroma_bottom;
+
+ /* H264_VALID_USER */
+ uint32_t user_data_size;
+ UD_HDR *user_data;
+
+ /* H264 VALID FGT */
+ FGT_SEI *pfgt;
+
+} PPB_H264;
+
+typedef struct {
+ /* Common fields. */
+ uint32_t picture_number; /* Ordinal display number */
+ uint32_t video_buffer; /* Video (picbuf) number */
+ uint32_t video_address; /* Address of picbuf Y */
+ uint32_t video_address_uv; /* Address of picbuf UV */
+ uint32_t video_stripe; /* Picbuf stripe */
+ uint32_t video_width; /* Picbuf width */
+ uint32_t video_height; /* Picbuf height */
+
+ uint32_t channel_id; /* Decoder channel ID */
+ uint32_t status; /* reserved */
+ uint32_t width; /* pixels */
+ uint32_t height; /* pixels */
+ uint32_t chroma_format; /* see above */
+ uint32_t pulldown; /* see above */
+ uint32_t flags; /* see above */
+ uint32_t pts; /* 32 LSBs of PTS */
+ uint32_t protocol; /* protocolXXX (above) */
+
+ uint32_t frame_rate; /* see above */
+ uint32_t matrix_coeff; /* see above */
+ uint32_t aspect_ratio; /* see above */
+ uint32_t colour_primaries; /* see above */
+ uint32_t transfer_char; /* see above */
+ uint32_t pcr_offset; /* 45kHz if PCR type; else 27MHz */
+ uint32_t n_drop; /* Number of pictures to be dropped */
+
+ uint32_t custom_aspect_ratio_width_height;
+ /* upper 16-bits is Y and lower 16-bits is X */
+
+ uint32_t picture_tag; /* Indexing tag from BUD packets */
+ uint32_t picture_done_payload;
+ uint32_t picture_meta_payload;
+ uint32_t reserved[1];
+
+ /* Protocol-specific extensions. */
+ union {
+ PPB_H264 h264;
+ PPB_MPEG mpeg;
+ PPB_VC1 vc1;
+ } other;
+
+} PPB;
+
+typedef struct {
+ uint32_t bFormatChange;
+ uint32_t resolution;
+ uint32_t channelId;
+ uint32_t ppbPtr;
+ int32_t ptsStcOffset;
+ uint32_t zeroPanscanValid;
+ uint32_t dramOutBufAddr;
+ uint32_t yComponent;
+ PPB ppb;
+
+} C011_PIB;
+
+
+
+typedef struct {
+ uint32_t command;
+ uint32_t sequence;
+ uint32_t status;
+ uint32_t picBuf;
+ uint32_t picRelBuf;
+ uint32_t picInfoDeliveryQ;
+ uint32_t picInfoReleaseQ;
+ uint32_t channelStatus;
+ uint32_t userDataDeliveryQ;
+ uint32_t userDataReleaseQ;
+ uint32_t transportStreamCaptureAddr;
+ uint32_t asyncEventQ;
+
+} DecRspChannelStartVideo;
+
+#define eCMD_C011_CMD_BASE (0x73763000)
+
+/* host commands */
+typedef enum {
+ eCMD_TS_GET_NEXT_PIC = 0x7376F100, /* debug get next picture */
+ eCMD_TS_GET_LAST_PIC = 0x7376F102, /* debug get last pic status */
+ eCMD_TS_READ_WRITE_MEM = 0x7376F104, /* debug read write memory */
+
+ /* New API commands */
+ /* General commands */
+ eCMD_C011_INIT = eCMD_C011_CMD_BASE + 0x01,
+ eCMD_C011_RESET = eCMD_C011_CMD_BASE + 0x02,
+ eCMD_C011_SELF_TEST = eCMD_C011_CMD_BASE + 0x03,
+ eCMD_C011_GET_VERSION = eCMD_C011_CMD_BASE + 0x04,
+ eCMD_C011_GPIO = eCMD_C011_CMD_BASE + 0x05,
+ eCMD_C011_DEBUG_SETUP = eCMD_C011_CMD_BASE + 0x06,
+
+ /* Decoding commands */
+ eCMD_C011_DEC_CHAN_OPEN = eCMD_C011_CMD_BASE + 0x100,
+ eCMD_C011_DEC_CHAN_CLOSE = eCMD_C011_CMD_BASE + 0x101,
+ eCMD_C011_DEC_CHAN_ACTIVATE = eCMD_C011_CMD_BASE + 0x102,
+ eCMD_C011_DEC_CHAN_STATUS = eCMD_C011_CMD_BASE + 0x103,
+ eCMD_C011_DEC_CHAN_FLUSH = eCMD_C011_CMD_BASE + 0x104,
+ eCMD_C011_DEC_CHAN_TRICK_PLAY = eCMD_C011_CMD_BASE + 0x105,
+ eCMD_C011_DEC_CHAN_TS_PIDS = eCMD_C011_CMD_BASE + 0x106,
+ eCMD_C011_DEC_CHAN_PS_STREAM_ID = eCMD_C011_CMD_BASE + 0x107,
+ eCMD_C011_DEC_CHAN_INPUT_PARAMS = eCMD_C011_CMD_BASE + 0x108,
+ eCMD_C011_DEC_CHAN_VIDEO_OUTPUT = eCMD_C011_CMD_BASE + 0x109,
+ eCMD_C011_DEC_CHAN_OUTPUT_FORMAT = eCMD_C011_CMD_BASE + 0x10A,
+ eCMD_C011_DEC_CHAN_SCALING_FILTERS = eCMD_C011_CMD_BASE + 0x10B,
+ eCMD_C011_DEC_CHAN_OSD_MODE = eCMD_C011_CMD_BASE + 0x10D,
+ eCMD_C011_DEC_CHAN_DROP = eCMD_C011_CMD_BASE + 0x10E,
+ eCMD_C011_DEC_CHAN_RELEASE = eCMD_C011_CMD_BASE + 0x10F,
+ eCMD_C011_DEC_CHAN_STREAM_SETTINGS = eCMD_C011_CMD_BASE + 0x110,
+ eCMD_C011_DEC_CHAN_PAUSE_OUTPUT = eCMD_C011_CMD_BASE + 0x111,
+ eCMD_C011_DEC_CHAN_CHANGE = eCMD_C011_CMD_BASE + 0x112,
+ eCMD_C011_DEC_CHAN_SET_STC = eCMD_C011_CMD_BASE + 0x113,
+ eCMD_C011_DEC_CHAN_SET_PTS = eCMD_C011_CMD_BASE + 0x114,
+ eCMD_C011_DEC_CHAN_CC_MODE = eCMD_C011_CMD_BASE + 0x115,
+ eCMD_C011_DEC_CREATE_AUDIO_CONTEXT = eCMD_C011_CMD_BASE + 0x116,
+ eCMD_C011_DEC_COPY_AUDIO_CONTEXT = eCMD_C011_CMD_BASE + 0x117,
+ eCMD_C011_DEC_DELETE_AUDIO_CONTEXT = eCMD_C011_CMD_BASE + 0x118,
+ eCMD_C011_DEC_CHAN_SET_DECYPTION = eCMD_C011_CMD_BASE + 0x119,
+ eCMD_C011_DEC_CHAN_START_VIDEO = eCMD_C011_CMD_BASE + 0x11A,
+ eCMD_C011_DEC_CHAN_STOP_VIDEO = eCMD_C011_CMD_BASE + 0x11B,
+ eCMD_C011_DEC_CHAN_PIC_CAPTURE = eCMD_C011_CMD_BASE + 0x11C,
+ eCMD_C011_DEC_CHAN_PAUSE = eCMD_C011_CMD_BASE + 0x11D,
+ eCMD_C011_DEC_CHAN_PAUSE_STATE = eCMD_C011_CMD_BASE + 0x11E,
+ eCMD_C011_DEC_CHAN_SET_SLOWM_RATE = eCMD_C011_CMD_BASE + 0x11F,
+ eCMD_C011_DEC_CHAN_GET_SLOWM_RATE = eCMD_C011_CMD_BASE + 0x120,
+ eCMD_C011_DEC_CHAN_SET_FF_RATE = eCMD_C011_CMD_BASE + 0x121,
+ eCMD_C011_DEC_CHAN_GET_FF_RATE = eCMD_C011_CMD_BASE + 0x122,
+ eCMD_C011_DEC_CHAN_FRAME_ADVANCE = eCMD_C011_CMD_BASE + 0x123,
+ eCMD_C011_DEC_CHAN_SET_SKIP_PIC_MODE = eCMD_C011_CMD_BASE + 0x124,
+ eCMD_C011_DEC_CHAN_GET_SKIP_PIC_MODE = eCMD_C011_CMD_BASE + 0x125,
+ eCMD_C011_DEC_CHAN_FILL_PIC_BUF = eCMD_C011_CMD_BASE + 0x126,
+ eCMD_C011_DEC_CHAN_SET_CONTINUITY_CHECK = eCMD_C011_CMD_BASE + 0x127,
+ eCMD_C011_DEC_CHAN_GET_CONTINUITY_CHECK = eCMD_C011_CMD_BASE + 0x128,
+ eCMD_C011_DEC_CHAN_SET_BRCM_TRICK_MODE = eCMD_C011_CMD_BASE + 0x129,
+ eCMD_C011_DEC_CHAN_GET_BRCM_TRICK_MODE = eCMD_C011_CMD_BASE + 0x12A,
+ eCMD_C011_DEC_CHAN_REVERSE_FIELD_STATUS = eCMD_C011_CMD_BASE + 0x12B,
+ eCMD_C011_DEC_CHAN_I_PICTURE_FOUND = eCMD_C011_CMD_BASE + 0x12C,
+ eCMD_C011_DEC_CHAN_SET_PARAMETER = eCMD_C011_CMD_BASE + 0x12D,
+ eCMD_C011_DEC_CHAN_SET_USER_DATA_MODE = eCMD_C011_CMD_BASE + 0x12E,
+ eCMD_C011_DEC_CHAN_SET_PAUSE_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x12F,
+ eCMD_C011_DEC_CHAN_SET_SLOW_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x130,
+ eCMD_C011_DEC_CHAN_SET_FF_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x131,
+ eCMD_C011_DEC_CHAN_SET_DISPLAY_TIMING_MODE = eCMD_C011_CMD_BASE + 0x132,
+ eCMD_C011_DEC_CHAN_SET_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x133,
+ eCMD_C011_DEC_CHAN_GET_DISPLAY_MODE = eCMD_C011_CMD_BASE + 0x134,
+ eCMD_C011_DEC_CHAN_SET_REVERSE_FIELD = eCMD_C011_CMD_BASE + 0x135,
+ eCMD_C011_DEC_CHAN_STREAM_OPEN = eCMD_C011_CMD_BASE + 0x136,
+ eCMD_C011_DEC_CHAN_SET_PCR_PID = eCMD_C011_CMD_BASE + 0x137,
+ eCMD_C011_DEC_CHAN_SET_VID_PID = eCMD_C011_CMD_BASE + 0x138,
+ eCMD_C011_DEC_CHAN_SET_PAN_SCAN_MODE = eCMD_C011_CMD_BASE + 0x139,
+ eCMD_C011_DEC_CHAN_START_DISPLAY_AT_PTS = eCMD_C011_CMD_BASE + 0x140,
+ eCMD_C011_DEC_CHAN_STOP_DISPLAY_AT_PTS = eCMD_C011_CMD_BASE + 0x141,
+ eCMD_C011_DEC_CHAN_SET_DISPLAY_ORDER = eCMD_C011_CMD_BASE + 0x142,
+ eCMD_C011_DEC_CHAN_GET_DISPLAY_ORDER = eCMD_C011_CMD_BASE + 0x143,
+ eCMD_C011_DEC_CHAN_SET_HOST_TRICK_MODE = eCMD_C011_CMD_BASE + 0x144,
+ eCMD_C011_DEC_CHAN_SET_OPERATION_MODE = eCMD_C011_CMD_BASE + 0x145,
+ eCMD_C011_DEC_CHAN_DISPLAY_PAUSE_UNTO_PTS = eCMD_C011_CMD_BASE + 0x146,
+ eCMD_C011_DEC_CHAN_SET_PTS_STC_DIFF_THRESHOLD = eCMD_C011_CMD_BASE + 0x147,
+ eCMD_C011_DEC_CHAN_SEND_COMPRESSED_BUF = eCMD_C011_CMD_BASE + 0x148,
+ eCMD_C011_DEC_CHAN_SET_CLIPPING = eCMD_C011_CMD_BASE + 0x149,
+ eCMD_C011_DEC_CHAN_SET_PARAMETERS_FOR_HARD_RESET_INTERRUPT_TO_HOST
+ = eCMD_C011_CMD_BASE + 0x150,
+
+ /* Decoder RevD commands */
+ eCMD_C011_DEC_CHAN_SET_CSC = eCMD_C011_CMD_BASE + 0x180, /* color space conversion */
+ eCMD_C011_DEC_CHAN_SET_RANGE_REMAP = eCMD_C011_CMD_BASE + 0x181,
+ eCMD_C011_DEC_CHAN_SET_FGT = eCMD_C011_CMD_BASE + 0x182,
+ /* Note: 0x183 not implemented yet in Rev D main */
+ eCMD_C011_DEC_CHAN_SET_LASTPICTURE_PADDING = eCMD_C011_CMD_BASE + 0x183,
+
+ /* Decoder 7412 commands (7412-only) */
+ eCMD_C011_DEC_CHAN_SET_CONTENT_KEY = eCMD_C011_CMD_BASE + 0x190,
+ eCMD_C011_DEC_CHAN_SET_SESSION_KEY = eCMD_C011_CMD_BASE + 0x191,
+ eCMD_C011_DEC_CHAN_FMT_CHANGE_ACK = eCMD_C011_CMD_BASE + 0x192,
+
+ eCMD_C011_DEC_CHAN_CUSTOM_VIDOUT = eCMD_C011_CMD_BASE + 0x1FF,
+
+ /* Encoding commands */
+ eCMD_C011_ENC_CHAN_OPEN = eCMD_C011_CMD_BASE + 0x200,
+ eCMD_C011_ENC_CHAN_CLOSE = eCMD_C011_CMD_BASE + 0x201,
+ eCMD_C011_ENC_CHAN_ACTIVATE = eCMD_C011_CMD_BASE + 0x202,
+ eCMD_C011_ENC_CHAN_CONTROL = eCMD_C011_CMD_BASE + 0x203,
+ eCMD_C011_ENC_CHAN_STATISTICS = eCMD_C011_CMD_BASE + 0x204,
+
+ eNOTIFY_C011_ENC_CHAN_EVENT = eCMD_C011_CMD_BASE + 0x210,
+
+} eC011_TS_CMD;
+
+#endif
diff --git a/drivers/staging/crystalhd/crystalhd_hw.c b/drivers/staging/crystalhd/crystalhd_hw.c
new file mode 100644
index 00000000000..01819d34201
--- /dev/null
+++ b/drivers/staging/crystalhd/crystalhd_hw.c
@@ -0,0 +1,2395 @@
+/***************************************************************************
+ * Copyright (c) 2005-2009, Broadcom Corporation.
+ *
+ * Name: crystalhd_hw . c
+ *
+ * Description:
+ * BCM70010 Linux driver HW layer.
+ *
+ **********************************************************************
+ * This file is part of the crystalhd device driver.
+ *
+ * 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, version 2 of the License.
+ *
+ * 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 driver. If not, see <http://www.gnu.org/licenses/>.
+ **********************************************************************/
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include "crystalhd_hw.h"
+
+/* Functions internal to this file */
+
+static void crystalhd_enable_uarts(struct crystalhd_adp *adp)
+{
+ bc_dec_reg_wr(adp, UartSelectA, BSVS_UART_STREAM);
+ bc_dec_reg_wr(adp, UartSelectB, BSVS_UART_DEC_OUTER);
+}
+
+
+static void crystalhd_start_dram(struct crystalhd_adp *adp)
+{
+ bc_dec_reg_wr(adp, SDRAM_PARAM, ((40 / 5 - 1) << 0) |
+ /* tras (40ns tras)/(5ns period) -1 ((15/5 - 1) << 4) | // trcd */
+ ((15 / 5 - 1) << 7) | /* trp */
+ ((10 / 5 - 1) << 10) | /* trrd */
+ ((15 / 5 + 1) << 12) | /* twr */
+ ((2 + 1) << 16) | /* twtr */
+ ((70 / 5 - 2) << 19) | /* trfc */
+ (0 << 23));
+
+ bc_dec_reg_wr(adp, SDRAM_PRECHARGE, 0);
+ bc_dec_reg_wr(adp, SDRAM_EXT_MODE, 2);
+ bc_dec_reg_wr(adp, SDRAM_MODE, 0x132);
+ bc_dec_reg_wr(adp, SDRAM_PRECHARGE, 0);
+ bc_dec_reg_wr(adp, SDRAM_REFRESH, 0);
+ bc_dec_reg_wr(adp, SDRAM_REFRESH, 0);
+ bc_dec_reg_wr(adp, SDRAM_MODE, 0x32);
+ /* setting the refresh rate here */
+ bc_dec_reg_wr(adp, SDRAM_REF_PARAM, ((1 << 12) | 96));
+}
+
+
+static bool crystalhd_bring_out_of_rst(struct crystalhd_adp *adp)
+{
+ link_misc_perst_deco_ctrl rst_deco_cntrl;
+ link_misc_perst_clk_ctrl rst_clk_cntrl;
+ uint32_t temp;
+
+ /*
+ * Link clocks: MISC_PERST_CLOCK_CTRL Clear PLL power down bit,
+ * delay to allow PLL to lock Clear alternate clock, stop clock bits
+ */
+ rst_clk_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_CLOCK_CTRL);
+ rst_clk_cntrl.pll_pwr_dn = 0;
+ crystalhd_reg_wr(adp, MISC_PERST_CLOCK_CTRL, rst_clk_cntrl.whole_reg);
+ msleep_interruptible(50);
+
+ rst_clk_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_CLOCK_CTRL);
+ rst_clk_cntrl.stop_core_clk = 0;
+ rst_clk_cntrl.sel_alt_clk = 0;
+
+ crystalhd_reg_wr(adp, MISC_PERST_CLOCK_CTRL, rst_clk_cntrl.whole_reg);
+ msleep_interruptible(50);
+
+ /*
+ * Bus Arbiter Timeout: GISB_ARBITER_TIMER
+ * Set internal bus arbiter timeout to 40us based on core clock speed
+ * (63MHz * 40us = 0x9D8)
+ */
+ crystalhd_reg_wr(adp, GISB_ARBITER_TIMER, 0x9D8);
+
+ /*
+ * Decoder clocks: MISC_PERST_DECODER_CTRL
+ * Enable clocks while 7412 reset is asserted, delay
+ * De-assert 7412 reset
+ */
+ rst_deco_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_DECODER_CTRL);
+ rst_deco_cntrl.stop_bcm_7412_clk = 0;
+ rst_deco_cntrl.bcm7412_rst = 1;
+ crystalhd_reg_wr(adp, MISC_PERST_DECODER_CTRL, rst_deco_cntrl.whole_reg);
+ msleep_interruptible(10);
+
+ rst_deco_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_DECODER_CTRL);
+ rst_deco_cntrl.bcm7412_rst = 0;
+ crystalhd_reg_wr(adp, MISC_PERST_DECODER_CTRL, rst_deco_cntrl.whole_reg);
+ msleep_interruptible(50);
+
+ /* Disable OTP_CONTENT_MISC to 0 to disable all secure modes */
+ crystalhd_reg_wr(adp, OTP_CONTENT_MISC, 0);
+
+ /* Clear bit 29 of 0x404 */
+ temp = crystalhd_reg_rd(adp, PCIE_TL_TRANSACTION_CONFIGURATION);
+ temp &= ~BC_BIT(29);
+ crystalhd_reg_wr(adp, PCIE_TL_TRANSACTION_CONFIGURATION, temp);
+
+ /* 2.5V regulator must be set to 2.6 volts (+6%) */
+ /* FIXME: jarod: what's the point of this reg read? */
+ temp = crystalhd_reg_rd(adp, MISC_PERST_VREG_CTRL);
+ crystalhd_reg_wr(adp, MISC_PERST_VREG_CTRL, 0xF3);
+
+ return true;
+}
+
+static bool crystalhd_put_in_reset(struct crystalhd_adp *adp)
+{
+ link_misc_perst_deco_ctrl rst_deco_cntrl;
+ link_misc_perst_clk_ctrl rst_clk_cntrl;
+ uint32_t temp;
+
+ /*
+ * Decoder clocks: MISC_PERST_DECODER_CTRL
+ * Assert 7412 reset, delay
+ * Assert 7412 stop clock
+ */
+ rst_deco_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_DECODER_CTRL);
+ rst_deco_cntrl.stop_bcm_7412_clk = 1;
+ crystalhd_reg_wr(adp, MISC_PERST_DECODER_CTRL, rst_deco_cntrl.whole_reg);
+ msleep_interruptible(50);
+
+ /* Bus Arbiter Timeout: GISB_ARBITER_TIMER
+ * Set internal bus arbiter timeout to 40us based on core clock speed
+ * (6.75MHZ * 40us = 0x10E)
+ */
+ crystalhd_reg_wr(adp, GISB_ARBITER_TIMER, 0x10E);
+
+ /* Link clocks: MISC_PERST_CLOCK_CTRL
+ * Stop core clk, delay
+ * Set alternate clk, delay, set PLL power down
+ */
+ rst_clk_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_CLOCK_CTRL);
+ rst_clk_cntrl.stop_core_clk = 1;
+ rst_clk_cntrl.sel_alt_clk = 1;
+ crystalhd_reg_wr(adp, MISC_PERST_CLOCK_CTRL, rst_clk_cntrl.whole_reg);
+ msleep_interruptible(50);
+
+ rst_clk_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC_PERST_CLOCK_CTRL);
+ rst_clk_cntrl.pll_pwr_dn = 1;
+ crystalhd_reg_wr(adp, MISC_PERST_CLOCK_CTRL, rst_clk_cntrl.whole_reg);
+
+ /*
+ * Read and restore the Transaction Configuration Register
+ * after core reset
+ */
+ temp = crystalhd_reg_rd(adp, PCIE_TL_TRANSACTION_CONFIGURATION);
+
+ /*
+ * Link core soft reset: MISC3_RESET_CTRL
+ * - Write BIT[0]=1 and read it back for core reset to take place
+ */
+ crystalhd_reg_wr(adp, MISC3_RESET_CTRL, 1);
+ rst_deco_cntrl.whole_reg = crystalhd_reg_rd(adp, MISC3_RESET_CTRL);
+ msleep_interruptible(50);
+
+ /* restore the transaction configuration register */
+ crystalhd_reg_wr(adp, PCIE_TL_TRANSACTION_CONFIGURATION, temp);
+
+ return true;
+}
+
+static void crystalhd_disable_interrupts(struct crystalhd_adp *adp)
+{
+ intr_mask_reg intr_mask;
+ intr_mask.whole_reg = crystalhd_reg_rd(adp, INTR_INTR_MSK_STS_REG);
+ intr_mask.mask_pcie_err = 1;
+ intr_mask.mask_pcie_rbusmast_err = 1;
+ intr_mask.mask_pcie_rgr_bridge = 1;
+ intr_mask.mask_rx_done = 1;
+ intr_mask.mask_rx_err = 1;
+ intr_mask.mask_tx_done = 1;
+ intr_mask.mask_tx_err = 1;
+ crystalhd_reg_wr(adp, INTR_INTR_MSK_SET_REG, intr_mask.whole_reg);
+
+ return;
+}
+
+static void crystalhd_enable_interrupts(struct crystalhd_adp *adp)
+{
+ intr_mask_reg intr_mask;
+ intr_mask.whole_reg = crystalhd_reg_rd(adp, INTR_INTR_MSK_STS_REG);
+ intr_mask.mask_pcie_err = 1;
+ intr_mask.mask_pcie_rbusmast_err = 1;
+ intr_mask.mask_pcie_rgr_bridge = 1;
+ intr_mask.mask_rx_done = 1;
+ intr_mask.mask_rx_err = 1;
+ intr_mask.mask_tx_done = 1;
+ intr_mask.mask_tx_err = 1;
+ crystalhd_reg_wr(adp, INTR_INTR_MSK_CLR_REG, intr_mask.whole_reg);
+
+ return;
+}
+
+static void crystalhd_clear_errors(struct crystalhd_adp *adp)
+{
+ uint32_t reg;
+
+ /* FIXME: jarod: wouldn't we want to write a 0 to the reg? Or does the write clear the bits specified? */
+ reg = crystalhd_reg_rd(adp, MISC1_Y_RX_ERROR_STATUS);
+ if (reg)
+ crystalhd_reg_wr(adp, MISC1_Y_RX_ERROR_STATUS, reg);
+
+ reg = crystalhd_reg_rd(adp, MISC1_UV_RX_ERROR_STATUS);
+ if (reg)
+ crystalhd_reg_wr(adp, MISC1_UV_RX_ERROR_STATUS, reg);
+
+ reg = crystalhd_reg_rd(adp, MISC1_TX_DMA_ERROR_STATUS);
+ if (reg)
+ crystalhd_reg_wr(adp, MISC1_TX_DMA_ERROR_STATUS, reg);
+}
+
+static void crystalhd_clear_interrupts(struct crystalhd_adp *adp)
+{
+ uint32_t intr_sts = crystalhd_reg_rd(adp, INTR_INTR_STATUS);
+
+ if (intr_sts) {
+ crystalhd_reg_wr(adp, INTR_INTR_CLR_REG, intr_sts);
+
+ /* Write End Of Interrupt for PCIE */
+ crystalhd_reg_wr(adp, INTR_EOI_CTRL, 1);
+ }
+}
+
+static void crystalhd_soft_rst(struct crystalhd_adp *adp)
+{
+ uint32_t val;
+
+ /* Assert c011 soft reset*/
+ bc_dec_reg_wr(adp, DecHt_HostSwReset, 0x00000001);
+ msleep_interruptible(50);
+
+ /* Release c011 soft reset*/
+ bc_dec_reg_wr(adp, DecHt_HostSwReset, 0x00000000);
+
+ /* Disable Stuffing..*/
+ val = crystalhd_reg_rd(adp, MISC2_GLOBAL_CTRL);
+ val |= BC_BIT(8);
+ crystalhd_reg_wr(adp, MISC2_GLOBAL_CTRL, val);
+}
+
+static bool crystalhd_load_firmware_config(struct crystalhd_adp *adp)
+{
+ uint32_t i = 0, reg;
+
+ crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (BC_DRAM_FW_CFG_ADDR >> 19));
+
+ crystalhd_reg_wr(adp, AES_CMD, 0);
+ crystalhd_reg_wr(adp, AES_CONFIG_INFO, (BC_DRAM_FW_CFG_ADDR & 0x7FFFF));
+ crystalhd_reg_wr(adp, AES_CMD, 0x1);
+
+ /* FIXME: jarod: I've seen this fail, and introducing extra delays helps... */
+ for (i = 0; i < 100; ++i) {
+ reg = crystalhd_reg_rd(adp, AES_STATUS);
+ if (reg & 0x1)
+ return true;
+ msleep_interruptible(10);
+ }
+
+ return false;
+}
+
+
+static bool crystalhd_start_device(struct crystalhd_adp *adp)
+{
+ uint32_t dbg_options, glb_cntrl = 0, reg_pwrmgmt = 0;
+
+ BCMLOG(BCMLOG_INFO, "Starting BCM70012 Device\n");
+
+ reg_pwrmgmt = crystalhd_reg_rd(adp, PCIE_DLL_DATA_LINK_CONTROL);
+ reg_pwrmgmt &= ~ASPM_L1_ENABLE;
+
+ crystalhd_reg_wr(adp, PCIE_DLL_DATA_LINK_CONTROL, reg_pwrmgmt);
+
+ if (!crystalhd_bring_out_of_rst(adp)) {
+ BCMLOG_ERR("Failed To Bring Link Out Of Reset\n");
+ return false;
+ }
+
+ crystalhd_disable_interrupts(adp);
+
+ crystalhd_clear_errors(adp);
+
+ crystalhd_clear_interrupts(adp);
+
+ crystalhd_enable_interrupts(adp);
+
+ /* Enable the option for getting the total no. of DWORDS
+ * that have been transfered by the RXDMA engine
+ */
+ dbg_options = crystalhd_reg_rd(adp, MISC1_DMA_DEBUG_OPTIONS_REG);
+ dbg_options |= 0x10;
+ crystalhd_reg_wr(adp, MISC1_DMA_DEBUG_OPTIONS_REG, dbg_options);
+
+ /* Enable PCI Global Control options */
+ glb_cntrl = crystalhd_reg_rd(adp, MISC2_GLOBAL_CTRL);
+ glb_cntrl |= 0x100;
+ glb_cntrl |= 0x8000;
+ crystalhd_reg_wr(adp, MISC2_GLOBAL_CTRL, glb_cntrl);
+
+ crystalhd_enable_interrupts(adp);
+
+ crystalhd_soft_rst(adp);
+ crystalhd_start_dram(adp);
+ crystalhd_enable_uarts(adp);
+
+ return true;
+}
+
+static bool crystalhd_stop_device(struct crystalhd_adp *adp)
+{
+ uint32_t reg;
+
+ BCMLOG(BCMLOG_INFO, "Stopping BCM70012 Device\n");
+ /* Clear and disable interrupts */
+ crystalhd_disable_interrupts(adp);
+ crystalhd_clear_errors(adp);
+ crystalhd_clear_interrupts(adp);
+
+ if (!crystalhd_put_in_reset(adp))
+ BCMLOG_ERR("Failed to Put Link To Reset State\n");
+
+ reg = crystalhd_reg_rd(adp, PCIE_DLL_DATA_LINK_CONTROL);
+ reg |= ASPM_L1_ENABLE;
+ crystalhd_reg_wr(adp, PCIE_DLL_DATA_LINK_CONTROL, reg);
+
+ /* Set PCI Clk Req */
+ reg = crystalhd_reg_rd(adp, PCIE_CLK_REQ_REG);
+ reg |= PCI_CLK_REQ_ENABLE;
+ crystalhd_reg_wr(adp, PCIE_CLK_REQ_REG, reg);
+
+ return true;
+}
+
+static crystalhd_rx_dma_pkt *crystalhd_hw_alloc_rx_pkt(struct crystalhd_hw *hw)
+{
+ unsigned long flags = 0;
+ crystalhd_rx_dma_pkt *temp = NULL;
+
+ if (!hw)
+ return NULL;
+
+ spin_lock_irqsave(&hw->lock, flags);
+ temp = hw->rx_pkt_pool_head;
+ if (temp) {
+ hw->rx_pkt_pool_head = hw->rx_pkt_pool_head->next;
+ temp->dio_req = NULL;
+ temp->pkt_tag = 0;
+ temp->flags = 0;
+ }
+ spin_unlock_irqrestore(&hw->lock, flags);
+
+ return temp;
+}
+
+static void crystalhd_hw_free_rx_pkt(struct crystalhd_hw *hw,
+ crystalhd_rx_dma_pkt *pkt)
+{
+ unsigned long flags = 0;
+
+ if (!hw || !pkt)
+ return;
+
+ spin_lock_irqsave(&hw->lock, flags);
+ pkt->next = hw->rx_pkt_pool_head;
+ hw->rx_pkt_pool_head = pkt;
+ spin_unlock_irqrestore(&hw->lock, flags);
+}
+
+/*
+ * Call back from TX - IOQ deletion.
+ *
+ * This routine will release the TX DMA rings allocated
+ * druing setup_dma rings interface.
+ *
+ * Memory is allocated per DMA ring basis. This is just
+ * a place holder to be able to create the dio queues.
+ */
+static void crystalhd_tx_desc_rel_call_back(void *context, void *data)
+{
+}
+
+/*
+ * Rx Packet release callback..
+ *
+ * Release All user mapped capture buffers and Our DMA packets
+ * back to our free pool. The actual cleanup of the DMA
+ * ring descriptors happen during dma ring release.
+ */
+static void crystalhd_rx_pkt_rel_call_back(void *context, void *data)
+{
+ struct crystalhd_hw *hw = (struct crystalhd_hw *)context;
+ crystalhd_rx_dma_pkt *pkt = (crystalhd_rx_dma_pkt *)data;
+
+ if (!pkt || !hw) {
+ BCMLOG_ERR("Invalid arg - %p %p\n", hw, pkt);
+ return;
+ }
+
+ if (pkt->dio_req)
+ crystalhd_unmap_dio(hw->adp, pkt->dio_req);
+ else
+ BCMLOG_ERR("Missing dio_req: 0x%x\n", pkt->pkt_tag);
+
+ crystalhd_hw_free_rx_pkt(hw, pkt);
+}
+
+#define crystalhd_hw_delete_ioq(adp, q) \
+ if (q) { \
+ crystalhd_delete_dioq(adp, q); \
+ q = NULL; \
+ }
+
+static void crystalhd_hw_delete_ioqs(struct crystalhd_hw *hw)
+{
+ if (!hw)
+ return;
+
+ BCMLOG(BCMLOG_DBG, "Deleting IOQs \n");
+ crystalhd_hw_delete_ioq(hw->adp, hw->tx_actq);
+ crystalhd_hw_delete_ioq(hw->adp, hw->tx_freeq);
+ crystalhd_hw_delete_ioq(hw->adp, hw->rx_actq);
+ crystalhd_hw_delete_ioq(hw->adp, hw->rx_freeq);
+ crystalhd_hw_delete_ioq(hw->adp, hw->rx_rdyq);
+}
+
+#define crystalhd_hw_create_ioq(sts, hw, q, cb) \
+do { \
+ sts = crystalhd_create_dioq(hw->adp, &q, cb, hw); \
+ if (sts != BC_STS_SUCCESS) \
+ goto hw_create_ioq_err; \
+} while (0)
+
+/*
+ * Create IOQs..
+ *
+ * TX - Active & Free
+ * RX - Active, Ready and Free.
+ */
+static BC_STATUS crystalhd_hw_create_ioqs(struct crystalhd_hw *hw)
+{
+ BC_STATUS sts = BC_STS_SUCCESS;
+
+ if (!hw) {
+ BCMLOG_ERR("Invalid Arg!!\n");
+ return BC_STS_INV_ARG;
+ }
+
+ crystalhd_hw_create_ioq(sts, hw, hw->tx_freeq,
+ crystalhd_tx_desc_rel_call_back);
+ crystalhd_hw_create_ioq(sts, hw, hw->tx_actq,
+ crystalhd_tx_desc_rel_call_back);
+
+ crystalhd_hw_create_ioq(sts, hw, hw->rx_freeq,
+ crystalhd_rx_pkt_rel_call_back);
+ crystalhd_hw_create_ioq(sts, hw, hw->rx_rdyq,
+ crystalhd_rx_pkt_rel_call_back);
+ crystalhd_hw_create_ioq(sts, hw, hw->rx_actq,
+ crystalhd_rx_pkt_rel_call_back);
+
+ return sts;
+
+hw_create_ioq_err:
+ crystalhd_hw_delete_ioqs(hw);
+
+ return sts;
+}
+
+
+static bool crystalhd_code_in_full(struct crystalhd_adp *adp, uint32_t needed_sz,
+ bool b_188_byte_pkts, uint8_t flags)
+{
+ uint32_t base, end, writep, readp;
+ uint32_t cpbSize, cpbFullness, fifoSize;
+
+ if (flags & 0x02) { /* ASF Bit is set */
+ base = bc_dec_reg_rd(adp, REG_Dec_TsAudCDB2Base);
+ end = bc_dec_reg_rd(adp, REG_Dec_TsAudCDB2End);
+ writep = bc_dec_reg_rd(adp, REG_Dec_TsAudCDB2Wrptr);
+ readp = bc_dec_reg_rd(adp, REG_Dec_TsAudCDB2Rdptr);
+ } else if (b_188_byte_pkts) { /*Encrypted 188 byte packets*/
+ base = bc_dec_reg_rd(adp, REG_Dec_TsUser0Base);
+ end = bc_dec_reg_rd(adp, REG_Dec_TsUser0End);
+ writep = bc_dec_reg_rd(adp, REG_Dec_TsUser0Wrptr);
+ readp = bc_dec_reg_rd(adp, REG_Dec_TsUser0Rdptr);
+ } else {
+ base = bc_dec_reg_rd(adp, REG_DecCA_RegCinBase);
+ end = bc_dec_reg_rd(adp, REG_DecCA_RegCinEnd);
+ writep = bc_dec_reg_rd(adp, REG_DecCA_RegCinWrPtr);
+ readp = bc_dec_reg_rd(adp, REG_DecCA_RegCinRdPtr);
+ }
+
+ cpbSize = end - base;
+ if (writep >= readp)
+ cpbFullness = writep - readp;
+ else
+ cpbFullness = (end - base) - (readp - writep);
+
+ fifoSize = cpbSize - cpbFullness;
+
+ if (fifoSize < BC_INFIFO_THRESHOLD)
+ return true;
+
+ if (needed_sz > (fifoSize - BC_INFIFO_THRESHOLD))
+ return true;
+
+ return false;
+}
+
+static BC_STATUS crystalhd_hw_tx_req_complete(struct crystalhd_hw *hw,
+ uint32_t list_id, BC_STATUS cs)
+{
+ tx_dma_pkt *tx_req;
+
+ if (!hw || !list_id) {
+ BCMLOG_ERR("Invalid Arg..\n");
+ return BC_STS_INV_ARG;
+ }
+
+ hw->pwr_lock--;
+
+ tx_req = (tx_dma_pkt *)crystalhd_dioq_find_and_fetch(hw->tx_actq, list_id);
+ if (!tx_req) {
+ if (cs != BC_STS_IO_USER_ABORT)
+ BCMLOG_ERR("Find and Fetch Did not find req\n");
+ return BC_STS_NO_DATA;
+ }
+
+ if (tx_req->call_back) {
+ tx_req->call_back(tx_req->dio_req, tx_req->cb_event, cs);
+ tx_req->dio_req = NULL;
+ tx_req->cb_event = NULL;
+ tx_req->call_back = NULL;
+ } else {
+ BCMLOG(BCMLOG_DBG, "Missing Tx Callback - %X\n",
+ tx_req->list_tag);
+ }
+
+ /* Now put back the tx_list back in FreeQ */
+ tx_req->list_tag = 0;
+
+ return crystalhd_dioq_add(hw->tx_freeq, tx_req, false, 0);
+}
+
+static bool crystalhd_tx_list0_handler(struct crystalhd_hw *hw, uint32_t err_sts)
+{
+ uint32_t err_mask, tmp;
+ unsigned long flags = 0;
+
+ err_mask = MISC1_TX_DMA_ERROR_STATUS_TX_L0_DESC_TX_ABORT_ERRORS_MASK |
+ MISC1_TX_DMA_ERROR_STATUS_TX_L0_DMA_DATA_TX_ABORT_ERRORS_MASK |
+ MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_MASK;
+
+ if (!(err_sts & err_mask))
+ return false;
+
+ BCMLOG_ERR("Error on Tx-L0 %x \n", err_sts);
+
+ tmp = err_mask;
+
+ if (err_sts & MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_MASK)
+ tmp &= ~MISC1_TX_DMA_ERROR_STATUS_TX_L0_FIFO_FULL_ERRORS_MASK;
+
+ if (tmp) {
+ spin_lock_irqsave(&hw->lock, flags);
+ /* reset list index.*/
+ hw->tx_list_post_index = 0;
+ spin_unlock_irqrestore(&hw->lock, flags);
+ }
+
+ tmp = err_sts & err_mask;
+ crystalhd_reg_wr(hw->adp, MISC1_TX_DMA_ERROR_STATUS, tmp);
+
+ return true;
+}
+
+static bool crystalhd_tx_list1_handler(struct crystalhd_hw *hw, uint32_t err_sts)
+{
+ uint32_t err_mask, tmp;
+ unsigned long flags = 0;
+
+ err_mask = MISC1_TX_DMA_ERROR_STATUS_TX_L1_DESC_TX_ABORT_ERRORS_MASK |
+ MISC1_TX_DMA_ERROR_STATUS_TX_L1_DMA_DATA_TX_ABORT_ERRORS_MASK |
+ MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_MASK;
+
+ if (!(err_sts & err_mask))
+ return false;
+
+ BCMLOG_ERR("Error on Tx-L1 %x \n", err_sts);
+
+ tmp = err_mask;
+
+ if (err_sts & MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_MASK)
+ tmp &= ~MISC1_TX_DMA_ERROR_STATUS_TX_L1_FIFO_FULL_ERRORS_MASK;
+
+ if (tmp) {
+ spin_lock_irqsave(&hw->lock, flags);
+ /* reset list index.*/
+ hw->tx_list_post_index = 0;
+ spin_unlock_irqrestore(&hw->lock, flags);
+ }
+
+ tmp = err_sts & err_mask;
+ crystalhd_reg_wr(hw->adp, MISC1_TX_DMA_ERROR_STATUS, tmp);
+
+ return true;
+}
+
+static void crystalhd_tx_isr(struct crystalhd_hw *hw, uint32_t int_sts)
+{
+ uint32_t err_sts;
+
+ if (int_sts & INTR_INTR_STATUS_L0_TX_DMA_DONE_INTR_MASK)
+ crystalhd_hw_tx_req_complete(hw, hw->tx_ioq_tag_seed + 0,
+ BC_STS_SUCCESS);
+
+ if (int_sts & INTR_INTR_STATUS_L1_TX_DMA_DONE_INTR_MASK)
+ crystalhd_hw_tx_req_complete(hw, hw->tx_ioq_tag_seed + 1,
+ BC_STS_SUCCESS);
+
+ if (!(int_sts & (INTR_INTR_STATUS_L0_TX_DMA_ERR_INTR_MASK |
+ INTR_INTR_STATUS_L1_TX_DMA_ERR_INTR_MASK))) {
+ /* No error mask set.. */
+ return;
+ }
+
+ /* Handle Tx errors. */
+ err_sts = crystalhd_reg_rd(hw->adp, MISC1_TX_DMA_ERROR_STATUS);
+
+ if (crystalhd_tx_list0_handler(hw, err_sts))
+ crystalhd_hw_tx_req_complete(hw, hw->tx_ioq_tag_seed + 0,
+ BC_STS_ERROR);
+
+ if (crystalhd_tx_list1_handler(hw, err_sts))
+ crystalhd_hw_tx_req_complete(hw, hw->tx_ioq_tag_seed + 1,
+ BC_STS_ERROR);
+
+ hw->stats.tx_errors++;
+}
+
+static void crystalhd_hw_dump_desc(pdma_descriptor p_dma_desc,
+ uint32_t ul_desc_index, uint32_t cnt)
+{
+ uint32_t ix, ll = 0;
+
+ if (!p_dma_desc || !cnt)
+ return;
+
+ /* FIXME: jarod: perhaps a modparam desc_debug to enable this, rather than
+ * setting ll (log level, I presume) to non-zero? */
+ if (!ll)
+ return;
+
+ for (ix = ul_desc_index; ix < (ul_desc_index + cnt); ix++) {
+ BCMLOG(ll, "%s[%d] Buff[%x:%x] Next:[%x:%x] XferSz:%x Intr:%x,Last:%x\n",
+ ((p_dma_desc[ul_desc_index].dma_dir) ? "TDesc" : "RDesc"),
+ ul_desc_index,
+ p_dma_desc[ul_desc_index].buff_addr_high,
+ p_dma_desc[ul_desc_index].buff_addr_low,
+ p_dma_desc[ul_desc_index].next_desc_addr_high,
+ p_dma_desc[ul_desc_index].next_desc_addr_low,
+ p_dma_desc[ul_desc_index].xfer_size,
+ p_dma_desc[ul_desc_index].intr_enable,
+ p_dma_desc[ul_desc_index].last_rec_indicator);
+ }
+
+}
+
+static BC_STATUS crystalhd_hw_fill_desc(crystalhd_dio_req *ioreq,
+ dma_descriptor *desc,
+ dma_addr_t desc_paddr_base,
+ uint32_t sg_cnt, uint32_t sg_st_ix,
+ uint32_t sg_st_off, uint32_t xfr_sz)
+{
+ uint32_t count = 0, ix = 0, sg_ix = 0, len = 0, last_desc_ix = 0;
+ dma_addr_t desc_phy_addr = desc_paddr_base;
+ addr_64 addr_temp;
+
+ if (!ioreq || !desc || !desc_paddr_base || !xfr_sz ||
+ (!sg_cnt && !ioreq->uinfo.dir_tx)) {
+ BCMLOG_ERR("Invalid Args\n");
+ return BC_STS_INV_ARG;
+ }
+
+ for (ix = 0; ix < sg_cnt; ix++) {
+
+ /* Setup SGLE index. */
+ sg_ix = ix + sg_st_ix;
+
+ /* Get SGLE length */
+ len = crystalhd_get_sgle_len(ioreq, sg_ix);
+ if (len % 4) {
+ BCMLOG_ERR(" len in sg %d %d %d\n", len, sg_ix, sg_cnt);
+ return BC_STS_NOT_IMPL;
+ }
+ /* Setup DMA desc with Phy addr & Length at current index. */
+ addr_temp.full_addr = crystalhd_get_sgle_paddr(ioreq, sg_ix);
+ if (sg_ix == sg_st_ix) {
+ addr_temp.full_addr += sg_st_off;
+ len -= sg_st_off;
+ }
+ memset(&desc[ix], 0, sizeof(desc[ix]));
+ desc[ix].buff_addr_low = addr_temp.low_part;
+ desc[ix].buff_addr_high = addr_temp.high_part;
+ desc[ix].dma_dir = ioreq->uinfo.dir_tx;
+
+ /* Chain DMA descriptor. */
+ addr_temp.full_addr = desc_phy_addr + sizeof(dma_descriptor);
+ desc[ix].next_desc_addr_low = addr_temp.low_part;
+ desc[ix].next_desc_addr_high = addr_temp.high_part;
+
+ if ((count + len) > xfr_sz)
+ len = xfr_sz - count;
+
+ /* Debug.. */
+ if ((!len) || (len > crystalhd_get_sgle_len(ioreq, sg_ix))) {
+ BCMLOG_ERR("inv-len(%x) Ix(%d) count:%x xfr_sz:%x sg_cnt:%d\n",
+ len, ix, count, xfr_sz, sg_cnt);
+ return BC_STS_ERROR;
+ }
+ /* Length expects Multiple of 4 */
+ desc[ix].xfer_size = (len / 4);
+
+ crystalhd_hw_dump_desc(desc, ix, 1);
+
+ count += len;
+ desc_phy_addr += sizeof(dma_descriptor);
+ }
+
+ last_desc_ix = ix - 1;
+
+ if (ioreq->fb_size) {
+ memset(&desc[ix], 0, sizeof(desc[ix]));
+ addr_temp.full_addr = ioreq->fb_pa;
+ desc[ix].buff_addr_low = addr_temp.low_part;
+ desc[ix].buff_addr_high = addr_temp.high_part;
+ desc[ix].dma_dir = ioreq->uinfo.dir_tx;
+ desc[ix].xfer_size = 1;
+ desc[ix].fill_bytes = 4 - ioreq->fb_size;
+ count += ioreq->fb_size;
+ last_desc_ix++;
+ }
+
+ /* setup last descriptor..*/
+ desc[last_desc_ix].last_rec_indicator = 1;
+ desc[last_desc_ix].next_desc_addr_low = 0;
+ desc[last_desc_ix].next_desc_addr_high = 0;
+ desc[last_desc_ix].intr_enable = 1;
+
+ crystalhd_hw_dump_desc(desc, last_desc_ix, 1);
+
+ if (count != xfr_sz) {
+ BCMLOG_ERR("interal error sz curr:%x exp:%x\n", count, xfr_sz);
+ return BC_STS_ERROR;
+ }
+
+ return BC_STS_SUCCESS;
+}
+
+static BC_STATUS crystalhd_xlat_sgl_to_dma_desc(crystalhd_dio_req *ioreq,
+ pdma_desc_mem pdesc_mem,
+ uint32_t *uv_desc_index)
+{
+ dma_descriptor *desc = NULL;
+ dma_addr_t desc_paddr_base = 0;
+ uint32_t sg_cnt = 0, sg_st_ix = 0, sg_st_off = 0;
+ uint32_t xfr_sz = 0;
+ BC_STATUS sts = BC_STS_SUCCESS;
+
+ /* Check params.. */
+ if (!ioreq || !pdesc_mem || !uv_desc_index) {
+ BCMLOG_ERR("Invalid Args\n");
+ return BC_STS_INV_ARG;
+ }
+
+ if (!pdesc_mem->sz || !pdesc_mem->pdma_desc_start ||
+ !ioreq->sg || (!ioreq->sg_cnt && !ioreq->uinfo.dir_tx)) {
+ BCMLOG_ERR("Invalid Args\n");
+ return BC_STS_INV_ARG;
+ }
+
+ if ((ioreq->uinfo.dir_tx) && (ioreq->uinfo.uv_offset)) {
+ BCMLOG_ERR("UV offset for TX??\n");
+ return BC_STS_INV_ARG;
+
+ }
+
+ desc = pdesc_mem->pdma_desc_start;
+ desc_paddr_base = pdesc_mem->phy_addr;
+
+ if (ioreq->uinfo.dir_tx || (ioreq->uinfo.uv_offset == 0)) {
+ sg_cnt = ioreq->sg_cnt;
+ xfr_sz = ioreq->uinfo.xfr_len;
+ } else {
+ sg_cnt = ioreq->uinfo.uv_sg_ix + 1;
+ xfr_sz = ioreq->uinfo.uv_offset;
+ }
+
+ sts = crystalhd_hw_fill_desc(ioreq, desc, desc_paddr_base, sg_cnt,
+ sg_st_ix, sg_st_off, xfr_sz);
+
+ if ((sts != BC_STS_SUCCESS) || !ioreq->uinfo.uv_offset)
+ return sts;
+
+ /* Prepare for UV mapping.. */
+ desc = &pdesc_mem->pdma_desc_start[sg_cnt];
+ desc_paddr_base = pdesc_mem->phy_addr +
+ (sg_cnt * sizeof(dma_descriptor));
+
+ /* Done with desc addr.. now update sg stuff.*/
+ sg_cnt = ioreq->sg_cnt - ioreq->uinfo.uv_sg_ix;
+ xfr_sz = ioreq->uinfo.xfr_len - ioreq->uinfo.uv_offset;
+ sg_st_ix = ioreq->uinfo.uv_sg_ix;
+ sg_st_off = ioreq->uinfo.uv_sg_off;
+
+ sts = crystalhd_hw_fill_desc(ioreq, desc, desc_paddr_base, sg_cnt,
+ sg_st_ix, sg_st_off, xfr_sz);
+ if (sts != BC_STS_SUCCESS)
+ return sts;
+
+ *uv_desc_index = sg_st_ix;
+
+ return sts;
+}
+
+static void crystalhd_start_tx_dma_engine(struct crystalhd_hw *hw)
+{
+ uint32_t dma_cntrl;
+
+ dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_TX_SW_DESC_LIST_CTRL_STS);
+ if (!(dma_cntrl & DMA_START_BIT)) {
+ dma_cntrl |= DMA_START_BIT;
+ crystalhd_reg_wr(hw->adp, MISC1_TX_SW_DESC_LIST_CTRL_STS,
+ dma_cntrl);
+ }
+
+ return;
+}
+
+/* _CHECK_THIS_
+ *
+ * Verify if the Stop generates a completion interrupt or not.
+ * if it does not generate an interrupt, then add polling here.
+ */
+static BC_STATUS crystalhd_stop_tx_dma_engine(struct crystalhd_hw *hw)
+{
+ uint32_t dma_cntrl, cnt = 30;
+ uint32_t l1 = 1, l2 = 1;
+ unsigned long flags = 0;
+
+ dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_TX_SW_DESC_LIST_CTRL_STS);
+
+ BCMLOG(BCMLOG_DBG, "Stopping TX DMA Engine..\n");
+
+ /* FIXME: jarod: invert dma_ctrl and check bit? or are there missing parens? */
+ if (!dma_cntrl & DMA_START_BIT) {
+ BCMLOG(BCMLOG_DBG, "Already Stopped\n");
+ return BC_STS_SUCCESS;
+ }
+
+ crystalhd_disable_interrupts(hw->adp);
+
+ /* Issue stop to HW */
+ /* This bit when set gave problems. Please check*/
+ dma_cntrl &= ~DMA_START_BIT;
+ crystalhd_reg_wr(hw->adp, MISC1_TX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
+
+ BCMLOG(BCMLOG_DBG, "Cleared the DMA Start bit\n");
+
+ /* Poll for 3seconds (30 * 100ms) on both the lists..*/
+ while ((l1 || l2) && cnt) {
+
+ if (l1) {
+ l1 = crystalhd_reg_rd(hw->adp, MISC1_TX_FIRST_DESC_L_ADDR_LIST0);
+ l1 &= DMA_START_BIT;
+ }
+
+ if (l2) {
+ l2 = crystalhd_reg_rd(hw->adp, MISC1_TX_FIRST_DESC_L_ADDR_LIST1);
+ l2 &= DMA_START_BIT;
+ }
+
+ msleep_interruptible(100);
+
+ cnt--;
+ }
+
+ if (!cnt) {
+ BCMLOG_ERR("Failed to stop TX DMA.. l1 %d, l2 %d\n", l1, l2);
+ crystalhd_enable_interrupts(hw->adp);
+ return BC_STS_ERROR;
+ }
+
+ spin_lock_irqsave(&hw->lock, flags);
+ hw->tx_list_post_index = 0;
+ spin_unlock_irqrestore(&hw->lock, flags);
+ BCMLOG(BCMLOG_DBG, "stopped TX DMA..\n");
+ crystalhd_enable_interrupts(hw->adp);
+
+ return BC_STS_SUCCESS;
+}
+
+static uint32_t crystalhd_get_pib_avail_cnt(struct crystalhd_hw *hw)
+{
+ /*
+ * Position of the PIB Entries can be found at
+ * 0th and the 1st location of the Circular list.
+ */
+ uint32_t Q_addr;
+ uint32_t pib_cnt, r_offset, w_offset;
+
+ Q_addr = hw->pib_del_Q_addr;
+
+ /* Get the Read Pointer */
+ crystalhd_mem_rd(hw->adp, Q_addr, 1, &r_offset);
+
+ /* Get the Write Pointer */
+ crystalhd_mem_rd(hw->adp, Q_addr + sizeof(uint32_t), 1, &w_offset);
+
+ if (r_offset == w_offset)
+ return 0; /* Queue is empty */
+
+ if (w_offset > r_offset)
+ pib_cnt = w_offset - r_offset;
+ else
+ pib_cnt = (w_offset + MAX_PIB_Q_DEPTH) -
+ (r_offset + MIN_PIB_Q_DEPTH);
+
+ if (pib_cnt > MAX_PIB_Q_DEPTH) {
+ BCMLOG_ERR("Invalid PIB Count (%u)\n", pib_cnt);
+ return 0;
+ }
+
+ return pib_cnt;
+}
+
+static uint32_t crystalhd_get_addr_from_pib_Q(struct crystalhd_hw *hw)
+{
+ uint32_t Q_addr;
+ uint32_t addr_entry, r_offset, w_offset;
+
+ Q_addr = hw->pib_del_Q_addr;
+
+ /* Get the Read Pointer 0Th Location is Read Pointer */
+ crystalhd_mem_rd(hw->adp, Q_addr, 1, &r_offset);
+
+ /* Get the Write Pointer 1st Location is Write pointer */
+ crystalhd_mem_rd(hw->adp, Q_addr + sizeof(uint32_t), 1, &w_offset);
+
+ /* Queue is empty */
+ if (r_offset == w_offset)
+ return 0;
+
+ if ((r_offset < MIN_PIB_Q_DEPTH) || (r_offset >= MAX_PIB_Q_DEPTH))
+ return 0;
+
+ /* Get the Actual Address of the PIB */
+ crystalhd_mem_rd(hw->adp, Q_addr + (r_offset * sizeof(uint32_t)),
+ 1, &addr_entry);
+
+ /* Increment the Read Pointer */
+ r_offset++;
+
+ if (MAX_PIB_Q_DEPTH == r_offset)
+ r_offset = MIN_PIB_Q_DEPTH;
+
+ /* Write back the read pointer to It's Location */
+ crystalhd_mem_wr(hw->adp, Q_addr, 1, &r_offset);
+
+ return addr_entry;
+}
+
+static bool crystalhd_rel_addr_to_pib_Q(struct crystalhd_hw *hw, uint32_t addr_to_rel)
+{
+ uint32_t Q_addr;
+ uint32_t r_offset, w_offset, n_offset;
+
+ Q_addr = hw->pib_rel_Q_addr;
+
+ /* Get the Read Pointer */
+ crystalhd_mem_rd(hw->adp, Q_addr, 1, &r_offset);
+
+ /* Get the Write Pointer */
+ crystalhd_mem_rd(hw->adp, Q_addr + sizeof(uint32_t), 1, &w_offset);
+
+ if ((r_offset < MIN_PIB_Q_DEPTH) ||
+ (r_offset >= MAX_PIB_Q_DEPTH))
+ return false;
+
+ n_offset = w_offset + 1;
+
+ if (MAX_PIB_Q_DEPTH == n_offset)
+ n_offset = MIN_PIB_Q_DEPTH;
+
+ if (r_offset == n_offset)
+ return false; /* should never happen */
+
+ /* Write the DRAM ADDR to the Queue at Next Offset */
+ crystalhd_mem_wr(hw->adp, Q_addr + (w_offset * sizeof(uint32_t)),
+ 1, &addr_to_rel);
+
+ /* Put the New value of the write pointer in Queue */
+ crystalhd_mem_wr(hw->adp, Q_addr + sizeof(uint32_t), 1, &n_offset);
+
+ return true;
+}
+
+static void cpy_pib_to_app(C011_PIB *src_pib, BC_PIC_INFO_BLOCK *dst_pib)
+{
+ if (!src_pib || !dst_pib) {
+ BCMLOG_ERR("Invalid Arguments\n");
+ return;
+ }
+
+ dst_pib->timeStamp = 0;
+ dst_pib->picture_number = src_pib->ppb.picture_number;
+ dst_pib->width = src_pib->ppb.width;
+ dst_pib->height = src_pib->ppb.height;
+ dst_pib->chroma_format = src_pib->ppb.chroma_format;
+ dst_pib->pulldown = src_pib->ppb.pulldown;
+ dst_pib->flags = src_pib->ppb.flags;
+ dst_pib->sess_num = src_pib->ptsStcOffset;
+ dst_pib->aspect_ratio = src_pib->ppb.aspect_ratio;
+ dst_pib->colour_primaries = src_pib->ppb.colour_primaries;
+ dst_pib->picture_meta_payload = src_pib->ppb.picture_meta_payload;
+ dst_pib->frame_rate = src_pib->resolution ;
+ return;
+}
+
+static void crystalhd_hw_proc_pib(struct crystalhd_hw *hw)
+{
+ unsigned int cnt;
+ C011_PIB src_pib;
+ uint32_t pib_addr, pib_cnt;
+ BC_PIC_INFO_BLOCK *AppPib;
+ crystalhd_rx_dma_pkt *rx_pkt = NULL;
+
+ pib_cnt = crystalhd_get_pib_avail_cnt(hw);
+
+ if (!pib_cnt)
+ return;
+
+ for (cnt = 0; cnt < pib_cnt; cnt++) {
+
+ pib_addr = crystalhd_get_addr_from_pib_Q(hw);
+ crystalhd_mem_rd(hw->adp, pib_addr, sizeof(C011_PIB) / 4,
+ (uint32_t *)&src_pib);
+
+ if (src_pib.bFormatChange) {
+ rx_pkt = (crystalhd_rx_dma_pkt *)crystalhd_dioq_fetch(hw->rx_freeq);
+ if (!rx_pkt)
+ return;
+ rx_pkt->flags = 0;
+ rx_pkt->flags |= COMP_FLAG_PIB_VALID | COMP_FLAG_FMT_CHANGE;
+ AppPib = &rx_pkt->pib;
+ cpy_pib_to_app(&src_pib, AppPib);
+
+ BCMLOG(BCMLOG_DBG,
+ "App PIB:%x %x %x %x %x %x %x %x %x %x\n",
+ rx_pkt->pib.picture_number,
+ rx_pkt->pib.aspect_ratio,
+ rx_pkt->pib.chroma_format,
+ rx_pkt->pib.colour_primaries,
+ rx_pkt->pib.frame_rate,
+ rx_pkt->pib.height,
+ rx_pkt->pib.height,
+ rx_pkt->pib.n_drop,
+ rx_pkt->pib.pulldown,
+ rx_pkt->pib.ycom);
+
+ crystalhd_dioq_add(hw->rx_rdyq, (void *)rx_pkt, true, rx_pkt->pkt_tag);
+
+ }
+
+ crystalhd_rel_addr_to_pib_Q(hw, pib_addr);
+ }
+}
+
+static void crystalhd_start_rx_dma_engine(struct crystalhd_hw *hw)
+{
+ uint32_t dma_cntrl;
+
+ dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_Y_RX_SW_DESC_LIST_CTRL_STS);
+ if (!(dma_cntrl & DMA_START_BIT)) {
+ dma_cntrl |= DMA_START_BIT;
+ crystalhd_reg_wr(hw->adp, MISC1_Y_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
+ }
+
+ dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_UV_RX_SW_DESC_LIST_CTRL_STS);
+ if (!(dma_cntrl & DMA_START_BIT)) {
+ dma_cntrl |= DMA_START_BIT;
+ crystalhd_reg_wr(hw->adp, MISC1_UV_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
+ }
+
+ return;
+}
+
+static void crystalhd_stop_rx_dma_engine(struct crystalhd_hw *hw)
+{
+ uint32_t dma_cntrl = 0, count = 30;
+ uint32_t l0y = 1, l0uv = 1, l1y = 1, l1uv = 1;
+
+ dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_Y_RX_SW_DESC_LIST_CTRL_STS);
+ if ((dma_cntrl & DMA_START_BIT)) {
+ dma_cntrl &= ~DMA_START_BIT;
+ crystalhd_reg_wr(hw->adp, MISC1_Y_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
+ }
+
+ dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_UV_RX_SW_DESC_LIST_CTRL_STS);
+ if ((dma_cntrl & DMA_START_BIT)) {
+ dma_cntrl &= ~DMA_START_BIT;
+ crystalhd_reg_wr(hw->adp, MISC1_UV_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
+ }
+
+ /* Poll for 3seconds (30 * 100ms) on both the lists..*/
+ while ((l0y || l0uv || l1y || l1uv) && count) {
+
+ if (l0y) {
+ l0y = crystalhd_reg_rd(hw->adp, MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST0);
+ l0y &= DMA_START_BIT;
+ if (!l0y) {
+ hw->rx_list_sts[0] &= ~rx_waiting_y_intr;
+ }
+ }
+
+ if (l1y) {
+ l1y = crystalhd_reg_rd(hw->adp, MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST1);
+ l1y &= DMA_START_BIT;
+ if (!l1y) {
+ hw->rx_list_sts[1] &= ~rx_waiting_y_intr;
+ }
+ }
+
+ if (l0uv) {
+ l0uv = crystalhd_reg_rd(hw->adp, MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST0);
+ l0uv &= DMA_START_BIT;
+ if (!l0uv) {
+ hw->rx_list_sts[0] &= ~rx_waiting_uv_intr;
+ }
+ }
+
+ if (l1uv) {
+ l1uv = crystalhd_reg_rd(hw->adp, MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST1);
+ l1uv &= DMA_START_BIT;
+ if (!l1uv) {
+ hw->rx_list_sts[1] &= ~rx_waiting_uv_intr;
+ }
+ }
+ msleep_interruptible(100);
+ count--;
+ }
+
+ hw->rx_list_post_index = 0;
+
+ BCMLOG(BCMLOG_SSTEP, "Capture Stop: %d List0:Sts:%x List1:Sts:%x\n",
+ count, hw->rx_list_sts[0], hw->rx_list_sts[1]);
+}
+
+static BC_STATUS crystalhd_hw_prog_rxdma(struct crystalhd_hw *hw, crystalhd_rx_dma_pkt *rx_pkt)
+{
+ uint32_t y_low_addr_reg, y_high_addr_reg;
+ uint32_t uv_low_addr_reg, uv_high_addr_reg;
+ addr_64 desc_addr;
+ unsigned long flags;
+
+ if (!hw || !rx_pkt) {
+ BCMLOG_ERR("Invalid Arguments\n");
+ return BC_STS_INV_ARG;
+ }
+
+ if (hw->rx_list_post_index >= DMA_ENGINE_CNT) {
+ BCMLOG_ERR("List Out Of bounds %x\n", hw->rx_list_post_index);
+ return BC_STS_INV_ARG;
+ }
+
+ spin_lock_irqsave(&hw->rx_lock, flags);
+ /* FIXME: jarod: sts_free is an enum for 0, in crystalhd_hw.h... yuk... */
+ if (sts_free != hw->rx_list_sts[hw->rx_list_post_index]) {
+ spin_unlock_irqrestore(&hw->rx_lock, flags);
+ return BC_STS_BUSY;
+ }
+
+ if (!hw->rx_list_post_index) {
+ y_low_addr_reg = MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST0;
+ y_high_addr_reg = MISC1_Y_RX_FIRST_DESC_U_ADDR_LIST0;
+ uv_low_addr_reg = MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST0;
+ uv_high_addr_reg = MISC1_UV_RX_FIRST_DESC_U_ADDR_LIST0;
+ } else {
+ y_low_addr_reg = MISC1_Y_RX_FIRST_DESC_L_ADDR_LIST1;
+ y_high_addr_reg = MISC1_Y_RX_FIRST_DESC_U_ADDR_LIST1;
+ uv_low_addr_reg = MISC1_UV_RX_FIRST_DESC_L_ADDR_LIST1;
+ uv_high_addr_reg = MISC1_UV_RX_FIRST_DESC_U_ADDR_LIST1;
+ }
+ rx_pkt->pkt_tag = hw->rx_pkt_tag_seed + hw->rx_list_post_index;
+ hw->rx_list_sts[hw->rx_list_post_index] |= rx_waiting_y_intr;
+ if (rx_pkt->uv_phy_addr)
+ hw->rx_list_sts[hw->rx_list_post_index] |= rx_waiting_uv_intr;
+ hw->rx_list_post_index = (hw->rx_list_post_index + 1) % DMA_ENGINE_CNT;
+ spin_unlock_irqrestore(&hw->rx_lock, flags);
+
+ crystalhd_dioq_add(hw->rx_actq, (void *)rx_pkt, false, rx_pkt->pkt_tag);
+
+ crystalhd_start_rx_dma_engine(hw);
+ /* Program the Y descriptor */
+ desc_addr.full_addr = rx_pkt->desc_mem.phy_addr;
+ crystalhd_reg_wr(hw->adp, y_high_addr_reg, desc_addr.high_part);
+ crystalhd_reg_wr(hw->adp, y_low_addr_reg, desc_addr.low_part | 0x01);
+
+ if (rx_pkt->uv_phy_addr) {
+ /* Program the UV descriptor */
+ desc_addr.full_addr = rx_pkt->uv_phy_addr;
+ crystalhd_reg_wr(hw->adp, uv_high_addr_reg, desc_addr.high_part);
+ crystalhd_reg_wr(hw->adp, uv_low_addr_reg, desc_addr.low_part | 0x01);
+ }
+
+ return BC_STS_SUCCESS;
+}
+
+static BC_STATUS crystalhd_hw_post_cap_buff(struct crystalhd_hw *hw,
+ crystalhd_rx_dma_pkt *rx_pkt)
+{
+ BC_STATUS sts = crystalhd_hw_prog_rxdma(hw, rx_pkt);
+
+ if (sts == BC_STS_BUSY)
+ crystalhd_dioq_add(hw->rx_freeq, (void *)rx_pkt,
+ false, rx_pkt->pkt_tag);
+
+ return sts;
+}
+
+static void crystalhd_get_dnsz(struct crystalhd_hw *hw, uint32_t list_index,
+ uint32_t *y_dw_dnsz, uint32_t *uv_dw_dnsz)
+{
+ uint32_t y_dn_sz_reg, uv_dn_sz_reg;
+
+ if (!list_index) {
+ y_dn_sz_reg = MISC1_Y_RX_LIST0_CUR_BYTE_CNT;
+ uv_dn_sz_reg = MISC1_UV_RX_LIST0_CUR_BYTE_CNT;
+ } else {
+ y_dn_sz_reg = MISC1_Y_RX_LIST1_CUR_BYTE_CNT;
+ uv_dn_sz_reg = MISC1_UV_RX_LIST1_CUR_BYTE_CNT;
+ }
+
+ *y_dw_dnsz = crystalhd_reg_rd(hw->adp, y_dn_sz_reg);
+ *uv_dw_dnsz = crystalhd_reg_rd(hw->adp, uv_dn_sz_reg);
+}
+
+/*
+ * This function should be called only after making sure that the two DMA
+ * lists are free. This function does not check if DMA's are active, before
+ * turning off the DMA.
+ */
+static void crystalhd_hw_finalize_pause(struct crystalhd_hw *hw)
+{
+ uint32_t dma_cntrl, aspm;
+
+ hw->stop_pending = 0;
+
+ dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_Y_RX_SW_DESC_LIST_CTRL_STS);
+ if (dma_cntrl & DMA_START_BIT) {
+ dma_cntrl &= ~DMA_START_BIT;
+ crystalhd_reg_wr(hw->adp, MISC1_Y_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
+ }
+
+ dma_cntrl = crystalhd_reg_rd(hw->adp, MISC1_UV_RX_SW_DESC_LIST_CTRL_STS);
+ if (dma_cntrl & DMA_START_BIT) {
+ dma_cntrl &= ~DMA_START_BIT;
+ crystalhd_reg_wr(hw->adp, MISC1_UV_RX_SW_DESC_LIST_CTRL_STS, dma_cntrl);
+ }
+ hw->rx_list_post_index = 0;
+
+ aspm = crystalhd_reg_rd(hw->adp, PCIE_DLL_DATA_LINK_CONTROL);
+ aspm |= ASPM_L1_ENABLE;
+ /* NAREN BCMLOG(BCMLOG_INFO, "aspm on\n"); */
+ crystalhd_reg_wr(hw->adp, PCIE_DLL_DATA_LINK_CONTROL, aspm);
+}
+
+static BC_STATUS crystalhd_rx_pkt_done(struct crystalhd_hw *hw, uint32_t list_index,
+ BC_STATUS comp_sts)
+{
+ crystalhd_rx_dma_pkt *rx_pkt = NULL;
+ uint32_t y_dw_dnsz, uv_dw_dnsz;
+ BC_STATUS sts = BC_STS_SUCCESS;
+
+ if (!hw || list_index >= DMA_ENGINE_CNT) {
+ BCMLOG_ERR("Invalid Arguments\n");
+ return BC_STS_INV_ARG;
+ }
+
+ rx_pkt = crystalhd_dioq_find_and_fetch(hw->rx_actq,
+ hw->rx_pkt_tag_seed + list_index);
+ if (!rx_pkt) {
+ BCMLOG_ERR("Act-Q:PostIx:%x L0Sts:%x L1Sts:%x current L:%x tag:%x comp:%x\n",
+ hw->rx_list_post_index, hw->rx_list_sts[0],
+ hw->rx_list_sts[1], list_index,
+ hw->rx_pkt_tag_seed + list_index, comp_sts);
+ return BC_STS_INV_ARG;
+ }
+
+ if (comp_sts == BC_STS_SUCCESS) {
+ crystalhd_get_dnsz(hw, list_index, &y_dw_dnsz, &uv_dw_dnsz);
+ rx_pkt->dio_req->uinfo.y_done_sz = y_dw_dnsz;
+ rx_pkt->flags = COMP_FLAG_DATA_VALID;
+ if (rx_pkt->uv_phy_addr)
+ rx_pkt->dio_req->uinfo.uv_done_sz = uv_dw_dnsz;
+ crystalhd_dioq_add(hw->rx_rdyq, rx_pkt, true,
+ hw->rx_pkt_tag_seed + list_index);
+ return sts;
+ }
+
+ /* Check if we can post this DIO again. */
+ return crystalhd_hw_post_cap_buff(hw, rx_pkt);
+}
+
+static bool crystalhd_rx_list0_handler(struct crystalhd_hw *hw, uint32_t int_sts,
+ uint32_t y_err_sts, uint32_t uv_err_sts)
+{
+ uint32_t tmp;
+ list_sts tmp_lsts;
+
+ if (!(y_err_sts & GET_Y0_ERR_MSK) && !(uv_err_sts & GET_UV0_ERR_MSK))
+ return false;
+
+ tmp_lsts = hw->rx_list_sts[0];
+
+ /* Y0 - DMA */
+ tmp = y_err_sts & GET_Y0_ERR_MSK;
+ if (int_sts & INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_MASK)
+ hw->rx_list_sts[0] &= ~rx_waiting_y_intr;
+
+ if (y_err_sts & MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK) {
+ hw->rx_list_sts[0] &= ~rx_waiting_y_intr;
+ tmp &= ~MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK;
+ }
+
+ if (y_err_sts & MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK) {
+ hw->rx_list_sts[0] &= ~rx_y_mask;
+ hw->rx_list_sts[0] |= rx_y_error;
+ tmp &= ~MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK;
+ }
+
+ if (tmp) {
+ hw->rx_list_sts[0] &= ~rx_y_mask;
+ hw->rx_list_sts[0] |= rx_y_error;
+ hw->rx_list_post_index = 0;
+ }
+
+ /* UV0 - DMA */
+ tmp = uv_err_sts & GET_UV0_ERR_MSK;
+ if (int_sts & INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_MASK)
+ hw->rx_list_sts[0] &= ~rx_waiting_uv_intr;
+
+ if (uv_err_sts & MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK) {
+ hw->rx_list_sts[0] &= ~rx_waiting_uv_intr;
+ tmp &= ~MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK;
+ }
+
+ if (uv_err_sts & MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK) {
+ hw->rx_list_sts[0] &= ~rx_uv_mask;
+ hw->rx_list_sts[0] |= rx_uv_error;
+ tmp &= ~MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK;
+ }
+
+ if (tmp) {
+ hw->rx_list_sts[0] &= ~rx_uv_mask;
+ hw->rx_list_sts[0] |= rx_uv_error;
+ hw->rx_list_post_index = 0;
+ }
+
+ if (y_err_sts & GET_Y0_ERR_MSK) {
+ tmp = y_err_sts & GET_Y0_ERR_MSK;
+ crystalhd_reg_wr(hw->adp, MISC1_Y_RX_ERROR_STATUS, tmp);
+ }
+
+ if (uv_err_sts & GET_UV0_ERR_MSK) {
+ tmp = uv_err_sts & GET_UV0_ERR_MSK;
+ crystalhd_reg_wr(hw->adp, MISC1_UV_RX_ERROR_STATUS, tmp);
+ }
+
+ return (tmp_lsts != hw->rx_list_sts[0]);
+}
+
+static bool crystalhd_rx_list1_handler(struct crystalhd_hw *hw, uint32_t int_sts,
+ uint32_t y_err_sts, uint32_t uv_err_sts)
+{
+ uint32_t tmp;
+ list_sts tmp_lsts;
+
+ if (!(y_err_sts & GET_Y1_ERR_MSK) && !(uv_err_sts & GET_UV1_ERR_MSK))
+ return false;
+
+ tmp_lsts = hw->rx_list_sts[1];
+
+ /* Y1 - DMA */
+ tmp = y_err_sts & GET_Y1_ERR_MSK;
+ if (int_sts & INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_MASK)
+ hw->rx_list_sts[1] &= ~rx_waiting_y_intr;
+
+ if (y_err_sts & MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK) {
+ hw->rx_list_sts[1] &= ~rx_waiting_y_intr;
+ tmp &= ~MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK;
+ }
+
+ if (y_err_sts & MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK) {
+ /* Add retry-support..*/
+ hw->rx_list_sts[1] &= ~rx_y_mask;
+ hw->rx_list_sts[1] |= rx_y_error;
+ tmp &= ~MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK;
+ }
+
+ if (tmp) {
+ hw->rx_list_sts[1] &= ~rx_y_mask;
+ hw->rx_list_sts[1] |= rx_y_error;
+ hw->rx_list_post_index = 0;
+ }
+
+ /* UV1 - DMA */
+ tmp = uv_err_sts & GET_UV1_ERR_MSK;
+ if (int_sts & INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_MASK) {
+ hw->rx_list_sts[1] &= ~rx_waiting_uv_intr;
+ }
+
+ if (uv_err_sts & MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK) {
+ hw->rx_list_sts[1] &= ~rx_waiting_uv_intr;
+ tmp &= ~MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK;
+ }
+
+ if (uv_err_sts & MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK) {
+ /* Add retry-support*/
+ hw->rx_list_sts[1] &= ~rx_uv_mask;
+ hw->rx_list_sts[1] |= rx_uv_error;
+ tmp &= ~MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK;
+ }
+
+ if (tmp) {
+ hw->rx_list_sts[1] &= ~rx_uv_mask;
+ hw->rx_list_sts[1] |= rx_uv_error;
+ hw->rx_list_post_index = 0;
+ }
+
+ if (y_err_sts & GET_Y1_ERR_MSK) {
+ tmp = y_err_sts & GET_Y1_ERR_MSK;
+ crystalhd_reg_wr(hw->adp, MISC1_Y_RX_ERROR_STATUS, tmp);
+ }
+
+ if (uv_err_sts & GET_UV1_ERR_MSK) {
+ tmp = uv_err_sts & GET_UV1_ERR_MSK;
+ crystalhd_reg_wr(hw->adp, MISC1_UV_RX_ERROR_STATUS, tmp);
+ }
+
+ return (tmp_lsts != hw->rx_list_sts[1]);
+}
+
+
+static void crystalhd_rx_isr(struct crystalhd_hw *hw, uint32_t intr_sts)
+{
+ unsigned long flags;
+ uint32_t i, list_avail = 0;
+ BC_STATUS comp_sts = BC_STS_NO_DATA;
+ uint32_t y_err_sts, uv_err_sts, y_dn_sz = 0, uv_dn_sz = 0;
+ bool ret = 0;
+
+ if (!hw) {
+ BCMLOG_ERR("Invalid Arguments\n");
+ return;
+ }
+
+ if (!(intr_sts & GET_RX_INTR_MASK))
+ return;
+
+ y_err_sts = crystalhd_reg_rd(hw->adp, MISC1_Y_RX_ERROR_STATUS);
+ uv_err_sts = crystalhd_reg_rd(hw->adp, MISC1_UV_RX_ERROR_STATUS);
+
+ for (i = 0; i < DMA_ENGINE_CNT; i++) {
+ /* Update States..*/
+ spin_lock_irqsave(&hw->rx_lock, flags);
+ if (i == 0)
+ ret = crystalhd_rx_list0_handler(hw, intr_sts, y_err_sts, uv_err_sts);
+ else
+ ret = crystalhd_rx_list1_handler(hw, intr_sts, y_err_sts, uv_err_sts);
+ if (ret) {
+ switch (hw->rx_list_sts[i]) {
+ case sts_free:
+ comp_sts = BC_STS_SUCCESS;
+ list_avail = 1;
+ break;
+ case rx_y_error:
+ case rx_uv_error:
+ case rx_sts_error:
+ /* We got error on both or Y or uv. */
+ hw->stats.rx_errors++;
+ crystalhd_get_dnsz(hw, i, &y_dn_sz, &uv_dn_sz);
+ /* FIXME: jarod: this is where my mini pci-e card is tripping up */
+ BCMLOG(BCMLOG_DBG, "list_index:%x rx[%d] Y:%x "
+ "UV:%x Int:%x YDnSz:%x UVDnSz:%x\n",
+ i, hw->stats.rx_errors, y_err_sts,
+ uv_err_sts, intr_sts, y_dn_sz, uv_dn_sz);
+ hw->rx_list_sts[i] = sts_free;
+ comp_sts = BC_STS_ERROR;
+ break;
+ default:
+ /* Wait for completion..*/
+ comp_sts = BC_STS_NO_DATA;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&hw->rx_lock, flags);
+
+ /* handle completion...*/
+ if (comp_sts != BC_STS_NO_DATA) {
+ crystalhd_rx_pkt_done(hw, i, comp_sts);
+ comp_sts = BC_STS_NO_DATA;
+ }
+ }
+
+ if (list_avail) {
+ if (hw->stop_pending) {
+ if ((hw->rx_list_sts[0] == sts_free) &&
+ (hw->rx_list_sts[1] == sts_free))
+ crystalhd_hw_finalize_pause(hw);
+ } else {
+ crystalhd_hw_start_capture(hw);
+ }
+ }
+}
+
+static BC_STATUS crystalhd_fw_cmd_post_proc(struct crystalhd_hw *hw,
+ BC_FW_CMD *fw_cmd)
+{
+ BC_STATUS sts = BC_STS_SUCCESS;
+ DecRspChannelStartVideo *st_rsp = NULL;
+
+ switch (fw_cmd->cmd[0]) {
+ case eCMD_C011_DEC_CHAN_START_VIDEO:
+ st_rsp = (DecRspChannelStartVideo *)fw_cmd->rsp;
+ hw->pib_del_Q_addr = st_rsp->picInfoDeliveryQ;
+ hw->pib_rel_Q_addr = st_rsp->picInfoReleaseQ;
+ BCMLOG(BCMLOG_DBG, "DelQAddr:%x RelQAddr:%x\n",
+ hw->pib_del_Q_addr, hw->pib_rel_Q_addr);
+ break;
+ case eCMD_C011_INIT:
+ if (!(crystalhd_load_firmware_config(hw->adp))) {
+ BCMLOG_ERR("Invalid Params.\n");
+ sts = BC_STS_FW_AUTH_FAILED;
+ }
+ break;
+ default:
+ break;
+ }
+ return sts;
+}
+
+static BC_STATUS crystalhd_put_ddr2sleep(struct crystalhd_hw *hw)
+{
+ uint32_t reg;
+ link_misc_perst_decoder_ctrl rst_cntrl_reg;
+
+ /* Pulse reset pin of 7412 (MISC_PERST_DECODER_CTRL) */
+ rst_cntrl_reg.whole_reg = crystalhd_reg_rd(hw->adp, MISC_PERST_DECODER_CTRL);
+
+ rst_cntrl_reg.bcm_7412_rst = 1;
+ crystalhd_reg_wr(hw->adp, MISC_PERST_DECODER_CTRL, rst_cntrl_reg.whole_reg);
+ msleep_interruptible(50);
+
+ rst_cntrl_reg.bcm_7412_rst = 0;
+ crystalhd_reg_wr(hw->adp, MISC_PERST_DECODER_CTRL, rst_cntrl_reg.whole_reg);
+
+ /* Close all banks, put DDR in idle */
+ bc_dec_reg_wr(hw->adp, SDRAM_PRECHARGE, 0);
+
+ /* Set bit 25 (drop CKE pin of DDR) */
+ reg = bc_dec_reg_rd(hw->adp, SDRAM_PARAM);
+ reg |= 0x02000000;
+ bc_dec_reg_wr(hw->adp, SDRAM_PARAM, reg);
+
+ /* Reset the audio block */
+ bc_dec_reg_wr(hw->adp, AUD_DSP_MISC_SOFT_RESET, 0x1);
+
+ /* Power down Raptor PLL */
+ reg = bc_dec_reg_rd(hw->adp, DecHt_PllCCtl);
+ reg |= 0x00008000;
+ bc_dec_reg_wr(hw->adp, DecHt_PllCCtl, reg);
+
+ /* Power down all Audio PLL */
+ bc_dec_reg_wr(hw->adp, AIO_MISC_PLL_RESET, 0x1);
+
+ /* Power down video clock (75MHz) */
+ reg = bc_dec_reg_rd(hw->adp, DecHt_PllECtl);
+ reg |= 0x00008000;
+ bc_dec_reg_wr(hw->adp, DecHt_PllECtl, reg);
+
+ /* Power down video clock (75MHz) */
+ reg = bc_dec_reg_rd(hw->adp, DecHt_PllDCtl);
+ reg |= 0x00008000;
+ bc_dec_reg_wr(hw->adp, DecHt_PllDCtl, reg);
+
+ /* Power down core clock (200MHz) */
+ reg = bc_dec_reg_rd(hw->adp, DecHt_PllACtl);
+ reg |= 0x00008000;
+ bc_dec_reg_wr(hw->adp, DecHt_PllACtl, reg);
+
+ /* Power down core clock (200MHz) */
+ reg = bc_dec_reg_rd(hw->adp, DecHt_PllBCtl);
+ reg |= 0x00008000;
+ bc_dec_reg_wr(hw->adp, DecHt_PllBCtl, reg);
+
+ return BC_STS_SUCCESS;
+}
+
+/************************************************
+**
+*************************************************/
+
+BC_STATUS crystalhd_download_fw(struct crystalhd_adp *adp, void *buffer, uint32_t sz)
+{
+ uint32_t reg_data, cnt, *temp_buff;
+ uint32_t fw_sig_len = 36;
+ uint32_t dram_offset = BC_FWIMG_ST_ADDR, sig_reg;
+
+ BCMLOG_ENTER;
+
+ if (!adp || !buffer || !sz) {
+ BCMLOG_ERR("Invalid Params.\n");
+ return BC_STS_INV_ARG;
+ }
+
+ reg_data = crystalhd_reg_rd(adp, OTP_CMD);
+ if (!(reg_data & 0x02)) {
+ BCMLOG_ERR("Invalid hw config.. otp not programmed\n");
+ return BC_STS_ERROR;
+ }
+
+ reg_data = 0;
+ crystalhd_reg_wr(adp, DCI_CMD, 0);
+ reg_data |= BC_BIT(0);
+ crystalhd_reg_wr(adp, DCI_CMD, reg_data);
+
+ reg_data = 0;
+ cnt = 1000;
+ msleep_interruptible(10);
+
+ while (reg_data != BC_BIT(4)) {
+ reg_data = crystalhd_reg_rd(adp, DCI_STATUS);
+ reg_data &= BC_BIT(4);
+ if (--cnt == 0) {
+ BCMLOG_ERR("Firmware Download RDY Timeout.\n");
+ return BC_STS_TIMEOUT;
+ }
+ }
+
+ msleep_interruptible(10);
+ /* Load the FW to the FW_ADDR field in the DCI_FIRMWARE_ADDR */
+ crystalhd_reg_wr(adp, DCI_FIRMWARE_ADDR, dram_offset);
+ temp_buff = (uint32_t *)buffer;
+ for (cnt = 0; cnt < (sz - fw_sig_len); cnt += 4) {
+ crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (dram_offset >> 19));
+ crystalhd_reg_wr(adp, DCI_FIRMWARE_DATA, *temp_buff);
+ dram_offset += 4;
+ temp_buff++;
+ }
+ msleep_interruptible(10);
+
+ temp_buff++;
+
+ sig_reg = (uint32_t)DCI_SIGNATURE_DATA_7;
+ for (cnt = 0; cnt < 8; cnt++) {
+ uint32_t swapped_data = *temp_buff;
+ swapped_data = bswap_32_1(swapped_data);
+ crystalhd_reg_wr(adp, sig_reg, swapped_data);
+ sig_reg -= 4;
+ temp_buff++;
+ }
+ msleep_interruptible(10);
+
+ reg_data = 0;
+ reg_data |= BC_BIT(1);
+ crystalhd_reg_wr(adp, DCI_CMD, reg_data);
+ msleep_interruptible(10);
+
+ reg_data = 0;
+ reg_data = crystalhd_reg_rd(adp, DCI_STATUS);
+
+ if ((reg_data & BC_BIT(9)) == BC_BIT(9)) {
+ cnt = 1000;
+ while ((reg_data & BC_BIT(0)) != BC_BIT(0)) {
+ reg_data = crystalhd_reg_rd(adp, DCI_STATUS);
+ reg_data &= BC_BIT(0);
+ if (!(--cnt))
+ break;
+ msleep_interruptible(10);
+ }
+ reg_data = 0;
+ reg_data = crystalhd_reg_rd(adp, DCI_CMD);
+ reg_data |= BC_BIT(4);
+ crystalhd_reg_wr(adp, DCI_CMD, reg_data);
+
+ } else {
+ BCMLOG_ERR("F/w Signature mismatch\n");
+ return BC_STS_FW_AUTH_FAILED;
+ }
+
+ BCMLOG(BCMLOG_INFO, "Firmware Downloaded Successfully\n");
+ return BC_STS_SUCCESS;;
+}
+
+BC_STATUS crystalhd_do_fw_cmd(struct crystalhd_hw *hw, BC_FW_CMD *fw_cmd)
+{
+ uint32_t cnt = 0, cmd_res_addr;
+ uint32_t *cmd_buff, *res_buff;
+ wait_queue_head_t fw_cmd_event;
+ int rc = 0;
+ BC_STATUS sts;
+
+ crystalhd_create_event(&fw_cmd_event);
+
+ BCMLOG_ENTER;
+
+ if (!hw || !fw_cmd) {
+ BCMLOG_ERR("Invalid Arguments\n");
+ return BC_STS_INV_ARG;
+ }
+
+ cmd_buff = fw_cmd->cmd;
+ res_buff = fw_cmd->rsp;
+
+ if (!cmd_buff || !res_buff) {
+ BCMLOG_ERR("Invalid Parameters for F/W Command \n");
+ return BC_STS_INV_ARG;
+ }
+
+ hw->pwr_lock++;
+
+ hw->fwcmd_evt_sts = 0;
+ hw->pfw_cmd_event = &fw_cmd_event;
+
+ /*Write the command to the memory*/
+ crystalhd_mem_wr(hw->adp, TS_Host2CpuSnd, FW_CMD_BUFF_SZ, cmd_buff);
+
+ /*Memory Read for memory arbitrator flush*/
+ crystalhd_mem_rd(hw->adp, TS_Host2CpuSnd, 1, &cnt);
+
+ /* Write the command address to mailbox */
+ bc_dec_reg_wr(hw->adp, Hst2CpuMbx1, TS_Host2CpuSnd);
+ msleep_interruptible(50);
+
+ crystalhd_wait_on_event(&fw_cmd_event, hw->fwcmd_evt_sts, 20000, rc, 0);
+
+ if (!rc) {
+ sts = BC_STS_SUCCESS;
+ } else if (rc == -EBUSY) {
+ BCMLOG_ERR("Firmware command T/O\n");
+ sts = BC_STS_TIMEOUT;
+ } else if (rc == -EINTR) {
+ BCMLOG(BCMLOG_DBG, "FwCmd Wait Signal int.\n");
+ sts = BC_STS_IO_USER_ABORT;
+ } else {
+ BCMLOG_ERR("FwCmd IO Error.\n");
+ sts = BC_STS_IO_ERROR;
+ }
+
+ if (sts != BC_STS_SUCCESS) {
+ BCMLOG_ERR("FwCmd Failed.\n");
+ hw->pwr_lock--;
+ return sts;
+ }
+
+ /*Get the Responce Address*/
+ cmd_res_addr = bc_dec_reg_rd(hw->adp, Cpu2HstMbx1);
+
+ /*Read the Response*/
+ crystalhd_mem_rd(hw->adp, cmd_res_addr, FW_CMD_BUFF_SZ, res_buff);
+
+ hw->pwr_lock--;
+
+ if (res_buff[2] != C011_RET_SUCCESS) {
+ BCMLOG_ERR("res_buff[2] != C011_RET_SUCCESS\n");
+ return BC_STS_FW_CMD_ERR;
+ }
+
+ sts = crystalhd_fw_cmd_post_proc(hw, fw_cmd);
+ if (sts != BC_STS_SUCCESS)
+ BCMLOG_ERR("crystalhd_fw_cmd_post_proc Failed.\n");
+
+ return sts;
+}
+
+bool crystalhd_hw_interrupt(struct crystalhd_adp *adp, struct crystalhd_hw *hw)
+{
+ uint32_t intr_sts = 0;
+ uint32_t deco_intr = 0;
+ bool rc = 0;
+
+ if (!adp || !hw->dev_started)
+ return rc;
+
+ hw->stats.num_interrupts++;
+ hw->pwr_lock++;
+
+ deco_intr = bc_dec_reg_rd(adp, Stream2Host_Intr_Sts);
+ intr_sts = crystalhd_reg_rd(adp, INTR_INTR_STATUS);
+
+ if (intr_sts) {
+ /* let system know we processed interrupt..*/
+ rc = 1;
+ hw->stats.dev_interrupts++;
+ }
+
+ if (deco_intr && (deco_intr != 0xdeaddead)) {
+
+ if (deco_intr & 0x80000000) {
+ /*Set the Event and the status flag*/
+ if (hw->pfw_cmd_event) {
+ hw->fwcmd_evt_sts = 1;
+ crystalhd_set_event(hw->pfw_cmd_event);
+ }
+ }
+
+ if (deco_intr & BC_BIT(1))
+ crystalhd_hw_proc_pib(hw);
+
+ bc_dec_reg_wr(adp, Stream2Host_Intr_Sts, deco_intr);
+ /* FIXME: jarod: No udelay? might this be the real reason mini pci-e cards were stalling out? */
+ bc_dec_reg_wr(adp, Stream2Host_Intr_Sts, 0);
+ rc = 1;
+ }
+
+ /* Rx interrupts */
+ crystalhd_rx_isr(hw, intr_sts);
+
+ /* Tx interrupts*/
+ crystalhd_tx_isr(hw, intr_sts);
+
+ /* Clear interrupts */
+ if (rc) {
+ if (intr_sts)
+ crystalhd_reg_wr(adp, INTR_INTR_CLR_REG, intr_sts);
+
+ crystalhd_reg_wr(adp, INTR_EOI_CTRL, 1);
+ }
+
+ hw->pwr_lock--;
+
+ return rc;
+}
+
+BC_STATUS crystalhd_hw_open(struct crystalhd_hw *hw, struct crystalhd_adp *adp)
+{
+ if (!hw || !adp) {
+ BCMLOG_ERR("Invalid Arguments\n");
+ return BC_STS_INV_ARG;
+ }
+
+ if (hw->dev_started)
+ return BC_STS_SUCCESS;
+
+ memset(hw, 0, sizeof(struct crystalhd_hw));
+
+ hw->adp = adp;
+ spin_lock_init(&hw->lock);
+ spin_lock_init(&hw->rx_lock);
+ /* FIXME: jarod: what are these magic numbers?!? */
+ hw->tx_ioq_tag_seed = 0x70023070;
+ hw->rx_pkt_tag_seed = 0x70029070;
+
+ hw->stop_pending = 0;
+ crystalhd_start_device(hw->adp);
+ hw->dev_started = true;
+
+ /* set initial core clock */
+ hw->core_clock_mhz = CLOCK_PRESET;
+ hw->prev_n = 0;
+ hw->pwr_lock = 0;
+ crystalhd_hw_set_core_clock(hw);
+
+ return BC_STS_SUCCESS;
+}
+
+BC_STATUS crystalhd_hw_close(struct crystalhd_hw *hw)
+{
+ if (!hw) {
+ BCMLOG_ERR("Invalid Arguments\n");
+ return BC_STS_INV_ARG;
+ }
+
+ if (!hw->dev_started)
+ return BC_STS_SUCCESS;
+
+ /* Stop and DDR sleep will happen in here */
+ crystalhd_hw_suspend(hw);
+ hw->dev_started = false;
+
+ return BC_STS_SUCCESS;
+}
+
+BC_STATUS crystalhd_hw_setup_dma_rings(struct crystalhd_hw *hw)
+{
+ unsigned int i;
+ void *mem;
+ size_t mem_len;
+ dma_addr_t phy_addr;
+ BC_STATUS sts = BC_STS_SUCCESS;
+ crystalhd_rx_dma_pkt *rpkt;
+
+ if (!hw || !hw->adp) {
+ BCMLOG_ERR("Invalid Arguments\n");
+ return BC_STS_INV_ARG;
+ }
+
+ sts = crystalhd_hw_create_ioqs(hw);
+ if (sts != BC_STS_SUCCESS) {
+ BCMLOG_ERR("Failed to create IOQs..\n");
+ return sts;
+ }
+
+ mem_len = BC_LINK_MAX_SGLS * sizeof(dma_descriptor);
+
+ for (i = 0; i < BC_TX_LIST_CNT; i++) {
+ mem = bc_kern_dma_alloc(hw->adp, mem_len, &phy_addr);
+ if (mem) {
+ memset(mem, 0, mem_len);
+ } else {
+ BCMLOG_ERR("Insufficient Memory For TX\n");
+ crystalhd_hw_free_dma_rings(hw);
+ return BC_STS_INSUFF_RES;
+ }
+ /* rx_pkt_pool -- static memory allocation */
+ hw->tx_pkt_pool[i].desc_mem.pdma_desc_start = mem;
+ hw->tx_pkt_pool[i].desc_mem.phy_addr = phy_addr;
+ hw->tx_pkt_pool[i].desc_mem.sz = BC_LINK_MAX_SGLS *
+ sizeof(dma_descriptor);
+ hw->tx_pkt_pool[i].list_tag = 0;
+
+ /* Add TX dma requests to Free Queue..*/
+ sts = crystalhd_dioq_add(hw->tx_freeq,
+ &hw->tx_pkt_pool[i], false, 0);
+ if (sts != BC_STS_SUCCESS) {
+ crystalhd_hw_free_dma_rings(hw);
+ return sts;
+ }
+ }
+
+ for (i = 0; i < BC_RX_LIST_CNT; i++) {
+ rpkt = kzalloc(sizeof(*rpkt), GFP_KERNEL);
+ if (!rpkt) {
+ BCMLOG_ERR("Insufficient Memory For RX\n");
+ crystalhd_hw_free_dma_rings(hw);
+ return BC_STS_INSUFF_RES;
+ }
+
+ mem = bc_kern_dma_alloc(hw->adp, mem_len, &phy_addr);
+ if (mem) {
+ memset(mem, 0, mem_len);
+ } else {
+ BCMLOG_ERR("Insufficient Memory For RX\n");
+ crystalhd_hw_free_dma_rings(hw);
+ return BC_STS_INSUFF_RES;
+ }
+ rpkt->desc_mem.pdma_desc_start = mem;
+ rpkt->desc_mem.phy_addr = phy_addr;
+ rpkt->desc_mem.sz = BC_LINK_MAX_SGLS * sizeof(dma_descriptor);
+ rpkt->pkt_tag = hw->rx_pkt_tag_seed + i;
+ crystalhd_hw_free_rx_pkt(hw, rpkt);
+ }
+
+ return BC_STS_SUCCESS;
+}
+
+BC_STATUS crystalhd_hw_free_dma_rings(struct crystalhd_hw *hw)
+{
+ unsigned int i;
+ crystalhd_rx_dma_pkt *rpkt = NULL;
+
+ if (!hw || !hw->adp) {
+ BCMLOG_ERR("Invalid Arguments\n");
+ return BC_STS_INV_ARG;
+ }
+
+ /* Delete all IOQs.. */
+ crystalhd_hw_delete_ioqs(hw);
+
+ for (i = 0; i < BC_TX_LIST_CNT; i++) {
+ if (hw->tx_pkt_pool[i].desc_mem.pdma_desc_start) {
+ bc_kern_dma_free(hw->adp,
+ hw->tx_pkt_pool[i].desc_mem.sz,
+ hw->tx_pkt_pool[i].desc_mem.pdma_desc_start,
+ hw->tx_pkt_pool[i].desc_mem.phy_addr);
+
+ hw->tx_pkt_pool[i].desc_mem.pdma_desc_start = NULL;
+ }
+ }
+
+ BCMLOG(BCMLOG_DBG, "Releasing RX Pkt pool\n");
+ do {
+ rpkt = crystalhd_hw_alloc_rx_pkt(hw);
+ if (!rpkt)
+ break;
+ bc_kern_dma_free(hw->adp, rpkt->desc_mem.sz,
+ rpkt->desc_mem.pdma_desc_start,
+ rpkt->desc_mem.phy_addr);
+ kfree(rpkt);
+ } while (rpkt);
+
+ return BC_STS_SUCCESS;
+}
+
+BC_STATUS crystalhd_hw_post_tx(struct crystalhd_hw *hw, crystalhd_dio_req *ioreq,
+ hw_comp_callback call_back,
+ wait_queue_head_t *cb_event, uint32_t *list_id,
+ uint8_t data_flags)
+{
+ tx_dma_pkt *tx_dma_packet = NULL;
+ uint32_t first_desc_u_addr, first_desc_l_addr;
+ uint32_t low_addr, high_addr;
+ addr_64 desc_addr;
+ BC_STATUS sts, add_sts;
+ uint32_t dummy_index = 0;
+ unsigned long flags;
+ bool rc;
+
+ if (!hw || !ioreq || !call_back || !cb_event || !list_id) {
+ BCMLOG_ERR("Invalid Arguments\n");
+ return BC_STS_INV_ARG;
+ }
+
+ /*
+ * Since we hit code in busy condition very frequently,
+ * we will check the code in status first before
+ * checking the availability of free elem.
+ *
+ * This will avoid the Q fetch/add in normal condition.
+ */
+ rc = crystalhd_code_in_full(hw->adp, ioreq->uinfo.xfr_len,
+ false, data_flags);
+ if (rc) {
+ hw->stats.cin_busy++;
+ return BC_STS_BUSY;
+ }
+
+ /* Get a list from TxFreeQ */
+ tx_dma_packet = (tx_dma_pkt *)crystalhd_dioq_fetch(hw->tx_freeq);
+ if (!tx_dma_packet) {
+ BCMLOG_ERR("No empty elements..\n");
+ return BC_STS_ERR_USAGE;
+ }
+
+ sts = crystalhd_xlat_sgl_to_dma_desc(ioreq,
+ &tx_dma_packet->desc_mem,
+ &dummy_index);
+ if (sts != BC_STS_SUCCESS) {
+ add_sts = crystalhd_dioq_add(hw->tx_freeq, tx_dma_packet,
+ false, 0);
+ if (add_sts != BC_STS_SUCCESS)
+ BCMLOG_ERR("double fault..\n");
+
+ return sts;
+ }
+
+ hw->pwr_lock++;
+
+ desc_addr.full_addr = tx_dma_packet->desc_mem.phy_addr;
+ low_addr = desc_addr.low_part;
+ high_addr = desc_addr.high_part;
+
+ tx_dma_packet->call_back = call_back;
+ tx_dma_packet->cb_event = cb_event;
+ tx_dma_packet->dio_req = ioreq;
+
+ spin_lock_irqsave(&hw->lock, flags);
+
+ if (hw->tx_list_post_index == 0) {
+ first_desc_u_addr = MISC1_TX_FIRST_DESC_U_ADDR_LIST0;
+ first_desc_l_addr = MISC1_TX_FIRST_DESC_L_ADDR_LIST0;
+ } else {
+ first_desc_u_addr = MISC1_TX_FIRST_DESC_U_ADDR_LIST1;
+ first_desc_l_addr = MISC1_TX_FIRST_DESC_L_ADDR_LIST1;
+ }
+
+ *list_id = tx_dma_packet->list_tag = hw->tx_ioq_tag_seed +
+ hw->tx_list_post_index;
+
+ hw->tx_list_post_index = (hw->tx_list_post_index + 1) % DMA_ENGINE_CNT;
+
+ spin_unlock_irqrestore(&hw->lock, flags);
+
+
+ /* Insert in Active Q..*/
+ crystalhd_dioq_add(hw->tx_actq, tx_dma_packet, false,
+ tx_dma_packet->list_tag);
+
+ /*
+ * Interrupt will come as soon as you write
+ * the valid bit. So be ready for that. All
+ * the initialization should happen before that.
+ */
+ crystalhd_start_tx_dma_engine(hw);
+ crystalhd_reg_wr(hw->adp, first_desc_u_addr, desc_addr.high_part);
+
+ crystalhd_reg_wr(hw->adp, first_desc_l_addr, desc_addr.low_part | 0x01);
+ /* Be sure we set the valid bit ^^^^ */
+
+ return BC_STS_SUCCESS;
+}
+
+/*
+ * This is a force cancel and we are racing with ISR.
+ *
+ * Will try to remove the req from ActQ before ISR gets it.
+ * If ISR gets it first then the completion happens in the
+ * normal path and we will return _STS_NO_DATA from here.
+ *
+ * FIX_ME: Not Tested the actual condition..
+ */
+BC_STATUS crystalhd_hw_cancel_tx(struct crystalhd_hw *hw, uint32_t list_id)
+{
+ if (!hw || !list_id) {
+ BCMLOG_ERR("Invalid Arguments\n");
+ return BC_STS_INV_ARG;
+ }
+
+ crystalhd_stop_tx_dma_engine(hw);
+ crystalhd_hw_tx_req_complete(hw, list_id, BC_STS_IO_USER_ABORT);
+
+ return BC_STS_SUCCESS;
+}
+
+BC_STATUS crystalhd_hw_add_cap_buffer(struct crystalhd_hw *hw,
+ crystalhd_dio_req *ioreq, bool en_post)
+{
+ crystalhd_rx_dma_pkt *rpkt;
+ uint32_t tag, uv_desc_ix = 0;
+ BC_STATUS sts;
+
+ if (!hw || !ioreq) {
+ BCMLOG_ERR("Invalid Arguments\n");
+ return BC_STS_INV_ARG;
+ }
+
+ rpkt = crystalhd_hw_alloc_rx_pkt(hw);
+ if (!rpkt) {
+ BCMLOG_ERR("Insufficient resources\n");
+ return BC_STS_INSUFF_RES;
+ }
+
+ rpkt->dio_req = ioreq;
+ tag = rpkt->pkt_tag;
+
+ sts = crystalhd_xlat_sgl_to_dma_desc(ioreq, &rpkt->desc_mem, &uv_desc_ix);
+ if (sts != BC_STS_SUCCESS)
+ return sts;
+
+ rpkt->uv_phy_addr = 0;
+
+ /* Store the address of UV in the rx packet for post*/
+ if (uv_desc_ix)
+ rpkt->uv_phy_addr = rpkt->desc_mem.phy_addr +
+ (sizeof(dma_descriptor) * (uv_desc_ix + 1));
+
+ if (en_post)
+ sts = crystalhd_hw_post_cap_buff(hw, rpkt);
+ else
+ sts = crystalhd_dioq_add(hw->rx_freeq, rpkt, false, tag);
+
+ return sts;
+}
+
+BC_STATUS crystalhd_hw_get_cap_buffer(struct crystalhd_hw *hw,
+ BC_PIC_INFO_BLOCK *pib,
+ crystalhd_dio_req **ioreq)
+{
+ crystalhd_rx_dma_pkt *rpkt;
+ uint32_t timeout = BC_PROC_OUTPUT_TIMEOUT / 1000;
+ uint32_t sig_pending = 0;
+
+
+ if (!hw || !ioreq || !pib) {
+ BCMLOG_ERR("Invalid Arguments\n");
+ return BC_STS_INV_ARG;
+ }
+
+ rpkt = crystalhd_dioq_fetch_wait(hw->rx_rdyq, timeout, &sig_pending);
+ if (!rpkt) {
+ if (sig_pending) {
+ BCMLOG(BCMLOG_INFO, "wait on frame time out %d\n", sig_pending);
+ return BC_STS_IO_USER_ABORT;
+ } else {
+ return BC_STS_TIMEOUT;
+ }
+ }
+
+ rpkt->dio_req->uinfo.comp_flags = rpkt->flags;
+
+ if (rpkt->flags & COMP_FLAG_PIB_VALID)
+ memcpy(pib, &rpkt->pib, sizeof(*pib));
+
+ *ioreq = rpkt->dio_req;
+
+ crystalhd_hw_free_rx_pkt(hw, rpkt);
+
+ return BC_STS_SUCCESS;
+}
+
+BC_STATUS crystalhd_hw_start_capture(struct crystalhd_hw *hw)
+{
+ crystalhd_rx_dma_pkt *rx_pkt;
+ BC_STATUS sts;
+ uint32_t i;
+
+ if (!hw) {
+ BCMLOG_ERR("Invalid Arguments\n");
+ return BC_STS_INV_ARG;
+ }
+
+ /* This is start of capture.. Post to both the lists.. */
+ for (i = 0; i < DMA_ENGINE_CNT; i++) {
+ rx_pkt = crystalhd_dioq_fetch(hw->rx_freeq);
+ if (!rx_pkt)
+ return BC_STS_NO_DATA;
+ sts = crystalhd_hw_post_cap_buff(hw, rx_pkt);
+ if (BC_STS_SUCCESS != sts)
+ break;
+
+ }
+
+ return BC_STS_SUCCESS;
+}
+
+BC_STATUS crystalhd_hw_stop_capture(struct crystalhd_hw *hw)
+{
+ void *temp = NULL;
+
+ if (!hw) {
+ BCMLOG_ERR("Invalid Arguments\n");
+ return BC_STS_INV_ARG;
+ }
+
+ crystalhd_stop_rx_dma_engine(hw);
+
+ do {
+ temp = crystalhd_dioq_fetch(hw->rx_freeq);
+ if (temp)
+ crystalhd_rx_pkt_rel_call_back(hw, temp);
+ } while (temp);
+
+ return BC_STS_SUCCESS;
+}
+
+BC_STATUS crystalhd_hw_pause(struct crystalhd_hw *hw)
+{
+ hw->stats.pause_cnt++;
+ hw->stop_pending = 1;
+
+ if ((hw->rx_list_sts[0] == sts_free) &&
+ (hw->rx_list_sts[1] == sts_free))
+ crystalhd_hw_finalize_pause(hw);
+
+ return BC_STS_SUCCESS;
+}
+
+BC_STATUS crystalhd_hw_unpause(struct crystalhd_hw *hw)
+{
+ BC_STATUS sts;
+ uint32_t aspm;
+
+ hw->stop_pending = 0;
+
+ aspm = crystalhd_reg_rd(hw->adp, PCIE_DLL_DATA_LINK_CONTROL);
+ aspm &= ~ASPM_L1_ENABLE;
+/* NAREN BCMLOG(BCMLOG_INFO, "aspm off\n"); */
+ crystalhd_reg_wr(hw->adp, PCIE_DLL_DATA_LINK_CONTROL, aspm);
+
+ sts = crystalhd_hw_start_capture(hw);
+ return sts;
+}
+
+BC_STATUS crystalhd_hw_suspend(struct crystalhd_hw *hw)
+{
+ BC_STATUS sts;
+
+ if (!hw) {
+ BCMLOG_ERR("Invalid Arguments\n");
+ return BC_STS_INV_ARG;
+ }
+
+ sts = crystalhd_put_ddr2sleep(hw);
+ if (sts != BC_STS_SUCCESS) {
+ BCMLOG_ERR("Failed to Put DDR To Sleep!!\n");
+ return BC_STS_ERROR;
+ }
+
+ if (!crystalhd_stop_device(hw->adp)) {
+ BCMLOG_ERR("Failed to Stop Device!!\n");
+ return BC_STS_ERROR;
+ }
+
+ return BC_STS_SUCCESS;
+}
+
+void crystalhd_hw_stats(struct crystalhd_hw *hw, struct crystalhd_hw_stats *stats)
+{
+ if (!hw) {
+ BCMLOG_ERR("Invalid Arguments\n");
+ return;
+ }
+
+ /* if called w/NULL stats, its a req to zero out the stats */
+ if (!stats) {
+ memset(&hw->stats, 0, sizeof(hw->stats));
+ return;
+ }
+
+ hw->stats.freeq_count = crystalhd_dioq_count(hw->rx_freeq);
+ hw->stats.rdyq_count = crystalhd_dioq_count(hw->rx_rdyq);
+ memcpy(stats, &hw->stats, sizeof(*stats));
+}
+
+BC_STATUS crystalhd_hw_set_core_clock(struct crystalhd_hw *hw)
+{
+ uint32_t reg, n, i;
+ uint32_t vco_mg, refresh_reg;
+
+ if (!hw) {
+ BCMLOG_ERR("Invalid Arguments\n");
+ return BC_STS_INV_ARG;
+ }
+
+ /* FIXME: jarod: wha? */
+ /*n = (hw->core_clock_mhz * 3) / 20 + 1; */
+ n = hw->core_clock_mhz/5;
+
+ if (n == hw->prev_n)
+ return BC_STS_CLK_NOCHG;
+
+ if (hw->pwr_lock > 0) {
+ /* BCMLOG(BCMLOG_INFO,"pwr_lock is %u\n", hw->pwr_lock) */
+ return BC_STS_CLK_NOCHG;
+ }
+
+ i = n * 27;
+ if (i < 560)
+ vco_mg = 0;
+ else if (i < 900)
+ vco_mg = 1;
+ else if (i < 1030)
+ vco_mg = 2;
+ else
+ vco_mg = 3;
+
+ reg = bc_dec_reg_rd(hw->adp, DecHt_PllACtl);
+
+ reg &= 0xFFFFCFC0;
+ reg |= n;
+ reg |= vco_mg << 12;
+
+ BCMLOG(BCMLOG_INFO, "clock is moving to %d with n %d with vco_mg %d\n",
+ hw->core_clock_mhz, n, vco_mg);
+
+ /* Change the DRAM refresh rate to accomodate the new frequency */
+ /* refresh reg = ((refresh_rate * clock_rate)/16) - 1; rounding up*/
+ refresh_reg = (7 * hw->core_clock_mhz / 16);
+ bc_dec_reg_wr(hw->adp, SDRAM_REF_PARAM, ((1 << 12) | refresh_reg));
+
+ bc_dec_reg_wr(hw->adp, DecHt_PllACtl, reg);
+
+ i = 0;
+
+ for (i = 0; i < 10; i++) {
+ reg = bc_dec_reg_rd(hw->adp, DecHt_PllACtl);
+
+ if (reg & 0x00020000) {
+ hw->prev_n = n;
+ /* FIXME: jarod: outputting a random "C" is... confusing... */
+ BCMLOG(BCMLOG_INFO, "C");
+ return BC_STS_SUCCESS;
+ } else {
+ msleep_interruptible(10);
+ }
+ }
+ BCMLOG(BCMLOG_INFO, "clk change failed\n");
+ return BC_STS_CLK_NOCHG;
+}
diff --git a/drivers/staging/crystalhd/crystalhd_hw.h b/drivers/staging/crystalhd/crystalhd_hw.h
new file mode 100644
index 00000000000..1c6318e912a
--- /dev/null
+++ b/drivers/staging/crystalhd/crystalhd_hw.h
@@ -0,0 +1,398 @@
+/***************************************************************************
+ * Copyright (c) 2005-2009, Broadcom Corporation.
+ *
+ * Name: crystalhd_hw . h
+ *
+ * Description:
+ * BCM70012 Linux driver hardware layer.
+ *
+ * HISTORY:
+ *
+ **********************************************************************
+ * This file is part of the crystalhd device driver.
+ *
+ * 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, version 2 of the License.
+ *
+ * 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 driver. If not, see <http://www.gnu.org/licenses/>.
+ **********************************************************************/
+
+#ifndef _CRYSTALHD_HW_H_
+#define _CRYSTALHD_HW_H_
+
+#include "crystalhd_misc.h"
+#include "crystalhd_fw_if.h"
+
+/* HW constants..*/
+#define DMA_ENGINE_CNT 2
+#define MAX_PIB_Q_DEPTH 64
+#define MIN_PIB_Q_DEPTH 2
+#define WR_POINTER_OFF 4
+
+#define ASPM_L1_ENABLE (BC_BIT(27))
+
+/*************************************************
+ 7412 Decoder Registers.
+**************************************************/
+#define FW_CMD_BUFF_SZ 64
+#define TS_Host2CpuSnd 0x00000100
+#define Hst2CpuMbx1 0x00100F00
+#define Cpu2HstMbx1 0x00100F04
+#define MbxStat1 0x00100F08
+#define Stream2Host_Intr_Sts 0x00100F24
+#define C011_RET_SUCCESS 0x0 /* Reutrn status of firmware command. */
+
+/* TS input status register */
+#define TS_StreamAFIFOStatus 0x0010044C
+#define TS_StreamBFIFOStatus 0x0010084C
+
+/*UART Selection definitions*/
+#define UartSelectA 0x00100300
+#define UartSelectB 0x00100304
+
+#define BSVS_UART_DEC_NONE 0x00
+#define BSVS_UART_DEC_OUTER 0x01
+#define BSVS_UART_DEC_INNER 0x02
+#define BSVS_UART_STREAM 0x03
+
+/* Code-In fifo */
+#define REG_DecCA_RegCinCTL 0xa00
+#define REG_DecCA_RegCinBase 0xa0c
+#define REG_DecCA_RegCinEnd 0xa10
+#define REG_DecCA_RegCinWrPtr 0xa04
+#define REG_DecCA_RegCinRdPtr 0xa08
+
+#define REG_Dec_TsUser0Base 0x100864
+#define REG_Dec_TsUser0Rdptr 0x100868
+#define REG_Dec_TsUser0Wrptr 0x10086C
+#define REG_Dec_TsUser0End 0x100874
+
+/* ASF Case ...*/
+#define REG_Dec_TsAudCDB2Base 0x10036c
+#define REG_Dec_TsAudCDB2Rdptr 0x100378
+#define REG_Dec_TsAudCDB2Wrptr 0x100374
+#define REG_Dec_TsAudCDB2End 0x100370
+
+/* DRAM bringup Registers */
+#define SDRAM_PARAM 0x00040804
+#define SDRAM_PRECHARGE 0x000408B0
+#define SDRAM_EXT_MODE 0x000408A4
+#define SDRAM_MODE 0x000408A0
+#define SDRAM_REFRESH 0x00040890
+#define SDRAM_REF_PARAM 0x00040808
+
+#define DecHt_PllACtl 0x34000C
+#define DecHt_PllBCtl 0x340010
+#define DecHt_PllCCtl 0x340014
+#define DecHt_PllDCtl 0x340034
+#define DecHt_PllECtl 0x340038
+#define AUD_DSP_MISC_SOFT_RESET 0x00240104
+#define AIO_MISC_PLL_RESET 0x0026000C
+#define PCIE_CLK_REQ_REG 0xDC
+#define PCI_CLK_REQ_ENABLE (BC_BIT(8))
+
+/*************************************************
+ F/W Copy engine definitions..
+**************************************************/
+#define BC_FWIMG_ST_ADDR 0x00000000
+/* FIXME: jarod: there's a kernel function that'll do this for us... */
+#define rotr32_1(x, n) (((x) >> n) | ((x) << (32 - n)))
+#define bswap_32_1(x) ((rotr32_1((x), 24) & 0x00ff00ff) | (rotr32_1((x), 8) & 0xff00ff00))
+
+#define DecHt_HostSwReset 0x340000
+#define BC_DRAM_FW_CFG_ADDR 0x001c2000
+
+typedef union _addr_64_ {
+ struct {
+ uint32_t low_part;
+ uint32_t high_part;
+ };
+
+ uint64_t full_addr;
+
+} addr_64;
+
+typedef union _intr_mask_reg_ {
+ struct {
+ uint32_t mask_tx_done:1;
+ uint32_t mask_tx_err:1;
+ uint32_t mask_rx_done:1;
+ uint32_t mask_rx_err:1;
+ uint32_t mask_pcie_err:1;
+ uint32_t mask_pcie_rbusmast_err:1;
+ uint32_t mask_pcie_rgr_bridge:1;
+ uint32_t reserved:25;
+ };
+
+ uint32_t whole_reg;
+
+} intr_mask_reg;
+
+typedef union _link_misc_perst_deco_ctrl_ {
+ struct {
+ uint32_t bcm7412_rst:1; /* 1 -> BCM7412 is held in reset. Reset value 1.*/
+ uint32_t reserved0:3; /* Reserved.No Effect*/
+ uint32_t stop_bcm_7412_clk:1; /* 1 ->Stops branch of 27MHz clk used to clk BCM7412*/
+ uint32_t reserved1:27; /* Reseved. No Effect*/
+ };
+
+ uint32_t whole_reg;
+
+} link_misc_perst_deco_ctrl;
+
+typedef union _link_misc_perst_clk_ctrl_ {
+ struct {
+ uint32_t sel_alt_clk:1; /* When set, selects a 6.75MHz clock as the source of core_clk */
+ uint32_t stop_core_clk:1; /* When set, stops the branch of core_clk that is not needed for low power operation */
+ uint32_t pll_pwr_dn:1; /* When set, powers down the main PLL. The alternate clock bit should be set
+ to select an alternate clock before setting this bit.*/
+ uint32_t reserved0:5; /* Reserved */
+ uint32_t pll_mult:8; /* This setting controls the multiplier for the PLL. */
+ uint32_t pll_div:4; /* This setting controls the divider for the PLL. */
+ uint32_t reserved1:12; /* Reserved */
+ };
+
+ uint32_t whole_reg;
+
+} link_misc_perst_clk_ctrl;
+
+
+typedef union _link_misc_perst_decoder_ctrl_ {
+ struct {
+ uint32_t bcm_7412_rst:1; /* 1 -> BCM7412 is held in reset. Reset value 1.*/
+ uint32_t res0:3; /* Reserved.No Effect*/
+ uint32_t stop_7412_clk:1; /* 1 ->Stops branch of 27MHz clk used to clk BCM7412*/
+ uint32_t res1:27; /* Reseved. No Effect */
+ };
+
+ uint32_t whole_reg;
+
+} link_misc_perst_decoder_ctrl;
+
+
+typedef union _desc_low_addr_reg_ {
+ struct {
+ uint32_t list_valid:1;
+ uint32_t reserved:4;
+ uint32_t low_addr:27;
+ };
+
+ uint32_t whole_reg;
+
+} desc_low_addr_reg;
+
+typedef struct _dma_descriptor_ { /* 8 32-bit values */
+ /* 0th u32 */
+ uint32_t sdram_buff_addr:28; /* bits 0-27: SDRAM Address */
+ uint32_t res0:4; /* bits 28-31: Reserved */
+
+ /* 1st u32 */
+ uint32_t buff_addr_low; /* 1 buffer address low */
+ uint32_t buff_addr_high; /* 2 buffer address high */
+
+ /* 3rd u32 */
+ uint32_t res2:2; /* 0-1 - Reserved */
+ uint32_t xfer_size:23; /* 2-24 = Xfer size in words */
+ uint32_t res3:6; /* 25-30 reserved */
+ uint32_t intr_enable:1; /* 31 - Interrupt After this desc */
+
+ /* 4th u32 */
+ uint32_t endian_xlat_align:2; /* 0-1 Endian Translation */
+ uint32_t next_desc_cont:1; /* 2 - Next desc is in contig memory */
+ uint32_t res4:25; /* 3 - 27 Reserved bits */
+ uint32_t fill_bytes:2; /* 28-29 Bits Fill Bytes */
+ uint32_t dma_dir:1; /* 30 bit DMA Direction */
+ uint32_t last_rec_indicator:1; /* 31 bit Last Record Indicator */
+
+ /* 5th u32 */
+ uint32_t next_desc_addr_low; /* 32-bits Next Desc Addr lower */
+
+ /* 6th u32 */
+ uint32_t next_desc_addr_high; /* 32-bits Next Desc Addr Higher */
+
+ /* 7th u32 */
+ uint32_t res8; /* Last 32bits reserved */
+
+} dma_descriptor, *pdma_descriptor;
+
+/*
+ * We will allocate the memory in 4K pages
+ * the linked list will be a list of 32 byte descriptors.
+ * The virtual address will determine what should be freed.
+ */
+typedef struct _dma_desc_mem_ {
+ pdma_descriptor pdma_desc_start; /* 32-bytes for dma descriptor. should be first element */
+ dma_addr_t phy_addr; /* physical address of each DMA desc */
+ uint32_t sz;
+ struct _dma_desc_mem_ *Next; /* points to Next Descriptor in chain */
+
+} dma_desc_mem, *pdma_desc_mem;
+
+
+
+typedef enum _list_sts_ {
+ sts_free = 0,
+
+ /* RX-Y Bits 0:7 */
+ rx_waiting_y_intr = 0x00000001,
+ rx_y_error = 0x00000004,
+
+ /* RX-UV Bits 8:16 */
+ rx_waiting_uv_intr = 0x0000100,
+ rx_uv_error = 0x0000400,
+
+ rx_sts_waiting = (rx_waiting_y_intr|rx_waiting_uv_intr),
+ rx_sts_error = (rx_y_error|rx_uv_error),
+
+ rx_y_mask = 0x000000FF,
+ rx_uv_mask = 0x0000FF00,
+
+} list_sts;
+
+typedef struct _tx_dma_pkt_ {
+ dma_desc_mem desc_mem;
+ hw_comp_callback call_back;
+ crystalhd_dio_req *dio_req;
+ wait_queue_head_t *cb_event;
+ uint32_t list_tag;
+
+} tx_dma_pkt;
+
+typedef struct _crystalhd_rx_dma_pkt {
+ dma_desc_mem desc_mem;
+ crystalhd_dio_req *dio_req;
+ uint32_t pkt_tag;
+ uint32_t flags;
+ BC_PIC_INFO_BLOCK pib;
+ dma_addr_t uv_phy_addr;
+ struct _crystalhd_rx_dma_pkt *next;
+
+} crystalhd_rx_dma_pkt;
+
+struct crystalhd_hw_stats{
+ uint32_t rx_errors;
+ uint32_t tx_errors;
+ uint32_t freeq_count;
+ uint32_t rdyq_count;
+ uint32_t num_interrupts;
+ uint32_t dev_interrupts;
+ uint32_t cin_busy;
+ uint32_t pause_cnt;
+};
+
+struct crystalhd_hw {
+ tx_dma_pkt tx_pkt_pool[DMA_ENGINE_CNT];
+ spinlock_t lock;
+
+ uint32_t tx_ioq_tag_seed;
+ uint32_t tx_list_post_index;
+
+ crystalhd_rx_dma_pkt *rx_pkt_pool_head;
+ uint32_t rx_pkt_tag_seed;
+
+ bool dev_started;
+ void *adp;
+
+ wait_queue_head_t *pfw_cmd_event;
+ int fwcmd_evt_sts;
+
+ uint32_t pib_del_Q_addr;
+ uint32_t pib_rel_Q_addr;
+
+ crystalhd_dioq_t *tx_freeq;
+ crystalhd_dioq_t *tx_actq;
+
+ /* Rx DMA Engine Specific Locks */
+ spinlock_t rx_lock;
+ uint32_t rx_list_post_index;
+ list_sts rx_list_sts[DMA_ENGINE_CNT];
+ crystalhd_dioq_t *rx_rdyq;
+ crystalhd_dioq_t *rx_freeq;
+ crystalhd_dioq_t *rx_actq;
+ uint32_t stop_pending;
+
+ /* HW counters.. */
+ struct crystalhd_hw_stats stats;
+
+ /* Core clock in MHz */
+ uint32_t core_clock_mhz;
+ uint32_t prev_n;
+ uint32_t pwr_lock;
+};
+
+/* Clock defines for power control */
+#define CLOCK_PRESET 175
+
+/* DMA engine register BIT mask wrappers.. */
+#define DMA_START_BIT MISC1_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_MASK
+
+#define GET_RX_INTR_MASK (INTR_INTR_STATUS_L1_UV_RX_DMA_ERR_INTR_MASK | \
+ INTR_INTR_STATUS_L1_UV_RX_DMA_DONE_INTR_MASK | \
+ INTR_INTR_STATUS_L1_Y_RX_DMA_ERR_INTR_MASK | \
+ INTR_INTR_STATUS_L1_Y_RX_DMA_DONE_INTR_MASK | \
+ INTR_INTR_STATUS_L0_UV_RX_DMA_ERR_INTR_MASK | \
+ INTR_INTR_STATUS_L0_UV_RX_DMA_DONE_INTR_MASK | \
+ INTR_INTR_STATUS_L0_Y_RX_DMA_ERR_INTR_MASK | \
+ INTR_INTR_STATUS_L0_Y_RX_DMA_DONE_INTR_MASK)
+
+#define GET_Y0_ERR_MSK (MISC1_Y_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_MASK | \
+ MISC1_Y_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK | \
+ MISC1_Y_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_MASK | \
+ MISC1_Y_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK)
+
+#define GET_UV0_ERR_MSK (MISC1_UV_RX_ERROR_STATUS_RX_L0_OVERRUN_ERROR_MASK | \
+ MISC1_UV_RX_ERROR_STATUS_RX_L0_UNDERRUN_ERROR_MASK | \
+ MISC1_UV_RX_ERROR_STATUS_RX_L0_DESC_TX_ABORT_ERRORS_MASK | \
+ MISC1_UV_RX_ERROR_STATUS_RX_L0_FIFO_FULL_ERRORS_MASK)
+
+#define GET_Y1_ERR_MSK (MISC1_Y_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_MASK | \
+ MISC1_Y_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK | \
+ MISC1_Y_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_MASK | \
+ MISC1_Y_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK)
+
+#define GET_UV1_ERR_MSK (MISC1_UV_RX_ERROR_STATUS_RX_L1_OVERRUN_ERROR_MASK | \
+ MISC1_UV_RX_ERROR_STATUS_RX_L1_UNDERRUN_ERROR_MASK | \
+ MISC1_UV_RX_ERROR_STATUS_RX_L1_DESC_TX_ABORT_ERRORS_MASK | \
+ MISC1_UV_RX_ERROR_STATUS_RX_L1_FIFO_FULL_ERRORS_MASK)
+
+
+/**** API Exposed to the other layers ****/
+BC_STATUS crystalhd_download_fw(struct crystalhd_adp *adp,
+ void *buffer, uint32_t sz);
+BC_STATUS crystalhd_do_fw_cmd(struct crystalhd_hw *hw, BC_FW_CMD *fw_cmd);
+bool crystalhd_hw_interrupt(struct crystalhd_adp *adp, struct crystalhd_hw *hw);
+BC_STATUS crystalhd_hw_open(struct crystalhd_hw *, struct crystalhd_adp *);
+BC_STATUS crystalhd_hw_close(struct crystalhd_hw *);
+BC_STATUS crystalhd_hw_setup_dma_rings(struct crystalhd_hw *);
+BC_STATUS crystalhd_hw_free_dma_rings(struct crystalhd_hw *);
+
+
+BC_STATUS crystalhd_hw_post_tx(struct crystalhd_hw *hw, crystalhd_dio_req *ioreq,
+ hw_comp_callback call_back,
+ wait_queue_head_t *cb_event,
+ uint32_t *list_id, uint8_t data_flags);
+
+BC_STATUS crystalhd_hw_pause(struct crystalhd_hw *hw);
+BC_STATUS crystalhd_hw_unpause(struct crystalhd_hw *hw);
+BC_STATUS crystalhd_hw_suspend(struct crystalhd_hw *hw);
+BC_STATUS crystalhd_hw_cancel_tx(struct crystalhd_hw *hw, uint32_t list_id);
+BC_STATUS crystalhd_hw_add_cap_buffer(struct crystalhd_hw *hw,
+ crystalhd_dio_req *ioreq, bool en_post);
+BC_STATUS crystalhd_hw_get_cap_buffer(struct crystalhd_hw *hw,
+ BC_PIC_INFO_BLOCK *pib,
+ crystalhd_dio_req **ioreq);
+BC_STATUS crystalhd_hw_stop_capture(struct crystalhd_hw *hw);
+BC_STATUS crystalhd_hw_start_capture(struct crystalhd_hw *hw);
+void crystalhd_hw_stats(struct crystalhd_hw *hw, struct crystalhd_hw_stats *stats);
+
+/* API to program the core clock on the decoder */
+BC_STATUS crystalhd_hw_set_core_clock(struct crystalhd_hw *);
+
+#endif
diff --git a/drivers/staging/crystalhd/crystalhd_lnx.c b/drivers/staging/crystalhd/crystalhd_lnx.c
new file mode 100644
index 00000000000..3eac70aa213
--- /dev/null
+++ b/drivers/staging/crystalhd/crystalhd_lnx.c
@@ -0,0 +1,765 @@
+/***************************************************************************
+ BCM70010 Linux driver
+ Copyright (c) 2005-2009, Broadcom Corporation.
+
+ 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, version 2 of the License.
+
+ 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 driver. If not, see <http://www.gnu.org/licenses/>.
+***************************************************************************/
+
+#include <linux/version.h>
+
+#include "crystalhd_lnx.h"
+
+static struct class *crystalhd_class;
+
+static struct crystalhd_adp *g_adp_info;
+
+static irqreturn_t chd_dec_isr(int irq, void *arg)
+{
+ struct crystalhd_adp *adp = (struct crystalhd_adp *) arg;
+ int rc = 0;
+ if (adp)
+ rc = crystalhd_cmd_interrupt(&adp->cmds);
+
+ return IRQ_RETVAL(rc);
+}
+
+static int chd_dec_enable_int(struct crystalhd_adp *adp)
+{
+ int rc = 0;
+
+ if (!adp || !adp->pdev) {
+ BCMLOG_ERR("Invalid arg!!\n");
+ return -EINVAL;
+ }
+
+ if (adp->pdev->msi_enabled)
+ adp->msi = 1;
+ else
+ adp->msi = pci_enable_msi(adp->pdev);
+
+ rc = request_irq(adp->pdev->irq, chd_dec_isr, IRQF_SHARED,
+ adp->name, (void *)adp);
+ if (rc) {
+ BCMLOG_ERR("Interrupt request failed.. \n");
+ pci_disable_msi(adp->pdev);
+ }
+
+ return rc;
+}
+
+static int chd_dec_disable_int(struct crystalhd_adp *adp)
+{
+ if (!adp || !adp->pdev) {
+ BCMLOG_ERR("Invalid arg!!\n");
+ return -EINVAL;
+ }
+
+ free_irq(adp->pdev->irq, adp);
+
+ if (adp->msi)
+ pci_disable_msi(adp->pdev);
+
+ return 0;
+}
+
+crystalhd_ioctl_data *chd_dec_alloc_iodata(struct crystalhd_adp *adp, bool isr)
+{
+ unsigned long flags = 0;
+ crystalhd_ioctl_data *temp;
+
+ if (!adp)
+ return NULL;
+
+ spin_lock_irqsave(&adp->lock, flags);
+
+ temp = adp->idata_free_head;
+ if (temp) {
+ adp->idata_free_head = adp->idata_free_head->next;
+ memset(temp, 0, sizeof(*temp));
+ }
+
+ spin_unlock_irqrestore(&adp->lock, flags);
+ return temp;
+}
+
+void chd_dec_free_iodata(struct crystalhd_adp *adp, crystalhd_ioctl_data *iodata,
+ bool isr)
+{
+ unsigned long flags = 0;
+
+ if (!adp || !iodata)
+ return;
+
+ spin_lock_irqsave(&adp->lock, flags);
+ iodata->next = adp->idata_free_head;
+ adp->idata_free_head = iodata;
+ spin_unlock_irqrestore(&adp->lock, flags);
+}
+
+static inline int crystalhd_user_data(unsigned long ud, void *dr, int size, int set)
+{
+ int rc;
+
+ if (!ud || !dr) {
+ BCMLOG_ERR("Invalid arg \n");
+ return -EINVAL;
+ }
+
+ if (set)
+ rc = copy_to_user((void *)ud, dr, size);
+ else
+ rc = copy_from_user(dr, (void *)ud, size);
+
+ if (rc) {
+ BCMLOG_ERR("Invalid args for command \n");
+ rc = -EFAULT;
+ }
+
+ return rc;
+}
+
+static int chd_dec_fetch_cdata(struct crystalhd_adp *adp, crystalhd_ioctl_data *io,
+ uint32_t m_sz, unsigned long ua)
+{
+ unsigned long ua_off;
+ int rc = 0;
+
+ if (!adp || !io || !ua || !m_sz) {
+ BCMLOG_ERR("Invalid Arg!!\n");
+ return -EINVAL;
+ }
+
+ io->add_cdata = vmalloc(m_sz);
+ if (!io->add_cdata) {
+ BCMLOG_ERR("kalloc fail for sz:%x\n", m_sz);
+ return -ENOMEM;
+ }
+
+ io->add_cdata_sz = m_sz;
+ ua_off = ua + sizeof(io->udata);
+ rc = crystalhd_user_data(ua_off, io->add_cdata, io->add_cdata_sz, 0);
+ if (rc) {
+ BCMLOG_ERR("failed to pull add_cdata sz:%x ua_off:%x\n",
+ io->add_cdata_sz, (unsigned int)ua_off);
+ if (io->add_cdata) {
+ kfree(io->add_cdata);
+ io->add_cdata = NULL;
+ }
+ return -ENODATA;
+ }
+
+ return rc;
+}
+
+static int chd_dec_release_cdata(struct crystalhd_adp *adp,
+ crystalhd_ioctl_data *io, unsigned long ua)
+{
+ unsigned long ua_off;
+ int rc;
+
+ if (!adp || !io || !ua) {
+ BCMLOG_ERR("Invalid Arg!!\n");
+ return -EINVAL;
+ }
+
+ if (io->cmd != BCM_IOC_FW_DOWNLOAD) {
+ ua_off = ua + sizeof(io->udata);
+ rc = crystalhd_user_data(ua_off, io->add_cdata,
+ io->add_cdata_sz, 1);
+ if (rc) {
+ BCMLOG_ERR("failed to push add_cdata sz:%x ua_off:%x\n",
+ io->add_cdata_sz, (unsigned int)ua_off);
+ return -ENODATA;
+ }
+ }
+
+ if (io->add_cdata) {
+ vfree(io->add_cdata);
+ io->add_cdata = NULL;
+ }
+
+ return 0;
+}
+
+static int chd_dec_proc_user_data(struct crystalhd_adp *adp,
+ crystalhd_ioctl_data *io,
+ unsigned long ua, int set)
+{
+ int rc;
+ uint32_t m_sz = 0;
+
+ if (!adp || !io || !ua) {
+ BCMLOG_ERR("Invalid Arg!!\n");
+ return -EINVAL;
+ }
+
+ rc = crystalhd_user_data(ua, &io->udata, sizeof(io->udata), set);
+ if (rc) {
+ BCMLOG_ERR("failed to %s iodata \n", (set ? "set" : "get"));
+ return rc;
+ }
+
+ switch (io->cmd) {
+ case BCM_IOC_MEM_RD:
+ case BCM_IOC_MEM_WR:
+ case BCM_IOC_FW_DOWNLOAD:
+ m_sz = io->udata.u.devMem.NumDwords * 4;
+ if (set)
+ rc = chd_dec_release_cdata(adp, io, ua);
+ else
+ rc = chd_dec_fetch_cdata(adp, io, m_sz, ua);
+ break;
+ default:
+ break;
+ }
+
+ return rc;
+}
+
+static int chd_dec_api_cmd(struct crystalhd_adp *adp, unsigned long ua,
+ uint32_t uid, uint32_t cmd, crystalhd_cmd_proc func)
+{
+ int rc;
+ crystalhd_ioctl_data *temp;
+ BC_STATUS sts = BC_STS_SUCCESS;
+
+ temp = chd_dec_alloc_iodata(adp, 0);
+ if (!temp) {
+ BCMLOG_ERR("Failed to get iodata..\n");
+ return -EINVAL;
+ }
+
+ temp->u_id = uid;
+ temp->cmd = cmd;
+
+ rc = chd_dec_proc_user_data(adp, temp, ua, 0);
+ if (!rc) {
+ sts = func(&adp->cmds, temp);
+ if (sts == BC_STS_PENDING)
+ sts = BC_STS_NOT_IMPL;
+ temp->udata.RetSts = sts;
+ rc = chd_dec_proc_user_data(adp, temp, ua, 1);
+ }
+
+ if (temp) {
+ chd_dec_free_iodata(adp, temp, 0);
+ temp = NULL;
+ }
+
+ return rc;
+}
+
+/* API interfaces */
+static int chd_dec_ioctl(struct inode *in, struct file *fd,
+ unsigned int cmd, unsigned long ua)
+{
+ struct crystalhd_adp *adp = chd_get_adp();
+ crystalhd_cmd_proc cproc;
+ struct crystalhd_user *uc;
+
+ if (!adp || !fd) {
+ BCMLOG_ERR("Invalid adp\n");
+ return -EINVAL;
+ }
+
+ uc = (struct crystalhd_user *)fd->private_data;
+ if (!uc) {
+ BCMLOG_ERR("Failed to get uc\n");
+ return -ENODATA;
+ }
+
+ cproc = crystalhd_get_cmd_proc(&adp->cmds, cmd, uc);
+ if (!cproc) {
+ BCMLOG_ERR("Unhandled command: %d\n", cmd);
+ return -EINVAL;
+ }
+
+ return chd_dec_api_cmd(adp, ua, uc->uid, cmd, cproc);
+}
+
+static int chd_dec_open(struct inode *in, struct file *fd)
+{
+ struct crystalhd_adp *adp = chd_get_adp();
+ int rc = 0;
+ BC_STATUS sts = BC_STS_SUCCESS;
+ struct crystalhd_user *uc = NULL;
+
+ BCMLOG_ENTER;
+ if (!adp) {
+ BCMLOG_ERR("Invalid adp\n");
+ return -EINVAL;
+ }
+
+ if (adp->cfg_users >= BC_LINK_MAX_OPENS) {
+ BCMLOG(BCMLOG_INFO, "Already in use.%d\n", adp->cfg_users);
+ return -EBUSY;
+ }
+
+ sts = crystalhd_user_open(&adp->cmds, &uc);
+ if (sts != BC_STS_SUCCESS) {
+ BCMLOG_ERR("cmd_user_open - %d \n", sts);
+ rc = -EBUSY;
+ }
+
+ adp->cfg_users++;
+
+ fd->private_data = uc;
+
+ return rc;
+}
+
+static int chd_dec_close(struct inode *in, struct file *fd)
+{
+ struct crystalhd_adp *adp = chd_get_adp();
+ struct crystalhd_user *uc;
+
+ BCMLOG_ENTER;
+ if (!adp) {
+ BCMLOG_ERR("Invalid adp \n");
+ return -EINVAL;
+ }
+
+ uc = (struct crystalhd_user *)fd->private_data;
+ if (!uc) {
+ BCMLOG_ERR("Failed to get uc\n");
+ return -ENODATA;
+ }
+
+ crystalhd_user_close(&adp->cmds, uc);
+
+ adp->cfg_users--;
+
+ return 0;
+}
+
+static const struct file_operations chd_dec_fops = {
+ .owner = THIS_MODULE,
+ .ioctl = chd_dec_ioctl,
+ .open = chd_dec_open,
+ .release = chd_dec_close,
+};
+
+static int __devinit chd_dec_init_chdev(struct crystalhd_adp *adp)
+{
+ crystalhd_ioctl_data *temp;
+ struct device *dev;
+ int rc = -ENODEV, i = 0;
+
+ if (!adp)
+ goto fail;
+
+ adp->chd_dec_major = register_chrdev(0, CRYSTALHD_API_NAME,
+ &chd_dec_fops);
+ if (adp->chd_dec_major < 0) {
+ BCMLOG_ERR("Failed to create config dev\n");
+ rc = adp->chd_dec_major;
+ goto fail;
+ }
+
+ /* register crystalhd class */
+ crystalhd_class = class_create(THIS_MODULE, "crystalhd");
+ if (IS_ERR(crystalhd_class)) {
+ BCMLOG_ERR("failed to create class\n");
+ goto fail;
+ }
+
+ dev = device_create(crystalhd_class, NULL, MKDEV(adp->chd_dec_major, 0),
+ NULL, "crystalhd");
+ if (!dev) {
+ BCMLOG_ERR("failed to create device\n");
+ goto device_create_fail;
+ }
+
+ rc = crystalhd_create_elem_pool(adp, BC_LINK_ELEM_POOL_SZ);
+ if (rc) {
+ BCMLOG_ERR("failed to create device\n");
+ goto elem_pool_fail;
+ }
+
+ /* Allocate general purpose ioctl pool. */
+ for (i = 0; i < CHD_IODATA_POOL_SZ; i++) {
+ /* FIXME: jarod: why atomic? */
+ temp = kzalloc(sizeof(crystalhd_ioctl_data), GFP_ATOMIC);
+ if (!temp) {
+ BCMLOG_ERR("ioctl data pool kzalloc failed\n");
+ rc = -ENOMEM;
+ goto kzalloc_fail;
+ }
+ /* Add to global pool.. */
+ chd_dec_free_iodata(adp, temp, 0);
+ }
+
+ return 0;
+
+kzalloc_fail:
+ crystalhd_delete_elem_pool(adp);
+elem_pool_fail:
+ device_destroy(crystalhd_class, MKDEV(adp->chd_dec_major, 0));
+device_create_fail:
+ class_destroy(crystalhd_class);
+fail:
+ return rc;
+}
+
+static void __devexit chd_dec_release_chdev(struct crystalhd_adp *adp)
+{
+ crystalhd_ioctl_data *temp = NULL;
+ if (!adp)
+ return;
+
+ if (adp->chd_dec_major > 0) {
+ /* unregister crystalhd class */
+ device_destroy(crystalhd_class, MKDEV(adp->chd_dec_major, 0));
+ unregister_chrdev(adp->chd_dec_major, CRYSTALHD_API_NAME);
+ BCMLOG(BCMLOG_INFO, "released api device - %d\n",
+ adp->chd_dec_major);
+ class_destroy(crystalhd_class);
+ }
+ adp->chd_dec_major = 0;
+
+ /* Clear iodata pool.. */
+ do {
+ temp = chd_dec_alloc_iodata(adp, 0);
+ if (temp)
+ kfree(temp);
+ } while (temp);
+
+ crystalhd_delete_elem_pool(adp);
+}
+
+static int __devinit chd_pci_reserve_mem(struct crystalhd_adp *pinfo)
+{
+ int rc;
+ unsigned long bar2 = pci_resource_start(pinfo->pdev, 2);
+ uint32_t mem_len = pci_resource_len(pinfo->pdev, 2);
+ unsigned long bar0 = pci_resource_start(pinfo->pdev, 0);
+ uint32_t i2o_len = pci_resource_len(pinfo->pdev, 0);
+
+ BCMLOG(BCMLOG_SSTEP, "bar2:0x%lx-0x%08x bar0:0x%lx-0x%08x\n",
+ bar2, mem_len, bar0, i2o_len);
+
+ rc = check_mem_region(bar2, mem_len);
+ if (rc) {
+ BCMLOG_ERR("No valid mem region...\n");
+ return -ENOMEM;
+ }
+
+ pinfo->addr = ioremap_nocache(bar2, mem_len);
+ if (!pinfo->addr) {
+ BCMLOG_ERR("Failed to remap mem region...\n");
+ return -ENOMEM;
+ }
+
+ pinfo->pci_mem_start = bar2;
+ pinfo->pci_mem_len = mem_len;
+
+ rc = check_mem_region(bar0, i2o_len);
+ if (rc) {
+ BCMLOG_ERR("No valid mem region...\n");
+ return -ENOMEM;
+ }
+
+ pinfo->i2o_addr = ioremap_nocache(bar0, i2o_len);
+ if (!pinfo->i2o_addr) {
+ BCMLOG_ERR("Failed to remap mem region...\n");
+ return -ENOMEM;
+ }
+
+ pinfo->pci_i2o_start = bar0;
+ pinfo->pci_i2o_len = i2o_len;
+
+ rc = pci_request_regions(pinfo->pdev, pinfo->name);
+ if (rc < 0) {
+ BCMLOG_ERR("Region request failed: %d\n", rc);
+ return rc;
+ }
+
+ BCMLOG(BCMLOG_SSTEP, "Mapped addr:0x%08lx i2o_addr:0x%08lx\n",
+ (unsigned long)pinfo->addr, (unsigned long)pinfo->i2o_addr);
+
+ return 0;
+}
+
+static void __devexit chd_pci_release_mem(struct crystalhd_adp *pinfo)
+{
+ if (!pinfo)
+ return;
+
+ if (pinfo->addr)
+ iounmap(pinfo->addr);
+
+ if (pinfo->i2o_addr)
+ iounmap(pinfo->i2o_addr);
+
+ pci_release_regions(pinfo->pdev);
+}
+
+
+static void __devexit chd_dec_pci_remove(struct pci_dev *pdev)
+{
+ struct crystalhd_adp *pinfo;
+ BC_STATUS sts = BC_STS_SUCCESS;
+
+ BCMLOG_ENTER;
+
+ pinfo = (struct crystalhd_adp *) pci_get_drvdata(pdev);
+ if (!pinfo) {
+ BCMLOG_ERR("could not get adp\n");
+ return;
+ }
+
+ sts = crystalhd_delete_cmd_context(&pinfo->cmds);
+ if (sts != BC_STS_SUCCESS)
+ BCMLOG_ERR("cmd delete :%d \n", sts);
+
+ chd_dec_release_chdev(pinfo);
+
+ chd_dec_disable_int(pinfo);
+
+ chd_pci_release_mem(pinfo);
+ pci_disable_device(pinfo->pdev);
+
+ kfree(pinfo);
+ g_adp_info = NULL;
+}
+
+static int __devinit chd_dec_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *entry)
+{
+ struct crystalhd_adp *pinfo;
+ int rc;
+ BC_STATUS sts = BC_STS_SUCCESS;
+
+ BCMLOG(BCMLOG_DBG, "PCI_INFO: Vendor:0x%04x Device:0x%04x "
+ "s_vendor:0x%04x s_device: 0x%04x\n",
+ pdev->vendor, pdev->device, pdev->subsystem_vendor,
+ pdev->subsystem_device);
+
+ /* FIXME: jarod: why atomic? */
+ pinfo = kzalloc(sizeof(struct crystalhd_adp), GFP_ATOMIC);
+ if (!pinfo) {
+ BCMLOG_ERR("Failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ pinfo->pdev = pdev;
+
+ rc = pci_enable_device(pdev);
+ if (rc) {
+ BCMLOG_ERR("Failed to enable PCI device\n");
+ return rc;
+ }
+
+ snprintf(pinfo->name, 31, "crystalhd_pci_e:%d:%d:%d",
+ pdev->bus->number, PCI_SLOT(pdev->devfn),
+ PCI_FUNC(pdev->devfn));
+
+ rc = chd_pci_reserve_mem(pinfo);
+ if (rc) {
+ BCMLOG_ERR("Failed to setup memory regions.\n");
+ return -ENOMEM;
+ }
+
+ pinfo->present = 1;
+ pinfo->drv_data = entry->driver_data;
+
+ /* Setup adapter level lock.. */
+ spin_lock_init(&pinfo->lock);
+
+ /* setup api stuff.. */
+ chd_dec_init_chdev(pinfo);
+ rc = chd_dec_enable_int(pinfo);
+ if (rc) {
+ BCMLOG_ERR("_enable_int err:%d \n", rc);
+ pci_disable_device(pdev);
+ return -ENODEV;
+ }
+
+ /* Set dma mask... */
+ if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+ pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
+ pinfo->dmabits = 64;
+ } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+ pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+ pinfo->dmabits = 32;
+ } else {
+ BCMLOG_ERR("Unabled to setup DMA %d\n", rc);
+ pci_disable_device(pdev);
+ return -ENODEV;
+ }
+
+ sts = crystalhd_setup_cmd_context(&pinfo->cmds, pinfo);
+ if (sts != BC_STS_SUCCESS) {
+ BCMLOG_ERR("cmd setup :%d \n", sts);
+ pci_disable_device(pdev);
+ return -ENODEV;
+ }
+
+ pci_set_master(pdev);
+
+ pci_set_drvdata(pdev, pinfo);
+
+ g_adp_info = pinfo;
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+int chd_dec_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct crystalhd_adp *adp;
+ crystalhd_ioctl_data *temp;
+ BC_STATUS sts = BC_STS_SUCCESS;
+
+ adp = (struct crystalhd_adp *)pci_get_drvdata(pdev);
+ if (!adp) {
+ BCMLOG_ERR("could not get adp\n");
+ return -ENODEV;
+ }
+
+ temp = chd_dec_alloc_iodata(adp, false);
+ if (!temp) {
+ BCMLOG_ERR("could not get ioctl data\n");
+ return -ENODEV;
+ }
+
+ sts = crystalhd_suspend(&adp->cmds, temp);
+ if (sts != BC_STS_SUCCESS) {
+ BCMLOG_ERR("BCM70012 Suspend %d\n", sts);
+ return -ENODEV;
+ }
+
+ chd_dec_free_iodata(adp, temp, false);
+ chd_dec_disable_int(adp);
+ pci_save_state(pdev);
+
+ /* Disable IO/bus master/irq router */
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ return 0;
+}
+
+int chd_dec_pci_resume(struct pci_dev *pdev)
+{
+ struct crystalhd_adp *adp;
+ BC_STATUS sts = BC_STS_SUCCESS;
+ int rc;
+
+ adp = (struct crystalhd_adp *)pci_get_drvdata(pdev);
+ if (!adp) {
+ BCMLOG_ERR("could not get adp\n");
+ return -ENODEV;
+ }
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ /* device's irq possibly is changed, driver should take care */
+ if (pci_enable_device(pdev)) {
+ BCMLOG_ERR("Failed to enable PCI device\n");
+ return 1;
+ }
+
+ pci_set_master(pdev);
+
+ rc = chd_dec_enable_int(adp);
+ if (rc) {
+ BCMLOG_ERR("_enable_int err:%d \n", rc);
+ pci_disable_device(pdev);
+ return -ENODEV;
+ }
+
+ sts = crystalhd_resume(&adp->cmds);
+ if (sts != BC_STS_SUCCESS) {
+ BCMLOG_ERR("BCM70012 Resume %d\n", sts);
+ pci_disable_device(pdev);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+#endif
+
+static DEFINE_PCI_DEVICE_TABLE(chd_dec_pci_id_table) = {
+ { PCI_VDEVICE(BROADCOM, 0x1612), 8 },
+ { 0, },
+};
+MODULE_DEVICE_TABLE(pci, chd_dec_pci_id_table);
+
+static struct pci_driver bc_chd_70012_driver = {
+ .name = "Broadcom 70012 Decoder",
+ .probe = chd_dec_pci_probe,
+ .remove = __devexit_p(chd_dec_pci_remove),
+ .id_table = chd_dec_pci_id_table,
+#ifdef CONFIG_PM
+ .suspend = chd_dec_pci_suspend,
+ .resume = chd_dec_pci_resume
+#endif
+};
+
+void chd_set_log_level(struct crystalhd_adp *adp, char *arg)
+{
+ if ((!arg) || (strlen(arg) < 3))
+ g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA;
+ else if (!strncmp(arg, "sstep", 5))
+ g_linklog_level = BCMLOG_INFO | BCMLOG_DATA | BCMLOG_DBG |
+ BCMLOG_SSTEP | BCMLOG_ERROR;
+ else if (!strncmp(arg, "info", 4))
+ g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA | BCMLOG_INFO;
+ else if (!strncmp(arg, "debug", 5))
+ g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA | BCMLOG_INFO |
+ BCMLOG_DBG;
+ else if (!strncmp(arg, "pball", 5))
+ g_linklog_level = 0xFFFFFFFF & ~(BCMLOG_SPINLOCK);
+ else if (!strncmp(arg, "silent", 6))
+ g_linklog_level = 0;
+ else
+ g_linklog_level = 0;
+}
+
+struct crystalhd_adp *chd_get_adp(void)
+{
+ return g_adp_info;
+}
+
+static int __init chd_dec_module_init(void)
+{
+ int rc;
+
+ chd_set_log_level(NULL, "debug");
+ BCMLOG(BCMLOG_DATA, "Loading crystalhd %d.%d.%d \n",
+ crystalhd_kmod_major, crystalhd_kmod_minor, crystalhd_kmod_rev);
+
+ rc = pci_register_driver(&bc_chd_70012_driver);
+
+ if (rc < 0)
+ BCMLOG_ERR("Could not find any devices. err:%d \n", rc);
+
+ return rc;
+}
+module_init(chd_dec_module_init);
+
+static void __exit chd_dec_module_cleanup(void)
+{
+ BCMLOG(BCMLOG_DATA, "unloading crystalhd %d.%d.%d \n",
+ crystalhd_kmod_major, crystalhd_kmod_minor, crystalhd_kmod_rev);
+
+ pci_unregister_driver(&bc_chd_70012_driver);
+}
+module_exit(chd_dec_module_cleanup);
+
+MODULE_AUTHOR("Naren Sankar <nsankar@broadcom.com>");
+MODULE_AUTHOR("Prasad Bolisetty <prasadb@broadcom.com>");
+MODULE_DESCRIPTION(CRYSTAL_HD_NAME);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("bcm70012");
diff --git a/drivers/staging/crystalhd/crystalhd_lnx.h b/drivers/staging/crystalhd/crystalhd_lnx.h
new file mode 100644
index 00000000000..d338ae97a4c
--- /dev/null
+++ b/drivers/staging/crystalhd/crystalhd_lnx.h
@@ -0,0 +1,96 @@
+/***************************************************************************
+ * Copyright (c) 2005-2009, Broadcom Corporation.
+ *
+ * Name: crystalhd_lnx . c
+ *
+ * Description:
+ * BCM70012 Linux driver
+ *
+ * HISTORY:
+ *
+ **********************************************************************
+ * This file is part of the crystalhd device driver.
+ *
+ * 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, version 2 of the License.
+ *
+ * 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 driver. If not, see <http://www.gnu.org/licenses/>.
+ **********************************************************************/
+
+#ifndef _CRYSTALHD_LNX_H_
+#define _CRYSTALHD_LNX_H_
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/pagemap.h>
+#include <linux/vmalloc.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#include "crystalhd_cmds.h"
+
+#define CRYSTAL_HD_NAME "Broadcom Crystal HD Decoder (BCM70012) Driver"
+
+
+/* OS specific PCI information structure and adapter information. */
+struct crystalhd_adp {
+ /* Hardware borad/PCI specifics */
+ char name[32];
+ struct pci_dev *pdev;
+
+ unsigned long pci_mem_start;
+ uint32_t pci_mem_len;
+ void *addr;
+
+ unsigned long pci_i2o_start;
+ uint32_t pci_i2o_len;
+ void *i2o_addr;
+
+ unsigned int drv_data;
+ unsigned int dmabits; /* 32 | 64 */
+ unsigned int registered;
+ unsigned int present;
+ unsigned int msi;
+
+ spinlock_t lock;
+
+ /* API Related */
+ unsigned int chd_dec_major;
+ unsigned int cfg_users;
+
+ crystalhd_ioctl_data *idata_free_head; /* ioctl data pool */
+ crystalhd_elem_t *elem_pool_head; /* Queue element pool */
+
+ struct crystalhd_cmd cmds;
+
+ crystalhd_dio_req *ua_map_free_head;
+ struct pci_pool *fill_byte_pool;
+};
+
+
+struct crystalhd_adp *chd_get_adp(void);
+void chd_set_log_level(struct crystalhd_adp *adp, char *arg);
+
+#endif
+
diff --git a/drivers/staging/crystalhd/crystalhd_misc.c b/drivers/staging/crystalhd/crystalhd_misc.c
new file mode 100644
index 00000000000..587dcc47786
--- /dev/null
+++ b/drivers/staging/crystalhd/crystalhd_misc.c
@@ -0,0 +1,1030 @@
+/***************************************************************************
+ * Copyright (c) 2005-2009, Broadcom Corporation.
+ *
+ * Name: crystalhd_misc . c
+ *
+ * Description:
+ * BCM70012 Linux driver misc routines.
+ *
+ * HISTORY:
+ *
+ **********************************************************************
+ * This file is part of the crystalhd device driver.
+ *
+ * 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, version 2 of the License.
+ *
+ * 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 driver. If not, see <http://www.gnu.org/licenses/>.
+ **********************************************************************/
+
+#include "crystalhd_misc.h"
+#include "crystalhd_lnx.h"
+
+uint32_t g_linklog_level;
+
+static inline uint32_t crystalhd_dram_rd(struct crystalhd_adp *adp, uint32_t mem_off)
+{
+ crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (mem_off >> 19));
+ return bc_dec_reg_rd(adp, (0x00380000 | (mem_off & 0x0007FFFF)));
+}
+
+static inline void crystalhd_dram_wr(struct crystalhd_adp *adp, uint32_t mem_off, uint32_t val)
+{
+ crystalhd_reg_wr(adp, DCI_DRAM_BASE_ADDR, (mem_off >> 19));
+ bc_dec_reg_wr(adp, (0x00380000 | (mem_off & 0x0007FFFF)), val);
+}
+
+static inline BC_STATUS bc_chk_dram_range(struct crystalhd_adp *adp, uint32_t start_off, uint32_t cnt)
+{
+ return BC_STS_SUCCESS;
+}
+
+static crystalhd_dio_req *crystalhd_alloc_dio(struct crystalhd_adp *adp)
+{
+ unsigned long flags = 0;
+ crystalhd_dio_req *temp = NULL;
+
+ if (!adp) {
+ BCMLOG_ERR("Invalid Arg!!\n");
+ return temp;
+ }
+
+ spin_lock_irqsave(&adp->lock, flags);
+ temp = adp->ua_map_free_head;
+ if (temp)
+ adp->ua_map_free_head = adp->ua_map_free_head->next;
+ spin_unlock_irqrestore(&adp->lock, flags);
+
+ return temp;
+}
+
+static void crystalhd_free_dio(struct crystalhd_adp *adp, crystalhd_dio_req *dio)
+{
+ unsigned long flags = 0;
+
+ if (!adp || !dio)
+ return;
+ spin_lock_irqsave(&adp->lock, flags);
+ dio->sig = crystalhd_dio_inv;
+ dio->page_cnt = 0;
+ dio->fb_size = 0;
+ memset(&dio->uinfo, 0, sizeof(dio->uinfo));
+ dio->next = adp->ua_map_free_head;
+ adp->ua_map_free_head = dio;
+ spin_unlock_irqrestore(&adp->lock, flags);
+}
+
+static crystalhd_elem_t *crystalhd_alloc_elem(struct crystalhd_adp *adp)
+{
+ unsigned long flags = 0;
+ crystalhd_elem_t *temp = NULL;
+
+ if (!adp)
+ return temp;
+ spin_lock_irqsave(&adp->lock, flags);
+ temp = adp->elem_pool_head;
+ if (temp) {
+ adp->elem_pool_head = adp->elem_pool_head->flink;
+ memset(temp, 0, sizeof(*temp));
+ }
+ spin_unlock_irqrestore(&adp->lock, flags);
+
+ return temp;
+}
+static void crystalhd_free_elem(struct crystalhd_adp *adp, crystalhd_elem_t *elem)
+{
+ unsigned long flags = 0;
+
+ if (!adp || !elem)
+ return;
+ spin_lock_irqsave(&adp->lock, flags);
+ elem->flink = adp->elem_pool_head;
+ adp->elem_pool_head = elem;
+ spin_unlock_irqrestore(&adp->lock, flags);
+}
+
+static inline void crystalhd_set_sg(struct scatterlist *sg, struct page *page,
+ unsigned int len, unsigned int offset)
+{
+ sg_set_page(sg, page, len, offset);
+#ifdef CONFIG_X86_64
+ sg->dma_length = len;
+#endif
+}
+
+static inline void crystalhd_init_sg(struct scatterlist *sg, unsigned int entries)
+{
+ /* http://lkml.org/lkml/2007/11/27/68 */
+ sg_init_table(sg, entries);
+}
+
+/*========================== Extern ========================================*/
+/**
+ * bc_dec_reg_rd - Read 7412's device register.
+ * @adp: Adapter instance
+ * @reg_off: Register offset.
+ *
+ * Return:
+ * 32bit value read
+ *
+ * 7412's device register read routine. This interface use
+ * 7412's device access range mapped from BAR-2 (4M) of PCIe
+ * configuration space.
+ */
+uint32_t bc_dec_reg_rd(struct crystalhd_adp *adp, uint32_t reg_off)
+{
+ if (!adp || (reg_off > adp->pci_mem_len)) {
+ BCMLOG_ERR("dec_rd_reg_off outof range: 0x%08x\n", reg_off);
+ return 0;
+ }
+
+ return readl(adp->addr + reg_off);
+}
+
+/**
+ * bc_dec_reg_wr - Write 7412's device register
+ * @adp: Adapter instance
+ * @reg_off: Register offset.
+ * @val: Dword value to be written.
+ *
+ * Return:
+ * none.
+ *
+ * 7412's device register write routine. This interface use
+ * 7412's device access range mapped from BAR-2 (4M) of PCIe
+ * configuration space.
+ */
+void bc_dec_reg_wr(struct crystalhd_adp *adp, uint32_t reg_off, uint32_t val)
+{
+ if (!adp || (reg_off > adp->pci_mem_len)) {
+ BCMLOG_ERR("dec_wr_reg_off outof range: 0x%08x\n", reg_off);
+ return;
+ }
+ writel(val, adp->addr + reg_off);
+ udelay(8);
+}
+
+/**
+ * crystalhd_reg_rd - Read Link's device register.
+ * @adp: Adapter instance
+ * @reg_off: Register offset.
+ *
+ * Return:
+ * 32bit value read
+ *
+ * Link device register read routine. This interface use
+ * Link's device access range mapped from BAR-1 (64K) of PCIe
+ * configuration space.
+ *
+ */
+uint32_t crystalhd_reg_rd(struct crystalhd_adp *adp, uint32_t reg_off)
+{
+ if (!adp || (reg_off > adp->pci_i2o_len)) {
+ BCMLOG_ERR("link_rd_reg_off outof range: 0x%08x\n", reg_off);
+ return 0;
+ }
+ return readl(adp->i2o_addr + reg_off);
+}
+
+/**
+ * crystalhd_reg_wr - Write Link's device register
+ * @adp: Adapter instance
+ * @reg_off: Register offset.
+ * @val: Dword value to be written.
+ *
+ * Return:
+ * none.
+ *
+ * Link device register write routine. This interface use
+ * Link's device access range mapped from BAR-1 (64K) of PCIe
+ * configuration space.
+ *
+ */
+void crystalhd_reg_wr(struct crystalhd_adp *adp, uint32_t reg_off, uint32_t val)
+{
+ if (!adp || (reg_off > adp->pci_i2o_len)) {
+ BCMLOG_ERR("link_wr_reg_off outof range: 0x%08x\n", reg_off);
+ return;
+ }
+ writel(val, adp->i2o_addr + reg_off);
+}
+
+/**
+ * crystalhd_mem_rd - Read data from 7412's DRAM area.
+ * @adp: Adapter instance
+ * @start_off: Start offset.
+ * @dw_cnt: Count in dwords.
+ * @rd_buff: Buffer to copy the data from dram.
+ *
+ * Return:
+ * Status.
+ *
+ * 7412's Dram read routine.
+ */
+BC_STATUS crystalhd_mem_rd(struct crystalhd_adp *adp, uint32_t start_off,
+ uint32_t dw_cnt, uint32_t *rd_buff)
+{
+ uint32_t ix = 0;
+
+ if (!adp || !rd_buff ||
+ (bc_chk_dram_range(adp, start_off, dw_cnt) != BC_STS_SUCCESS)) {
+ BCMLOG_ERR("Invalid arg \n");
+ return BC_STS_INV_ARG;
+ }
+ for (ix = 0; ix < dw_cnt; ix++)
+ rd_buff[ix] = crystalhd_dram_rd(adp, (start_off + (ix * 4)));
+
+ return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_mem_wr - Write data to 7412's DRAM area.
+ * @adp: Adapter instance
+ * @start_off: Start offset.
+ * @dw_cnt: Count in dwords.
+ * @wr_buff: Data Buffer to be written.
+ *
+ * Return:
+ * Status.
+ *
+ * 7412's Dram write routine.
+ */
+BC_STATUS crystalhd_mem_wr(struct crystalhd_adp *adp, uint32_t start_off,
+ uint32_t dw_cnt, uint32_t *wr_buff)
+{
+ uint32_t ix = 0;
+
+ if (!adp || !wr_buff ||
+ (bc_chk_dram_range(adp, start_off, dw_cnt) != BC_STS_SUCCESS)) {
+ BCMLOG_ERR("Invalid arg \n");
+ return BC_STS_INV_ARG;
+ }
+
+ for (ix = 0; ix < dw_cnt; ix++)
+ crystalhd_dram_wr(adp, (start_off + (ix * 4)), wr_buff[ix]);
+
+ return BC_STS_SUCCESS;
+}
+/**
+ * crystalhd_pci_cfg_rd - PCIe config read
+ * @adp: Adapter instance
+ * @off: PCI config space offset.
+ * @len: Size -- Byte, Word & dword.
+ * @val: Value read
+ *
+ * Return:
+ * Status.
+ *
+ * Get value from Link's PCIe config space.
+ */
+BC_STATUS crystalhd_pci_cfg_rd(struct crystalhd_adp *adp, uint32_t off,
+ uint32_t len, uint32_t *val)
+{
+ BC_STATUS sts = BC_STS_SUCCESS;
+ int rc = 0;
+
+ if (!adp || !val) {
+ BCMLOG_ERR("Invalid arg \n");
+ return BC_STS_INV_ARG;
+ }
+
+ switch (len) {
+ case 1:
+ rc = pci_read_config_byte(adp->pdev, off, (u8 *)val);
+ break;
+ case 2:
+ rc = pci_read_config_word(adp->pdev, off, (u16 *)val);
+ break;
+ case 4:
+ rc = pci_read_config_dword(adp->pdev, off, (u32 *)val);
+ break;
+ default:
+ rc = -EINVAL;
+ sts = BC_STS_INV_ARG;
+ BCMLOG_ERR("Invalid len:%d\n", len);
+ };
+
+ if (rc && (sts == BC_STS_SUCCESS))
+ sts = BC_STS_ERROR;
+
+ return sts;
+}
+
+/**
+ * crystalhd_pci_cfg_wr - PCIe config write
+ * @adp: Adapter instance
+ * @off: PCI config space offset.
+ * @len: Size -- Byte, Word & dword.
+ * @val: Value to be written
+ *
+ * Return:
+ * Status.
+ *
+ * Set value to Link's PCIe config space.
+ */
+BC_STATUS crystalhd_pci_cfg_wr(struct crystalhd_adp *adp, uint32_t off,
+ uint32_t len, uint32_t val)
+{
+ BC_STATUS sts = BC_STS_SUCCESS;
+ int rc = 0;
+
+ if (!adp || !val) {
+ BCMLOG_ERR("Invalid arg \n");
+ return BC_STS_INV_ARG;
+ }
+
+ switch (len) {
+ case 1:
+ rc = pci_write_config_byte(adp->pdev, off, (u8)val);
+ break;
+ case 2:
+ rc = pci_write_config_word(adp->pdev, off, (u16)val);
+ break;
+ case 4:
+ rc = pci_write_config_dword(adp->pdev, off, val);
+ break;
+ default:
+ rc = -EINVAL;
+ sts = BC_STS_INV_ARG;
+ BCMLOG_ERR("Invalid len:%d\n", len);
+ };
+
+ if (rc && (sts == BC_STS_SUCCESS))
+ sts = BC_STS_ERROR;
+
+ return sts;
+}
+
+/**
+ * bc_kern_dma_alloc - Allocate memory for Dma rings
+ * @adp: Adapter instance
+ * @sz: Size of the memory to allocate.
+ * @phy_addr: Physical address of the memory allocated.
+ * Typedef to system's dma_addr_t (u64)
+ *
+ * Return:
+ * Pointer to allocated memory..
+ *
+ * Wrapper to Linux kernel interface.
+ *
+ */
+void *bc_kern_dma_alloc(struct crystalhd_adp *adp, uint32_t sz,
+ dma_addr_t *phy_addr)
+{
+ void *temp = NULL;
+
+ if (!adp || !sz || !phy_addr) {
+ BCMLOG_ERR("Invalide Arg..\n");
+ return temp;
+ }
+
+ temp = pci_alloc_consistent(adp->pdev, sz, phy_addr);
+ if (temp)
+ memset(temp, 0, sz);
+
+ return temp;
+}
+
+/**
+ * bc_kern_dma_free - Release Dma ring memory.
+ * @adp: Adapter instance
+ * @sz: Size of the memory to allocate.
+ * @ka: Kernel virtual address returned during _dio_alloc()
+ * @phy_addr: Physical address of the memory allocated.
+ * Typedef to system's dma_addr_t (u64)
+ *
+ * Return:
+ * none.
+ */
+void bc_kern_dma_free(struct crystalhd_adp *adp, uint32_t sz, void *ka,
+ dma_addr_t phy_addr)
+{
+ if (!adp || !ka || !sz || !phy_addr) {
+ BCMLOG_ERR("Invalide Arg..\n");
+ return;
+ }
+
+ pci_free_consistent(adp->pdev, sz, ka, phy_addr);
+}
+
+/**
+ * crystalhd_create_dioq - Create Generic DIO queue
+ * @adp: Adapter instance
+ * @dioq_hnd: Handle to the dio queue created
+ * @cb : Optional - Call back To free the element.
+ * @cbctx: Context to pass to callback.
+ *
+ * Return:
+ * status
+ *
+ * Initialize Generic DIO queue to hold any data. Callback
+ * will be used to free elements while deleting the queue.
+ */
+BC_STATUS crystalhd_create_dioq(struct crystalhd_adp *adp,
+ crystalhd_dioq_t **dioq_hnd,
+ crystalhd_data_free_cb cb, void *cbctx)
+{
+ crystalhd_dioq_t *dioq = NULL;
+
+ if (!adp || !dioq_hnd) {
+ BCMLOG_ERR("Invalid arg!!\n");
+ return BC_STS_INV_ARG;
+ }
+
+ dioq = kzalloc(sizeof(*dioq), GFP_KERNEL);
+ if (!dioq)
+ return BC_STS_INSUFF_RES;
+
+ spin_lock_init(&dioq->lock);
+ dioq->sig = BC_LINK_DIOQ_SIG;
+ dioq->head = (crystalhd_elem_t *)&dioq->head;
+ dioq->tail = (crystalhd_elem_t *)&dioq->head;
+ crystalhd_create_event(&dioq->event);
+ dioq->adp = adp;
+ dioq->data_rel_cb = cb;
+ dioq->cb_context = cbctx;
+ *dioq_hnd = dioq;
+
+ return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_delete_dioq - Delete Generic DIO queue
+ * @adp: Adapter instance
+ * @dioq: DIOQ instance..
+ *
+ * Return:
+ * None.
+ *
+ * Release Generic DIO queue. This function will remove
+ * all the entries from the Queue and will release data
+ * by calling the call back provided during creation.
+ *
+ */
+void crystalhd_delete_dioq(struct crystalhd_adp *adp, crystalhd_dioq_t *dioq)
+{
+ void *temp;
+
+ if (!dioq || (dioq->sig != BC_LINK_DIOQ_SIG))
+ return;
+
+ do {
+ temp = crystalhd_dioq_fetch(dioq);
+ if (temp && dioq->data_rel_cb)
+ dioq->data_rel_cb(dioq->cb_context, temp);
+ } while (temp);
+ dioq->sig = 0;
+ kfree(dioq);
+}
+
+/**
+ * crystalhd_dioq_add - Add new DIO request element.
+ * @ioq: DIO queue instance
+ * @t: DIO request to be added.
+ * @wake: True - Wake up suspended process.
+ * @tag: Special tag to assign - For search and get.
+ *
+ * Return:
+ * Status.
+ *
+ * Insert new element to Q tail.
+ */
+BC_STATUS crystalhd_dioq_add(crystalhd_dioq_t *ioq, void *data,
+ bool wake, uint32_t tag)
+{
+ unsigned long flags = 0;
+ crystalhd_elem_t *tmp;
+
+ if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG) || !data) {
+ BCMLOG_ERR("Invalid arg!!\n");
+ return BC_STS_INV_ARG;
+ }
+
+ tmp = crystalhd_alloc_elem(ioq->adp);
+ if (!tmp) {
+ BCMLOG_ERR("No free elements.\n");
+ return BC_STS_INSUFF_RES;
+ }
+
+ tmp->data = data;
+ tmp->tag = tag;
+ spin_lock_irqsave(&ioq->lock, flags);
+ tmp->flink = (crystalhd_elem_t *)&ioq->head;
+ tmp->blink = ioq->tail;
+ tmp->flink->blink = tmp;
+ tmp->blink->flink = tmp;
+ ioq->count++;
+ spin_unlock_irqrestore(&ioq->lock, flags);
+
+ if (wake)
+ crystalhd_set_event(&ioq->event);
+
+ return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_dioq_fetch - Fetch element from head.
+ * @ioq: DIO queue instance
+ *
+ * Return:
+ * data element from the head..
+ *
+ * Remove an element from Queue.
+ */
+void *crystalhd_dioq_fetch(crystalhd_dioq_t *ioq)
+{
+ unsigned long flags = 0;
+ crystalhd_elem_t *tmp;
+ crystalhd_elem_t *ret = NULL;
+ void *data = NULL;
+
+ if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG)) {
+ BCMLOG_ERR("Invalid arg!!\n");
+ return data;
+ }
+
+ spin_lock_irqsave(&ioq->lock, flags);
+ tmp = ioq->head;
+ if (tmp != (crystalhd_elem_t *)&ioq->head) {
+ ret = tmp;
+ tmp->flink->blink = tmp->blink;
+ tmp->blink->flink = tmp->flink;
+ ioq->count--;
+ }
+ spin_unlock_irqrestore(&ioq->lock, flags);
+ if (ret) {
+ data = ret->data;
+ crystalhd_free_elem(ioq->adp, ret);
+ }
+
+ return data;
+}
+/**
+ * crystalhd_dioq_find_and_fetch - Search the tag and Fetch element
+ * @ioq: DIO queue instance
+ * @tag: Tag to search for.
+ *
+ * Return:
+ * element from the head..
+ *
+ * Search TAG and remove the element.
+ */
+void *crystalhd_dioq_find_and_fetch(crystalhd_dioq_t *ioq, uint32_t tag)
+{
+ unsigned long flags = 0;
+ crystalhd_elem_t *tmp;
+ crystalhd_elem_t *ret = NULL;
+ void *data = NULL;
+
+ if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG)) {
+ BCMLOG_ERR("Invalid arg!!\n");
+ return data;
+ }
+
+ spin_lock_irqsave(&ioq->lock, flags);
+ tmp = ioq->head;
+ while (tmp != (crystalhd_elem_t *)&ioq->head) {
+ if (tmp->tag == tag) {
+ ret = tmp;
+ tmp->flink->blink = tmp->blink;
+ tmp->blink->flink = tmp->flink;
+ ioq->count--;
+ break;
+ }
+ tmp = tmp->flink;
+ }
+ spin_unlock_irqrestore(&ioq->lock, flags);
+
+ if (ret) {
+ data = ret->data;
+ crystalhd_free_elem(ioq->adp, ret);
+ }
+
+ return data;
+}
+
+/**
+ * crystalhd_dioq_fetch_wait - Fetch element from Head.
+ * @ioq: DIO queue instance
+ * @to_secs: Wait timeout in seconds..
+ *
+ * Return:
+ * element from the head..
+ *
+ * Return element from head if Q is not empty. Wait for new element
+ * if Q is empty for Timeout seconds.
+ */
+void *crystalhd_dioq_fetch_wait(crystalhd_dioq_t *ioq, uint32_t to_secs,
+ uint32_t *sig_pend)
+{
+ unsigned long flags = 0;
+ int rc = 0, count;
+ void *tmp = NULL;
+
+ if (!ioq || (ioq->sig != BC_LINK_DIOQ_SIG) || !to_secs || !sig_pend) {
+ BCMLOG_ERR("Invalid arg!!\n");
+ return tmp;
+ }
+
+ count = to_secs;
+ spin_lock_irqsave(&ioq->lock, flags);
+ while ((ioq->count == 0) && count) {
+ spin_unlock_irqrestore(&ioq->lock, flags);
+
+ crystalhd_wait_on_event(&ioq->event, (ioq->count > 0), 1000, rc, 0);
+ if (rc == 0) {
+ goto out;
+ } else if (rc == -EINTR) {
+ BCMLOG(BCMLOG_INFO, "Cancelling fetch wait\n");
+ *sig_pend = 1;
+ return tmp;
+ }
+ spin_lock_irqsave(&ioq->lock, flags);
+ count--;
+ }
+ spin_unlock_irqrestore(&ioq->lock, flags);
+
+out:
+ return crystalhd_dioq_fetch(ioq);
+}
+
+/**
+ * crystalhd_map_dio - Map user address for DMA
+ * @adp: Adapter instance
+ * @ubuff: User buffer to map.
+ * @ubuff_sz: User buffer size.
+ * @uv_offset: UV buffer offset.
+ * @en_422mode: TRUE:422 FALSE:420 Capture mode.
+ * @dir_tx: TRUE for Tx (To device from host)
+ * @dio_hnd: Handle to mapped DIO request.
+ *
+ * Return:
+ * Status.
+ *
+ * This routine maps user address and lock pages for DMA.
+ *
+ */
+BC_STATUS crystalhd_map_dio(struct crystalhd_adp *adp, void *ubuff,
+ uint32_t ubuff_sz, uint32_t uv_offset,
+ bool en_422mode, bool dir_tx,
+ crystalhd_dio_req **dio_hnd)
+{
+ crystalhd_dio_req *dio;
+ /* FIXME: jarod: should some of these unsigned longs be uint32_t or uintptr_t? */
+ unsigned long start = 0, end = 0, uaddr = 0, count = 0;
+ unsigned long spsz = 0, uv_start = 0;
+ int i = 0, rw = 0, res = 0, nr_pages = 0, skip_fb_sg = 0;
+
+ if (!adp || !ubuff || !ubuff_sz || !dio_hnd) {
+ BCMLOG_ERR("Invalid arg \n");
+ return BC_STS_INV_ARG;
+ }
+ /* Compute pages */
+ uaddr = (unsigned long)ubuff;
+ count = (unsigned long)ubuff_sz;
+ end = (uaddr + count + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ start = uaddr >> PAGE_SHIFT;
+ nr_pages = end - start;
+
+ if (!count || ((uaddr + count) < uaddr)) {
+ BCMLOG_ERR("User addr overflow!!\n");
+ return BC_STS_INV_ARG;
+ }
+
+ dio = crystalhd_alloc_dio(adp);
+ if (!dio) {
+ BCMLOG_ERR("dio pool empty..\n");
+ return BC_STS_INSUFF_RES;
+ }
+
+ if (dir_tx) {
+ rw = WRITE;
+ dio->direction = DMA_TO_DEVICE;
+ } else {
+ rw = READ;
+ dio->direction = DMA_FROM_DEVICE;
+ }
+
+ if (nr_pages > dio->max_pages) {
+ BCMLOG_ERR("max_pages(%d) exceeded(%d)!!\n",
+ dio->max_pages, nr_pages);
+ crystalhd_unmap_dio(adp, dio);
+ return BC_STS_INSUFF_RES;
+ }
+
+ if (uv_offset) {
+ uv_start = (uaddr + (unsigned long)uv_offset) >> PAGE_SHIFT;
+ dio->uinfo.uv_sg_ix = uv_start - start;
+ dio->uinfo.uv_sg_off = ((uaddr + (unsigned long)uv_offset) & ~PAGE_MASK);
+ }
+
+ dio->fb_size = ubuff_sz & 0x03;
+ if (dio->fb_size) {
+ res = copy_from_user(dio->fb_va,
+ (void *)(uaddr + count - dio->fb_size),
+ dio->fb_size);
+ if (res) {
+ BCMLOG_ERR("failed %d to copy %u fill bytes from %p\n",
+ res, dio->fb_size,
+ (void *)(uaddr + count-dio->fb_size));
+ crystalhd_unmap_dio(adp, dio);
+ return BC_STS_INSUFF_RES;
+ }
+ }
+
+ down_read(&current->mm->mmap_sem);
+ res = get_user_pages(current, current->mm, uaddr, nr_pages, rw == READ,
+ 0, dio->pages, NULL);
+ up_read(&current->mm->mmap_sem);
+
+ /* Save for release..*/
+ dio->sig = crystalhd_dio_locked;
+ if (res < nr_pages) {
+ BCMLOG_ERR("get pages failed: %d-%d\n", nr_pages, res);
+ dio->page_cnt = res;
+ crystalhd_unmap_dio(adp, dio);
+ return BC_STS_ERROR;
+ }
+
+ dio->page_cnt = nr_pages;
+ /* Get scatter/gather */
+ crystalhd_init_sg(dio->sg, dio->page_cnt);
+ crystalhd_set_sg(&dio->sg[0], dio->pages[0], 0, uaddr & ~PAGE_MASK);
+ if (nr_pages > 1) {
+ dio->sg[0].length = PAGE_SIZE - dio->sg[0].offset;
+
+#ifdef CONFIG_X86_64
+ dio->sg[0].dma_length = dio->sg[0].length;
+#endif
+ count -= dio->sg[0].length;
+ for (i = 1; i < nr_pages; i++) {
+ if (count < 4) {
+ spsz = count;
+ skip_fb_sg = 1;
+ } else {
+ spsz = (count < PAGE_SIZE) ?
+ (count & ~0x03) : PAGE_SIZE;
+ }
+ crystalhd_set_sg(&dio->sg[i], dio->pages[i], spsz, 0);
+ count -= spsz;
+ }
+ } else {
+ if (count < 4) {
+ dio->sg[0].length = count;
+ skip_fb_sg = 1;
+ } else {
+ dio->sg[0].length = count - dio->fb_size;
+ }
+#ifdef CONFIG_X86_64
+ dio->sg[0].dma_length = dio->sg[0].length;
+#endif
+ }
+ dio->sg_cnt = pci_map_sg(adp->pdev, dio->sg,
+ dio->page_cnt, dio->direction);
+ if (dio->sg_cnt <= 0) {
+ BCMLOG_ERR("sg map %d-%d \n", dio->sg_cnt, dio->page_cnt);
+ crystalhd_unmap_dio(adp, dio);
+ return BC_STS_ERROR;
+ }
+ if (dio->sg_cnt && skip_fb_sg)
+ dio->sg_cnt -= 1;
+ dio->sig = crystalhd_dio_sg_mapped;
+ /* Fill in User info.. */
+ dio->uinfo.xfr_len = ubuff_sz;
+ dio->uinfo.xfr_buff = ubuff;
+ dio->uinfo.uv_offset = uv_offset;
+ dio->uinfo.b422mode = en_422mode;
+ dio->uinfo.dir_tx = dir_tx;
+
+ *dio_hnd = dio;
+
+ return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_unmap_sgl - Release mapped resources
+ * @adp: Adapter instance
+ * @dio: DIO request instance
+ *
+ * Return:
+ * Status.
+ *
+ * This routine is to unmap the user buffer pages.
+ */
+BC_STATUS crystalhd_unmap_dio(struct crystalhd_adp *adp, crystalhd_dio_req *dio)
+{
+ struct page *page = NULL;
+ int j = 0;
+
+ if (!adp || !dio) {
+ BCMLOG_ERR("Invalid arg \n");
+ return BC_STS_INV_ARG;
+ }
+
+ if ((dio->page_cnt > 0) && (dio->sig != crystalhd_dio_inv)) {
+ for (j = 0; j < dio->page_cnt; j++) {
+ page = dio->pages[j];
+ if (page) {
+ if (!PageReserved(page) &&
+ (dio->direction == DMA_FROM_DEVICE))
+ SetPageDirty(page);
+ page_cache_release(page);
+ }
+ }
+ }
+ if (dio->sig == crystalhd_dio_sg_mapped)
+ pci_unmap_sg(adp->pdev, dio->sg, dio->page_cnt, dio->direction);
+
+ crystalhd_free_dio(adp, dio);
+
+ return BC_STS_SUCCESS;
+}
+
+/**
+ * crystalhd_create_dio_pool - Allocate mem pool for DIO management.
+ * @adp: Adapter instance
+ * @max_pages: Max pages for size calculation.
+ *
+ * Return:
+ * system error.
+ *
+ * This routine creates a memory pool to hold dio context for
+ * for HW Direct IO operation.
+ */
+int crystalhd_create_dio_pool(struct crystalhd_adp *adp, uint32_t max_pages)
+{
+ uint32_t asz = 0, i = 0;
+ uint8_t *temp;
+ crystalhd_dio_req *dio;
+
+ if (!adp || !max_pages) {
+ BCMLOG_ERR("Invalid Arg!!\n");
+ return -EINVAL;
+ }
+
+ /* Get dma memory for fill byte handling..*/
+ adp->fill_byte_pool = pci_pool_create("crystalhd_fbyte",
+ adp->pdev, 8, 8, 0);
+ if (!adp->fill_byte_pool) {
+ BCMLOG_ERR("failed to create fill byte pool\n");
+ return -ENOMEM;
+ }
+
+ /* Get the max size from user based on 420/422 modes */
+ asz = (sizeof(*dio->pages) * max_pages) +
+ (sizeof(*dio->sg) * max_pages) + sizeof(*dio);
+
+ BCMLOG(BCMLOG_DBG, "Initializing Dio pool %d %d %x %p\n",
+ BC_LINK_SG_POOL_SZ, max_pages, asz, adp->fill_byte_pool);
+
+ for (i = 0; i < BC_LINK_SG_POOL_SZ; i++) {
+ temp = (uint8_t *)kzalloc(asz, GFP_KERNEL);
+ if ((temp) == NULL) {
+ BCMLOG_ERR("Failed to alloc %d mem\n", asz);
+ return -ENOMEM;
+ }
+
+ dio = (crystalhd_dio_req *)temp;
+ temp += sizeof(*dio);
+ dio->pages = (struct page **)temp;
+ temp += (sizeof(*dio->pages) * max_pages);
+ dio->sg = (struct scatterlist *)temp;
+ dio->max_pages = max_pages;
+ dio->fb_va = pci_pool_alloc(adp->fill_byte_pool, GFP_KERNEL,
+ &dio->fb_pa);
+ if (!dio->fb_va) {
+ BCMLOG_ERR("fill byte alloc failed.\n");
+ return -ENOMEM;
+ }
+
+ crystalhd_free_dio(adp, dio);
+ }
+
+ return 0;
+}
+
+/**
+ * crystalhd_destroy_dio_pool - Release DIO mem pool.
+ * @adp: Adapter instance
+ *
+ * Return:
+ * none.
+ *
+ * This routine releases dio memory pool during close.
+ */
+void crystalhd_destroy_dio_pool(struct crystalhd_adp *adp)
+{
+ crystalhd_dio_req *dio;
+ int count = 0;
+
+ if (!adp) {
+ BCMLOG_ERR("Invalid Arg!!\n");
+ return;
+ }
+
+ do {
+ dio = crystalhd_alloc_dio(adp);
+ if (dio) {
+ if (dio->fb_va)
+ pci_pool_free(adp->fill_byte_pool,
+ dio->fb_va, dio->fb_pa);
+ count++;
+ kfree(dio);
+ }
+ } while (dio);
+
+ if (adp->fill_byte_pool) {
+ pci_pool_destroy(adp->fill_byte_pool);
+ adp->fill_byte_pool = NULL;
+ }
+
+ BCMLOG(BCMLOG_DBG, "Released dio pool %d \n", count);
+}
+
+/**
+ * crystalhd_create_elem_pool - List element pool creation.
+ * @adp: Adapter instance
+ * @pool_size: Number of elements in the pool.
+ *
+ * Return:
+ * 0 - success, <0 error
+ *
+ * Create general purpose list element pool to hold pending,
+ * and active requests.
+ */
+int __devinit crystalhd_create_elem_pool(struct crystalhd_adp *adp,
+ uint32_t pool_size)
+{
+ uint32_t i;
+ crystalhd_elem_t *temp;
+
+ if (!adp || !pool_size)
+ return -EINVAL;
+
+ for (i = 0; i < pool_size; i++) {
+ temp = kzalloc(sizeof(*temp), GFP_KERNEL);
+ if (!temp) {
+ BCMLOG_ERR("kalloc failed \n");
+ return -ENOMEM;
+ }
+ crystalhd_free_elem(adp, temp);
+ }
+ BCMLOG(BCMLOG_DBG, "allocated %d elem\n", pool_size);
+ return 0;
+}
+
+/**
+ * crystalhd_delete_elem_pool - List element pool deletion.
+ * @adp: Adapter instance
+ *
+ * Return:
+ * none
+ *
+ * Delete general purpose list element pool.
+ */
+void crystalhd_delete_elem_pool(struct crystalhd_adp *adp)
+{
+ crystalhd_elem_t *temp;
+ int dbg_cnt = 0;
+
+ if (!adp)
+ return;
+
+ do {
+ temp = crystalhd_alloc_elem(adp);
+ if (temp) {
+ kfree(temp);
+ dbg_cnt++;
+ }
+ } while (temp);
+
+ BCMLOG(BCMLOG_DBG, "released %d elem\n", dbg_cnt);
+}
+
+/*================ Debug support routines.. ================================*/
+void crystalhd_show_buffer(uint32_t off, uint8_t *buff, uint32_t dwcount)
+{
+ uint32_t i, k = 1;
+
+ for (i = 0; i < dwcount; i++) {
+ if (k == 1)
+ BCMLOG(BCMLOG_DATA, "0x%08X : ", off);
+
+ BCMLOG(BCMLOG_DATA, " 0x%08X ", *((uint32_t *)buff));
+
+ buff += sizeof(uint32_t);
+ off += sizeof(uint32_t);
+ k++;
+ if ((i == dwcount - 1) || (k > 4)) {
+ BCMLOG(BCMLOG_DATA, "\n");
+ k = 1;
+ }
+ }
+}
diff --git a/drivers/staging/crystalhd/crystalhd_misc.h b/drivers/staging/crystalhd/crystalhd_misc.h
new file mode 100644
index 00000000000..a2aa6ad7fc8
--- /dev/null
+++ b/drivers/staging/crystalhd/crystalhd_misc.h
@@ -0,0 +1,229 @@
+/***************************************************************************
+ * Copyright (c) 2005-2009, Broadcom Corporation.
+ *
+ * Name: crystalhd_misc . h
+ *
+ * Description:
+ * BCM70012 Linux driver general purpose routines.
+ * Includes reg/mem read and write routines.
+ *
+ * HISTORY:
+ *
+ **********************************************************************
+ * This file is part of the crystalhd device driver.
+ *
+ * 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, version 2 of the License.
+ *
+ * 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 driver. If not, see <http://www.gnu.org/licenses/>.
+ **********************************************************************/
+
+#ifndef _CRYSTALHD_MISC_H_
+#define _CRYSTALHD_MISC_H_
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/ioctl.h>
+#include <linux/dma-mapping.h>
+#include <linux/version.h>
+#include <linux/sched.h>
+#include <asm/system.h>
+#include "bc_dts_glob_lnx.h"
+
+/* Global log level variable defined in crystal_misc.c file */
+extern uint32_t g_linklog_level;
+
+/* Global element pool for all Queue management.
+ * TX: Active = BC_TX_LIST_CNT, Free = BC_TX_LIST_CNT.
+ * RX: Free = BC_RX_LIST_CNT, Active = 2
+ * FW-CMD: 4
+ */
+#define BC_LINK_ELEM_POOL_SZ ((BC_TX_LIST_CNT * 2) + BC_RX_LIST_CNT + 2 + 4)
+
+/* Driver's IODATA pool count */
+#define CHD_IODATA_POOL_SZ (BC_IOCTL_DATA_POOL_SIZE * BC_LINK_MAX_OPENS)
+
+/* Scatter Gather memory pool size for Tx and Rx */
+#define BC_LINK_SG_POOL_SZ (BC_TX_LIST_CNT + BC_RX_LIST_CNT)
+
+enum _crystalhd_dio_sig {
+ crystalhd_dio_inv = 0,
+ crystalhd_dio_locked,
+ crystalhd_dio_sg_mapped,
+};
+
+struct crystalhd_dio_user_info {
+ void *xfr_buff;
+ uint32_t xfr_len;
+ uint32_t uv_offset;
+ bool dir_tx;
+
+ uint32_t uv_sg_ix;
+ uint32_t uv_sg_off;
+ int comp_sts;
+ int ev_sts;
+ uint32_t y_done_sz;
+ uint32_t uv_done_sz;
+ uint32_t comp_flags;
+ bool b422mode;
+};
+
+typedef struct _crystalhd_dio_req {
+ uint32_t sig;
+ uint32_t max_pages;
+ struct page **pages;
+ struct scatterlist *sg;
+ int sg_cnt;
+ int page_cnt;
+ int direction;
+ struct crystalhd_dio_user_info uinfo;
+ void *fb_va;
+ uint32_t fb_size;
+ dma_addr_t fb_pa;
+ struct _crystalhd_dio_req *next;
+} crystalhd_dio_req;
+
+#define BC_LINK_DIOQ_SIG (0x09223280)
+
+typedef struct _crystalhd_elem_s {
+ struct _crystalhd_elem_s *flink;
+ struct _crystalhd_elem_s *blink;
+ void *data;
+ uint32_t tag;
+} crystalhd_elem_t;
+
+typedef void (*crystalhd_data_free_cb)(void *context, void *data);
+
+typedef struct _crystalhd_dioq_s {
+ uint32_t sig;
+ struct crystalhd_adp *adp;
+ crystalhd_elem_t *head;
+ crystalhd_elem_t *tail;
+ uint32_t count;
+ spinlock_t lock;
+ wait_queue_head_t event;
+ crystalhd_data_free_cb data_rel_cb;
+ void *cb_context;
+} crystalhd_dioq_t;
+
+typedef void (*hw_comp_callback)(crystalhd_dio_req *,
+ wait_queue_head_t *event, BC_STATUS sts);
+
+/*========= Decoder (7412) register access routines.================= */
+uint32_t bc_dec_reg_rd(struct crystalhd_adp *, uint32_t);
+void bc_dec_reg_wr(struct crystalhd_adp *, uint32_t, uint32_t);
+
+/*========= Link (70012) register access routines.. =================*/
+uint32_t crystalhd_reg_rd(struct crystalhd_adp *, uint32_t);
+void crystalhd_reg_wr(struct crystalhd_adp *, uint32_t, uint32_t);
+
+/*========= Decoder (7412) memory access routines..=================*/
+BC_STATUS crystalhd_mem_rd(struct crystalhd_adp *, uint32_t, uint32_t, uint32_t *);
+BC_STATUS crystalhd_mem_wr(struct crystalhd_adp *, uint32_t, uint32_t, uint32_t *);
+
+/*==========Link (70012) PCIe Config access routines.================*/
+BC_STATUS crystalhd_pci_cfg_rd(struct crystalhd_adp *, uint32_t, uint32_t, uint32_t *);
+BC_STATUS crystalhd_pci_cfg_wr(struct crystalhd_adp *, uint32_t, uint32_t, uint32_t);
+
+/*========= Linux Kernel Interface routines. ======================= */
+void *bc_kern_dma_alloc(struct crystalhd_adp *, uint32_t, dma_addr_t *);
+void bc_kern_dma_free(struct crystalhd_adp *, uint32_t,
+ void *, dma_addr_t);
+#define crystalhd_create_event(_ev) init_waitqueue_head(_ev)
+#define crystalhd_set_event(_ev) wake_up_interruptible(_ev)
+#define crystalhd_wait_on_event(ev, condition, timeout, ret, nosig) \
+do { \
+ DECLARE_WAITQUEUE(entry, current); \
+ unsigned long end = jiffies + ((timeout * HZ) / 1000); \
+ ret = 0; \
+ add_wait_queue(ev, &entry); \
+ for (;;) { \
+ __set_current_state(TASK_INTERRUPTIBLE); \
+ if (condition) { \
+ break; \
+ } \
+ if (time_after_eq(jiffies, end)) { \
+ ret = -EBUSY; \
+ break; \
+ } \
+ schedule_timeout((HZ / 100 > 1) ? HZ / 100 : 1); \
+ if (!nosig && signal_pending(current)) { \
+ ret = -EINTR; \
+ break; \
+ } \
+ } \
+ __set_current_state(TASK_RUNNING); \
+ remove_wait_queue(ev, &entry); \
+} while (0)
+
+/*================ Direct IO mapping routines ==================*/
+extern int crystalhd_create_dio_pool(struct crystalhd_adp *, uint32_t);
+extern void crystalhd_destroy_dio_pool(struct crystalhd_adp *);
+extern BC_STATUS crystalhd_map_dio(struct crystalhd_adp *, void *, uint32_t,
+ uint32_t, bool, bool, crystalhd_dio_req**);
+
+extern BC_STATUS crystalhd_unmap_dio(struct crystalhd_adp *, crystalhd_dio_req*);
+#define crystalhd_get_sgle_paddr(_dio, _ix) (cpu_to_le64(sg_dma_address(&_dio->sg[_ix])))
+#define crystalhd_get_sgle_len(_dio, _ix) (cpu_to_le32(sg_dma_len(&_dio->sg[_ix])))
+
+/*================ General Purpose Queues ==================*/
+extern BC_STATUS crystalhd_create_dioq(struct crystalhd_adp *, crystalhd_dioq_t **, crystalhd_data_free_cb , void *);
+extern void crystalhd_delete_dioq(struct crystalhd_adp *, crystalhd_dioq_t *);
+extern BC_STATUS crystalhd_dioq_add(crystalhd_dioq_t *ioq, void *data, bool wake, uint32_t tag);
+extern void *crystalhd_dioq_fetch(crystalhd_dioq_t *ioq);
+extern void *crystalhd_dioq_find_and_fetch(crystalhd_dioq_t *ioq, uint32_t tag);
+extern void *crystalhd_dioq_fetch_wait(crystalhd_dioq_t *ioq, uint32_t to_secs, uint32_t *sig_pend);
+
+#define crystalhd_dioq_count(_ioq) ((_ioq) ? _ioq->count : 0)
+
+extern int crystalhd_create_elem_pool(struct crystalhd_adp *, uint32_t);
+extern void crystalhd_delete_elem_pool(struct crystalhd_adp *);
+
+
+/*================ Debug routines/macros .. ================================*/
+extern void crystalhd_show_buffer(uint32_t off, uint8_t *buff, uint32_t dwcount);
+
+enum _chd_log_levels {
+ BCMLOG_ERROR = 0x80000000, /* Don't disable this option */
+ BCMLOG_DATA = 0x40000000, /* Data, enable by default */
+ BCMLOG_SPINLOCK = 0x20000000, /* Spcial case for Spin locks*/
+
+ /* Following are allowed only in debug mode */
+ BCMLOG_INFO = 0x00000001, /* Generic informational */
+ BCMLOG_DBG = 0x00000002, /* First level Debug info */
+ BCMLOG_SSTEP = 0x00000004, /* Stepping information */
+ BCMLOG_ENTER_LEAVE = 0x00000008, /* stack tracking */
+};
+
+#define BCMLOG_ENTER \
+if (g_linklog_level & BCMLOG_ENTER_LEAVE) { \
+ printk("Entered %s\n", __func__); \
+}
+
+#define BCMLOG_LEAVE \
+if (g_linklog_level & BCMLOG_ENTER_LEAVE) { \
+ printk("Leaving %s\n", __func__); \
+}
+
+#define BCMLOG(trace, fmt, args...) \
+if (g_linklog_level & trace) { \
+ printk(fmt, ##args); \
+}
+
+#define BCMLOG_ERR(fmt, args...) \
+do { \
+ if (g_linklog_level & BCMLOG_ERROR) { \
+ printk("*ERR*:%s:%d: "fmt, __FILE__, __LINE__, ##args); \
+ } \
+} while (0);
+
+#endif
diff --git a/drivers/staging/cx25821/cx25821-audups11.c b/drivers/staging/cx25821/cx25821-audups11.c
index 89c8fe2997f..46c7f78bb97 100644
--- a/drivers/staging/cx25821/cx25821-audups11.c
+++ b/drivers/staging/cx25821/cx25821-audups11.c
@@ -343,10 +343,11 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctl)
{
struct cx25821_fh *fh = priv;
- struct cx25821_dev *dev = fh->dev;
+ struct cx25821_dev *dev;
int err;
if (fh) {
+ dev = fh->dev;
err = v4l2_prio_check(&dev->prio, &fh->prio);
if (0 != err)
return err;
diff --git a/drivers/staging/cx25821/cx25821-medusa-video.c b/drivers/staging/cx25821/cx25821-medusa-video.c
index 1eb079b3d42..d6016200d69 100644
--- a/drivers/staging/cx25821/cx25821-medusa-video.c
+++ b/drivers/staging/cx25821/cx25821-medusa-video.c
@@ -795,10 +795,8 @@ int medusa_video_init(struct cx25821_dev *dev)
value &= 0xFFFFFFDF;
ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value);
- if (ret_val < 0) {
- mutex_unlock(&dev->lock);
+ if (ret_val < 0)
return -EINVAL;
- }
mutex_unlock(&dev->lock);
diff --git a/drivers/staging/cx25821/cx25821-video.c b/drivers/staging/cx25821/cx25821-video.c
index c7c14c7698a..8cd3986d2e5 100644
--- a/drivers/staging/cx25821/cx25821-video.c
+++ b/drivers/staging/cx25821/cx25821-video.c
@@ -876,7 +876,7 @@ int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i)
dprintk(1, "%s()\n", __func__);
n = i->index;
- if (n > 2)
+ if (n >= 2)
return -EINVAL;
if (0 == INPUT(n)->type)
@@ -963,10 +963,11 @@ int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f)
int vidioc_s_frequency(struct file *file, void *priv, struct v4l2_frequency *f)
{
struct cx25821_fh *fh = priv;
- struct cx25821_dev *dev = fh->dev;
+ struct cx25821_dev *dev;
int err;
if (fh) {
+ dev = fh->dev;
err = v4l2_prio_check(&dev->prio, &fh->prio);
if (0 != err)
return err;
diff --git a/drivers/staging/dream/camera/Kconfig b/drivers/staging/dream/camera/Kconfig
index 0a3e903b336..bfb6d241d80 100644
--- a/drivers/staging/dream/camera/Kconfig
+++ b/drivers/staging/dream/camera/Kconfig
@@ -15,7 +15,7 @@ config MSM_CAMERA_DEBUG
config MSM_CAMERA_FLASH
bool "Qualcomm MSM camera flash support"
- depends on MSM_CAMERA
+ depends on MSM_CAMERA && BROKEN
---help---
Enable support for LED flash for msm camera
diff --git a/drivers/staging/dream/camera/Makefile b/drivers/staging/dream/camera/Makefile
index 4429ae5fcaf..db228d7d113 100644
--- a/drivers/staging/dream/camera/Makefile
+++ b/drivers/staging/dream/camera/Makefile
@@ -1,3 +1,4 @@
+EXTRA_CFLAGS=-Idrivers/staging/dream/include
obj-$(CONFIG_MT9T013) += mt9t013.o mt9t013_reg.o
obj-$(CONFIG_MT9D112) += mt9d112.o mt9d112_reg.o
obj-$(CONFIG_MT9P012) += mt9p012_fox.o mt9p012_reg.o
diff --git a/drivers/staging/dream/camera/msm_camera.c b/drivers/staging/dream/camera/msm_camera.c
index 7d938772eac..dc7c603625c 100644
--- a/drivers/staging/dream/camera/msm_camera.c
+++ b/drivers/staging/dream/camera/msm_camera.c
@@ -2,7 +2,7 @@
* Copyright (C) 2008-2009 QUALCOMM Incorporated.
*/
-//FIXME: most allocations need not be GFP_ATOMIC
+/* FIXME: most allocations need not be GFP_ATOMIC */
/* FIXME: management of mutexes */
/* FIXME: msm_pmem_region_lookup return values */
/* FIXME: way too many copy to/from user */
@@ -76,14 +76,14 @@ static LIST_HEAD(msm_sensors);
list_del_init(&qcmd->list); \
kfree(qcmd); \
}; \
-} while(0)
+} while (0)
#define MSM_DRAIN_QUEUE(sync, name) do { \
unsigned long flags; \
spin_lock_irqsave(&(sync)->name##_lock, flags); \
MSM_DRAIN_QUEUE_NOSYNC(sync, name); \
spin_unlock_irqrestore(&(sync)->name##_lock, flags); \
-} while(0)
+} while (0)
static int check_overlap(struct hlist_head *ptype,
unsigned long paddr,
@@ -361,7 +361,7 @@ static int __msm_get_frame(struct msm_sync *sync,
if (!frame->buffer) {
pr_err("%s: cannot get frame, invalid lookup address "
"y=%x cbcr=%x offset=%d\n",
- __FUNCTION__,
+ __func__,
pphy->y_phy,
pphy->cbcr_phy,
frame->y_off);
@@ -455,7 +455,7 @@ static int msm_disable_vfe(struct msm_sync *sync, void __user *arg)
return rc;
}
-static struct msm_queue_cmd* __msm_control(struct msm_sync *sync,
+static struct msm_queue_cmd *__msm_control(struct msm_sync *sync,
struct msm_control_device_queue *queue,
struct msm_queue_cmd *qcmd,
int timeout)
@@ -592,8 +592,7 @@ end:
* a result of a successful completion, we are freeing the qcmd that
* we dequeued from queue->ctrl_status_q.
*/
- if (qcmd)
- kfree(qcmd);
+ kfree(qcmd);
CDBG("msm_control: end rc = %d\n", rc);
return rc;
@@ -670,7 +669,7 @@ static int msm_get_stats(struct msm_sync *sync, void __user *arg)
&(stats.fd));
if (!stats.buffer) {
pr_err("%s: msm_pmem_stats_ptov_lookup error\n",
- __FUNCTION__);
+ __func__);
rc = -EINVAL;
goto failure;
}
@@ -718,8 +717,7 @@ static int msm_get_stats(struct msm_sync *sync, void __user *arg)
buf.fmain.buffer =
(unsigned long)region.vaddr;
buf.fmain.fd = region.fd;
- }
- else {
+ } else {
pr_err("%s: pmem lookup failed\n",
__func__);
rc = -EINVAL;
@@ -796,8 +794,7 @@ static int msm_get_stats(struct msm_sync *sync, void __user *arg)
}
failure:
- if (qcmd)
- kfree(qcmd);
+ kfree(qcmd);
CDBG("msm_get_stats: %d\n", rc);
return rc;
@@ -838,8 +835,8 @@ static int msm_ctrl_cmd_done(struct msm_control_device *ctrl_pmsm,
kfree(qcmd);
goto end;
}
- }
- else ctrlcmd->value = NULL;
+ } else
+ ctrlcmd->value = NULL;
end:
CDBG("msm_ctrl_cmd_done: end rc = %d\n", rc);
@@ -869,14 +866,14 @@ static int msm_config_vfe(struct msm_sync *sync, void __user *arg)
return -EFAULT;
}
- switch(cfgcmd.cmd_type) {
+ switch (cfgcmd.cmd_type) {
case CMD_STATS_ENABLE:
axi_data.bufnum1 =
msm_pmem_region_lookup(&sync->stats,
MSM_PMEM_AEC_AWB, &region[0],
NUM_WB_EXP_STAT_OUTPUT_BUFFERS);
if (!axi_data.bufnum1) {
- pr_err("%s: pmem region lookup error\n", __FUNCTION__);
+ pr_err("%s: pmem region lookup error\n", __func__);
return -EINVAL;
}
axi_data.region = &region[0];
@@ -888,7 +885,7 @@ static int msm_config_vfe(struct msm_sync *sync, void __user *arg)
MSM_PMEM_AF, &region[0],
NUM_AF_STAT_OUTPUT_BUFFERS);
if (!axi_data.bufnum1) {
- pr_err("%s: pmem region lookup error\n", __FUNCTION__);
+ pr_err("%s: pmem region lookup error\n", __func__);
return -EINVAL;
}
axi_data.region = &region[0];
@@ -899,7 +896,7 @@ static int msm_config_vfe(struct msm_sync *sync, void __user *arg)
break;
default:
pr_err("%s: unknown command type %d\n",
- __FUNCTION__, cfgcmd.cmd_type);
+ __func__, cfgcmd.cmd_type);
return -EINVAL;
}
@@ -928,7 +925,7 @@ static int msm_frame_axi_cfg(struct msm_sync *sync,
msm_pmem_region_lookup(&sync->frame, pmem_type,
&region[0], 8);
if (!axi_data.bufnum1) {
- pr_err("%s: pmem region lookup error\n", __FUNCTION__);
+ pr_err("%s: pmem region lookup error\n", __func__);
return -EINVAL;
}
break;
@@ -939,7 +936,7 @@ static int msm_frame_axi_cfg(struct msm_sync *sync,
msm_pmem_region_lookup(&sync->frame, pmem_type,
&region[0], 8);
if (!axi_data.bufnum2) {
- pr_err("%s: pmem region lookup error\n", __FUNCTION__);
+ pr_err("%s: pmem region lookup error\n", __func__);
return -EINVAL;
}
break;
@@ -950,7 +947,7 @@ static int msm_frame_axi_cfg(struct msm_sync *sync,
msm_pmem_region_lookup(&sync->frame, pmem_type,
&region[0], 8);
if (!axi_data.bufnum1) {
- pr_err("%s: pmem region lookup error\n", __FUNCTION__);
+ pr_err("%s: pmem region lookup error\n", __func__);
return -EINVAL;
}
@@ -959,7 +956,7 @@ static int msm_frame_axi_cfg(struct msm_sync *sync,
msm_pmem_region_lookup(&sync->frame, pmem_type,
&region[axi_data.bufnum1], 8);
if (!axi_data.bufnum2) {
- pr_err("%s: pmem region lookup error\n", __FUNCTION__);
+ pr_err("%s: pmem region lookup error\n", __func__);
return -EINVAL;
}
break;
@@ -970,7 +967,7 @@ static int msm_frame_axi_cfg(struct msm_sync *sync,
msm_pmem_region_lookup(&sync->frame, pmem_type,
&region[0], 8);
if (!axi_data.bufnum2) {
- pr_err("%s: pmem region lookup error\n", __FUNCTION__);
+ pr_err("%s: pmem region lookup error\n", __func__);
return -EINVAL;
}
break;
@@ -981,7 +978,7 @@ static int msm_frame_axi_cfg(struct msm_sync *sync,
default:
pr_err("%s: unknown command type %d\n",
- __FUNCTION__, cfgcmd->cmd_type);
+ __func__, cfgcmd->cmd_type);
return -EINVAL;
}
@@ -1047,7 +1044,7 @@ static int __msm_put_frame_buf(struct msm_sync *sync,
rc = sync->vfefn.vfe_config(&cfgcmd, &pphy);
} else {
pr_err("%s: msm_pmem_frame_vtop_lookup failed\n",
- __FUNCTION__);
+ __func__);
rc = -EINVAL;
}
@@ -1131,7 +1128,7 @@ static int msm_stats_axi_cfg(struct msm_sync *sync,
break;
default:
pr_err("%s: unknown command type %d\n",
- __FUNCTION__, cfgcmd->cmd_type);
+ __func__, cfgcmd->cmd_type);
return -EINVAL;
}
@@ -1140,7 +1137,7 @@ static int msm_stats_axi_cfg(struct msm_sync *sync,
msm_pmem_region_lookup(&sync->stats, pmem_type,
&region[0], NUM_WB_EXP_STAT_OUTPUT_BUFFERS);
if (!axi_data.bufnum1) {
- pr_err("%s: pmem region lookup error\n", __FUNCTION__);
+ pr_err("%s: pmem region lookup error\n", __func__);
return -EINVAL;
}
axi_data.region = &region[0];
@@ -1177,7 +1174,7 @@ static int msm_put_stats_buffer(struct msm_sync *sync, void __user *arg)
cfgcmd.cmd_type = CMD_STATS_AF_BUF_RELEASE;
else {
pr_err("%s: invalid buf type %d\n",
- __FUNCTION__,
+ __func__,
buf.type);
rc = -EINVAL;
goto put_done;
@@ -1223,7 +1220,7 @@ static int msm_axi_config(struct msm_sync *sync, void __user *arg)
default:
pr_err("%s: unknown command type %d\n",
- __FUNCTION__,
+ __func__,
cfgcmd.cmd_type);
return -EINVAL;
}
@@ -1622,7 +1619,8 @@ static int msm_release_control(struct inode *node, struct file *filep)
int rc;
struct msm_control_device *ctrl_pmsm = filep->private_data;
struct msm_device *pmsm = ctrl_pmsm->pmsm;
- printk("msm_camera: RELEASE %s\n", filep->f_path.dentry->d_name.name);
+ printk(KERN_INFO "msm_camera: RELEASE %s\n",
+ filep->f_path.dentry->d_name.name);
rc = __msm_release(pmsm->sync);
if (!rc) {
MSM_DRAIN_QUEUE(&ctrl_pmsm->ctrl_q, ctrl_status_q);
@@ -1636,7 +1634,8 @@ static int msm_release_frame(struct inode *node, struct file *filep)
{
int rc;
struct msm_device *pmsm = filep->private_data;
- printk("msm_camera: RELEASE %s\n", filep->f_path.dentry->d_name.name);
+ printk(KERN_INFO "msm_camera: RELEASE %s\n",
+ filep->f_path.dentry->d_name.name);
rc = __msm_release(pmsm->sync);
if (!rc) {
MSM_DRAIN_QUEUE(pmsm->sync, prev_frame_q);
@@ -1720,7 +1719,7 @@ static void msm_vfe_sync(struct msm_vfe_resp *vdata,
qcmd->type = qtype;
if (qtype == MSM_CAM_Q_VFE_MSG) {
- switch(vdata->type) {
+ switch (vdata->type) {
case VFE_MSG_OUTPUT1:
case VFE_MSG_OUTPUT2:
qcmd_frame =
@@ -1885,8 +1884,10 @@ static int msm_open_control(struct inode *inode, struct file *filep)
return -ENOMEM;
rc = msm_open_common(inode, filep, 0);
- if (rc < 0)
+ if (rc < 0) {
+ kfree(ctrl_pmsm);
return rc;
+ }
ctrl_pmsm->pmsm = filep->private_data;
filep->private_data = ctrl_pmsm;
@@ -1929,7 +1930,7 @@ static int __msm_v4l2_control(struct msm_sync *sync,
memcpy(out->value, ctrl->value, ctrl->length);
end:
- if (rcmd) kfree(rcmd);
+ kfree(rcmd);
CDBG("__msm_v4l2_control: end rc = %d\n", rc);
return rc;
}
diff --git a/drivers/staging/dream/camera/msm_vfe7x.c b/drivers/staging/dream/camera/msm_vfe7x.c
index 33ab3ac6ac5..62fd24d632d 100644
--- a/drivers/staging/dream/camera/msm_vfe7x.c
+++ b/drivers/staging/dream/camera/msm_vfe7x.c
@@ -255,8 +255,7 @@ static int vfe_7x_init(struct msm_vfe_callback *presp,
extlen = sizeof(struct vfe_frame_extra);
- extdata =
- kmalloc(sizeof(extlen), GFP_ATOMIC);
+ extdata = kmalloc(extlen, GFP_ATOMIC);
if (!extdata) {
rc = -ENOMEM;
goto init_fail;
diff --git a/drivers/staging/dream/camera/s5k3e2fx.c b/drivers/staging/dream/camera/s5k3e2fx.c
index edba19889b0..841792e2624 100644
--- a/drivers/staging/dream/camera/s5k3e2fx.c
+++ b/drivers/staging/dream/camera/s5k3e2fx.c
@@ -743,12 +743,12 @@ static int s5k3e2fx_sensor_open_init(const struct msm_camera_sensor_info *data)
}
/* initialize AF */
- if ((rc = s5k3e2fx_i2c_write_b(s5k3e2fx_client->addr,
- 0x3146, 0x3A)) < 0)
+ rc = s5k3e2fx_i2c_write_b(s5k3e2fx_client->addr, 0x3146, 0x3A);
+ if (rc < 0)
goto init_fail1;
- if ((rc = s5k3e2fx_i2c_write_b(s5k3e2fx_client->addr,
- 0x3130, 0x03)) < 0)
+ rc = s5k3e2fx_i2c_write_b(s5k3e2fx_client->addr, 0x3130, 0x03);
+ if (rc < 0)
goto init_fail1;
goto init_done;
@@ -814,20 +814,20 @@ static uint16_t s5k3e2fx_get_prev_lines_pf(void)
static uint16_t s5k3e2fx_get_prev_pixels_pl(void)
{
- return (s5k3e2fx_reg_pat[S_RES_PREVIEW].size_w +
- s5k3e2fx_reg_pat[S_RES_PREVIEW].blk_p);
+ return s5k3e2fx_reg_pat[S_RES_PREVIEW].size_w +
+ s5k3e2fx_reg_pat[S_RES_PREVIEW].blk_p;
}
static uint16_t s5k3e2fx_get_pict_lines_pf(void)
{
- return (s5k3e2fx_reg_pat[S_RES_CAPTURE].size_h +
- s5k3e2fx_reg_pat[S_RES_CAPTURE].blk_l);
+ return s5k3e2fx_reg_pat[S_RES_CAPTURE].size_h +
+ s5k3e2fx_reg_pat[S_RES_CAPTURE].blk_l;
}
static uint16_t s5k3e2fx_get_pict_pixels_pl(void)
{
- return (s5k3e2fx_reg_pat[S_RES_CAPTURE].size_w +
- s5k3e2fx_reg_pat[S_RES_CAPTURE].blk_p);
+ return s5k3e2fx_reg_pat[S_RES_CAPTURE].size_w +
+ s5k3e2fx_reg_pat[S_RES_CAPTURE].blk_p;
}
static uint32_t s5k3e2fx_get_pict_max_exp_lc(void)
@@ -1093,14 +1093,10 @@ static int32_t s5k3e2fx_move_focus(int direction, int32_t num_steps)
actual_step = step_direction * (int16_t)num_steps;
pos_offset = init_code + s5k3e2fx_ctrl->curr_lens_pos;
- gain = actual_step * 0x400 / 5;
+ gain = ((actual_step << 10) / 5) >> 10;
- for (i = 0; i <= 4; i++) {
- if (actual_step >= 0)
- s_move[i] = ((((i+1)*gain+0x200) - (i*gain+0x200))/0x400);
- else
- s_move[i] = ((((i+1)*gain-0x200) - (i*gain-0x200))/0x400);
- }
+ for (i = 0; i <= 4; i++)
+ s_move[i] = gain;
/* Ring Damping Code */
for (i = 0; i <= 4; i++) {
diff --git a/drivers/staging/dream/include/linux/android_pmem.h b/drivers/staging/dream/include/linux/android_pmem.h
new file mode 100644
index 00000000000..2fc05d7d335
--- /dev/null
+++ b/drivers/staging/dream/include/linux/android_pmem.h
@@ -0,0 +1,80 @@
+/* drivers/staging/dream/include/linux/android_pmem.h
+ *
+ * Copyright (C) 2007 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _ANDROID_PMEM_H_
+#define _ANDROID_PMEM_H_
+
+#define PMEM_IOCTL_MAGIC 'p'
+#define PMEM_GET_PHYS _IOW(PMEM_IOCTL_MAGIC, 1, unsigned int)
+#define PMEM_MAP _IOW(PMEM_IOCTL_MAGIC, 2, unsigned int)
+#define PMEM_GET_SIZE _IOW(PMEM_IOCTL_MAGIC, 3, unsigned int)
+#define PMEM_UNMAP _IOW(PMEM_IOCTL_MAGIC, 4, unsigned int)
+/* This ioctl will allocate pmem space, backing the file, it will fail
+ * if the file already has an allocation, pass it the len as the argument
+ * to the ioctl */
+#define PMEM_ALLOCATE _IOW(PMEM_IOCTL_MAGIC, 5, unsigned int)
+/* This will connect a one pmem file to another, pass the file that is already
+ * backed in memory as the argument to the ioctl
+ */
+#define PMEM_CONNECT _IOW(PMEM_IOCTL_MAGIC, 6, unsigned int)
+/* Returns the total size of the pmem region it is sent to as a pmem_region
+ * struct (with offset set to 0).
+ */
+#define PMEM_GET_TOTAL_SIZE _IOW(PMEM_IOCTL_MAGIC, 7, unsigned int)
+/* Revokes gpu registers and resets the gpu. Pass a pointer to the
+ * start of the mapped gpu regs (the vaddr returned by mmap) as the argument.
+ */
+#define HW3D_REVOKE_GPU _IOW(PMEM_IOCTL_MAGIC, 8, unsigned int)
+#define HW3D_GRANT_GPU _IOW(PMEM_IOCTL_MAGIC, 9, unsigned int)
+#define HW3D_WAIT_FOR_INTERRUPT _IOW(PMEM_IOCTL_MAGIC, 10, unsigned int)
+
+int get_pmem_file(int fd, unsigned long *start, unsigned long *vstart,
+ unsigned long *end, struct file **filp);
+int get_pmem_user_addr(struct file *file, unsigned long *start,
+ unsigned long *end);
+void put_pmem_file(struct file* file);
+void flush_pmem_file(struct file *file, unsigned long start, unsigned long len);
+
+struct android_pmem_platform_data
+{
+ const char* name;
+ /* starting physical address of memory region */
+ unsigned long start;
+ /* size of memory region */
+ unsigned long size;
+ /* set to indicate the region should not be managed with an allocator */
+ unsigned no_allocator;
+ /* set to indicate maps of this region should be cached, if a mix of
+ * cached and uncached is desired, set this and open the device with
+ * O_SYNC to get an uncached region */
+ unsigned cached;
+ /* The MSM7k has bits to enable a write buffer in the bus controller*/
+ unsigned buffered;
+};
+
+struct pmem_region {
+ unsigned long offset;
+ unsigned long len;
+};
+
+int pmem_setup(struct android_pmem_platform_data *pdata,
+ long (*ioctl)(struct file *, unsigned int, unsigned long),
+ int (*release)(struct inode *, struct file *));
+
+int pmem_remap(struct pmem_region *region, struct file *file,
+ unsigned operation);
+
+#endif //_ANDROID_PPP_H_
+
diff --git a/drivers/staging/dream/include/linux/gpio_event.h b/drivers/staging/dream/include/linux/gpio_event.h
new file mode 100644
index 00000000000..ffc5da392ad
--- /dev/null
+++ b/drivers/staging/dream/include/linux/gpio_event.h
@@ -0,0 +1,154 @@
+/* drivers/staging/dream/include/linux/gpio_event.h
+ *
+ * Copyright (C) 2007 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _LINUX_GPIO_EVENT_H
+#define _LINUX_GPIO_EVENT_H
+
+#include <linux/input.h>
+
+enum {
+ GPIO_EVENT_FUNC_UNINIT = 0x0,
+ GPIO_EVENT_FUNC_INIT = 0x1,
+ GPIO_EVENT_FUNC_SUSPEND = 0x2,
+ GPIO_EVENT_FUNC_RESUME = 0x3,
+};
+struct gpio_event_info {
+ int (*func)(struct input_dev *input_dev,
+ struct gpio_event_info *info,
+ void **data, int func);
+ int (*event)(struct input_dev *input_dev,
+ struct gpio_event_info *info,
+ void **data, unsigned int type,
+ unsigned int code, int value); /* out events */
+};
+
+struct gpio_event_platform_data {
+ const char *name;
+ struct gpio_event_info **info;
+ size_t info_count;
+ int (*power)(const struct gpio_event_platform_data *pdata, bool on);
+};
+
+#define GPIO_EVENT_DEV_NAME "gpio-event"
+
+/* Key matrix */
+
+enum gpio_event_matrix_flags {
+ /* unset: drive active output low, set: drive active output high */
+ GPIOKPF_ACTIVE_HIGH = 1U << 0,
+ GPIOKPF_DEBOUNCE = 1U << 1,
+ GPIOKPF_REMOVE_SOME_PHANTOM_KEYS = 1U << 2,
+ GPIOKPF_REMOVE_PHANTOM_KEYS = GPIOKPF_REMOVE_SOME_PHANTOM_KEYS |
+ GPIOKPF_DEBOUNCE,
+ GPIOKPF_DRIVE_INACTIVE = 1U << 3,
+ GPIOKPF_LEVEL_TRIGGERED_IRQ = 1U << 4,
+ GPIOKPF_PRINT_UNMAPPED_KEYS = 1U << 16,
+ GPIOKPF_PRINT_MAPPED_KEYS = 1U << 17,
+ GPIOKPF_PRINT_PHANTOM_KEYS = 1U << 18,
+};
+
+extern int gpio_event_matrix_func(struct input_dev *input_dev,
+ struct gpio_event_info *info, void **data, int func);
+struct gpio_event_matrix_info {
+ /* initialize to gpio_event_matrix_func */
+ struct gpio_event_info info;
+ /* size must be ninputs * noutputs */
+ const unsigned short *keymap;
+ unsigned int *input_gpios;
+ unsigned int *output_gpios;
+ unsigned int ninputs;
+ unsigned int noutputs;
+ /* time to wait before reading inputs after driving each output */
+ ktime_t settle_time;
+ /* time to wait before scanning the keypad a second time */
+ ktime_t debounce_delay;
+ ktime_t poll_time;
+ unsigned flags;
+};
+
+/* Directly connected inputs and outputs */
+
+enum gpio_event_direct_flags {
+ GPIOEDF_ACTIVE_HIGH = 1U << 0,
+/* GPIOEDF_USE_DOWN_IRQ = 1U << 1, */
+/* GPIOEDF_USE_IRQ = (1U << 2) | GPIOIDF_USE_DOWN_IRQ, */
+ GPIOEDF_PRINT_KEYS = 1U << 8,
+ GPIOEDF_PRINT_KEY_DEBOUNCE = 1U << 9,
+};
+
+struct gpio_event_direct_entry {
+ uint32_t gpio:23;
+ uint32_t code:9;
+};
+
+/* inputs */
+extern int gpio_event_input_func(struct input_dev *input_dev,
+ struct gpio_event_info *info, void **data, int func);
+struct gpio_event_input_info {
+ /* initialize to gpio_event_input_func */
+ struct gpio_event_info info;
+ ktime_t debounce_time;
+ ktime_t poll_time;
+ uint16_t flags;
+ uint16_t type;
+ const struct gpio_event_direct_entry *keymap;
+ size_t keymap_size;
+};
+
+/* outputs */
+extern int gpio_event_output_func(struct input_dev *input_dev,
+ struct gpio_event_info *info, void **data, int func);
+extern int gpio_event_output_event(struct input_dev *input_dev,
+ struct gpio_event_info *info, void **data,
+ unsigned int type, unsigned int code, int value);
+struct gpio_event_output_info {
+ /* initialize to gpio_event_output_func and gpio_event_output_event */
+ struct gpio_event_info info;
+ uint16_t flags;
+ uint16_t type;
+ const struct gpio_event_direct_entry *keymap;
+ size_t keymap_size;
+};
+
+
+/* axes */
+
+enum gpio_event_axis_flags {
+ GPIOEAF_PRINT_UNKNOWN_DIRECTION = 1U << 16,
+ GPIOEAF_PRINT_RAW = 1U << 17,
+ GPIOEAF_PRINT_EVENT = 1U << 18,
+};
+
+extern int gpio_event_axis_func(struct input_dev *input_dev,
+ struct gpio_event_info *info, void **data, int func);
+struct gpio_event_axis_info {
+ /* initialize to gpio_event_axis_func */
+ struct gpio_event_info info;
+ uint8_t count;
+ uint8_t type; /* EV_REL or EV_ABS */
+ uint16_t code;
+ uint16_t decoded_size;
+ uint16_t (*map)(struct gpio_event_axis_info *info, uint16_t in);
+ uint32_t *gpio;
+ uint32_t flags;
+};
+#define gpio_axis_2bit_gray_map gpio_axis_4bit_gray_map
+#define gpio_axis_3bit_gray_map gpio_axis_4bit_gray_map
+uint16_t gpio_axis_4bit_gray_map(
+ struct gpio_event_axis_info *info, uint16_t in);
+uint16_t gpio_axis_5bit_singletrack_map(
+ struct gpio_event_axis_info *info, uint16_t in);
+
+#endif
diff --git a/drivers/staging/dream/include/linux/msm_adsp.h b/drivers/staging/dream/include/linux/msm_adsp.h
new file mode 100644
index 00000000000..e775f3e94f1
--- /dev/null
+++ b/drivers/staging/dream/include/linux/msm_adsp.h
@@ -0,0 +1,84 @@
+/* drivers/staging/dream/include/linux/msm_adsp.h
+ *
+ * Copyright (c) QUALCOMM Incorporated
+ * Copyright (C) 2007 Google, Inc.
+ * Author: Iliyan Malchev <ibm@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+#ifndef __LINUX_MSM_ADSP_H
+#define __LINUX_MSM_ADSP_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define ADSP_IOCTL_MAGIC 'q'
+
+/* ADSP_IOCTL_WRITE_COMMAND */
+struct adsp_command_t {
+ uint16_t queue;
+ uint32_t len; /* bytes */
+ uint8_t *data;
+};
+
+/* ADSP_IOCTL_GET_EVENT */
+struct adsp_event_t {
+ uint16_t type; /* 1 == event (RPC), 0 == message (adsp) */
+ uint32_t timeout_ms; /* -1 for infinite, 0 for immediate return */
+ uint16_t msg_id;
+ uint16_t flags; /* 1 == 16--bit event, 0 == 32-bit event */
+ uint32_t len; /* size in, number of bytes out */
+ uint8_t *data;
+};
+
+#define ADSP_IOCTL_ENABLE \
+ _IOR(ADSP_IOCTL_MAGIC, 1, unsigned)
+
+#define ADSP_IOCTL_DISABLE \
+ _IOR(ADSP_IOCTL_MAGIC, 2, unsigned)
+
+#define ADSP_IOCTL_DISABLE_ACK \
+ _IOR(ADSP_IOCTL_MAGIC, 3, unsigned)
+
+#define ADSP_IOCTL_WRITE_COMMAND \
+ _IOR(ADSP_IOCTL_MAGIC, 4, struct adsp_command_t *)
+
+#define ADSP_IOCTL_GET_EVENT \
+ _IOWR(ADSP_IOCTL_MAGIC, 5, struct adsp_event_data_t *)
+
+#define ADSP_IOCTL_SET_CLKRATE \
+ _IOR(ADSP_IOCTL_MAGIC, 6, unsigned)
+
+#define ADSP_IOCTL_DISABLE_EVENT_RSP \
+ _IOR(ADSP_IOCTL_MAGIC, 10, unsigned)
+
+struct adsp_pmem_info {
+ int fd;
+ void *vaddr;
+};
+
+#define ADSP_IOCTL_REGISTER_PMEM \
+ _IOW(ADSP_IOCTL_MAGIC, 13, unsigned)
+
+#define ADSP_IOCTL_UNREGISTER_PMEM \
+ _IOW(ADSP_IOCTL_MAGIC, 14, unsigned)
+
+/* Cause any further GET_EVENT ioctls to fail (-ENODEV)
+ * until the device is closed and reopened. Useful for
+ * terminating event dispatch threads
+ */
+#define ADSP_IOCTL_ABORT_EVENT_READ \
+ _IOW(ADSP_IOCTL_MAGIC, 15, unsigned)
+
+#define ADSP_IOCTL_LINK_TASK \
+ _IOW(ADSP_IOCTL_MAGIC, 16, unsigned)
+
+#endif
diff --git a/drivers/staging/dream/include/linux/msm_audio.h b/drivers/staging/dream/include/linux/msm_audio.h
new file mode 100644
index 00000000000..cfbdaa0d98b
--- /dev/null
+++ b/drivers/staging/dream/include/linux/msm_audio.h
@@ -0,0 +1,115 @@
+/* drivers/staging/dream/include/linux/msm_audio.h
+ *
+ * Copyright (C) 2008 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __LINUX_MSM_AUDIO_H
+#define __LINUX_MSM_AUDIO_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <asm/sizes.h>
+
+/* PCM Audio */
+
+#define AUDIO_IOCTL_MAGIC 'a'
+
+#define AUDIO_START _IOW(AUDIO_IOCTL_MAGIC, 0, unsigned)
+#define AUDIO_STOP _IOW(AUDIO_IOCTL_MAGIC, 1, unsigned)
+#define AUDIO_FLUSH _IOW(AUDIO_IOCTL_MAGIC, 2, unsigned)
+#define AUDIO_GET_CONFIG _IOR(AUDIO_IOCTL_MAGIC, 3, unsigned)
+#define AUDIO_SET_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 4, unsigned)
+#define AUDIO_GET_STATS _IOR(AUDIO_IOCTL_MAGIC, 5, unsigned)
+#define AUDIO_ENABLE_AUDPP _IOW(AUDIO_IOCTL_MAGIC, 6, unsigned)
+#define AUDIO_SET_ADRC _IOW(AUDIO_IOCTL_MAGIC, 7, unsigned)
+#define AUDIO_SET_EQ _IOW(AUDIO_IOCTL_MAGIC, 8, unsigned)
+#define AUDIO_SET_RX_IIR _IOW(AUDIO_IOCTL_MAGIC, 9, unsigned)
+#define AUDIO_SET_VOLUME _IOW(AUDIO_IOCTL_MAGIC, 10, unsigned)
+#define AUDIO_ENABLE_AUDPRE _IOW(AUDIO_IOCTL_MAGIC, 11, unsigned)
+#define AUDIO_SET_AGC _IOW(AUDIO_IOCTL_MAGIC, 12, unsigned)
+#define AUDIO_SET_NS _IOW(AUDIO_IOCTL_MAGIC, 13, unsigned)
+#define AUDIO_SET_TX_IIR _IOW(AUDIO_IOCTL_MAGIC, 14, unsigned)
+#define AUDIO_PAUSE _IOW(AUDIO_IOCTL_MAGIC, 15, unsigned)
+#define AUDIO_GET_PCM_CONFIG _IOR(AUDIO_IOCTL_MAGIC, 30, unsigned)
+#define AUDIO_SET_PCM_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 31, unsigned)
+#define AUDIO_SWITCH_DEVICE _IOW(AUDIO_IOCTL_MAGIC, 32, unsigned)
+
+#define AUDIO_MAX_COMMON_IOCTL_NUM 100
+
+#define AUDIO_MAX_COMMON_IOCTL_NUM 100
+
+struct msm_audio_config {
+ uint32_t buffer_size;
+ uint32_t buffer_count;
+ uint32_t channel_count;
+ uint32_t sample_rate;
+ uint32_t type;
+ uint32_t unused[3];
+};
+
+struct msm_audio_stats {
+ uint32_t byte_count;
+ uint32_t sample_count;
+ uint32_t unused[2];
+};
+
+/* Audio routing */
+
+#define SND_IOCTL_MAGIC 's'
+
+#define SND_MUTE_UNMUTED 0
+#define SND_MUTE_MUTED 1
+
+struct msm_snd_device_config {
+ uint32_t device;
+ uint32_t ear_mute;
+ uint32_t mic_mute;
+};
+
+#define SND_SET_DEVICE _IOW(SND_IOCTL_MAGIC, 2, struct msm_device_config *)
+
+#define SND_METHOD_VOICE 0
+
+struct msm_snd_volume_config {
+ uint32_t device;
+ uint32_t method;
+ uint32_t volume;
+};
+
+#define SND_SET_VOLUME _IOW(SND_IOCTL_MAGIC, 3, struct msm_snd_volume_config *)
+
+/* Returns the number of SND endpoints supported. */
+
+#define SND_GET_NUM_ENDPOINTS _IOR(SND_IOCTL_MAGIC, 4, unsigned *)
+
+struct msm_snd_endpoint {
+ int id; /* input and output */
+ char name[64]; /* output only */
+};
+
+/* Takes an index between 0 and one less than the number returned by
+ * SND_GET_NUM_ENDPOINTS, and returns the SND index and name of a
+ * SND endpoint. On input, the .id field contains the number of the
+ * endpoint, and on exit it contains the SND index, while .name contains
+ * the description of the endpoint.
+ */
+
+#define SND_GET_ENDPOINT _IOWR(SND_IOCTL_MAGIC, 5, struct msm_snd_endpoint *)
+
+struct msm_audio_pcm_config {
+ uint32_t pcm_feedback; /* 0 - disable > 0 - enable */
+ uint32_t buffer_count; /* Number of buffers to allocate */
+ uint32_t buffer_size; /* Size of buffer for capturing of
+ PCM samples */
+};
+#endif
diff --git a/drivers/staging/dream/include/linux/msm_rpcrouter.h b/drivers/staging/dream/include/linux/msm_rpcrouter.h
new file mode 100644
index 00000000000..64845fb481f
--- /dev/null
+++ b/drivers/staging/dream/include/linux/msm_rpcrouter.h
@@ -0,0 +1,47 @@
+/* drivers/staging/dream/include/linux/msm_rpcrouter.h
+ *
+ * Copyright (c) QUALCOMM Incorporated
+ * Copyright (C) 2007 Google, Inc.
+ * Author: San Mehat <san@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+#ifndef __LINUX_MSM_RPCROUTER_H
+#define __LINUX_MSM_RPCROUTER_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define RPC_ROUTER_VERSION_V1 0x00010000
+
+struct rpcrouter_ioctl_server_args {
+ uint32_t prog;
+ uint32_t vers;
+};
+
+#define RPC_ROUTER_IOCTL_MAGIC (0xC1)
+
+#define RPC_ROUTER_IOCTL_GET_VERSION \
+ _IOR(RPC_ROUTER_IOCTL_MAGIC, 0, unsigned int)
+
+#define RPC_ROUTER_IOCTL_GET_MTU \
+ _IOR(RPC_ROUTER_IOCTL_MAGIC, 1, unsigned int)
+
+#define RPC_ROUTER_IOCTL_REGISTER_SERVER \
+ _IOWR(RPC_ROUTER_IOCTL_MAGIC, 2, unsigned int)
+
+#define RPC_ROUTER_IOCTL_UNREGISTER_SERVER \
+ _IOWR(RPC_ROUTER_IOCTL_MAGIC, 3, unsigned int)
+
+#define RPC_ROUTER_IOCTL_GET_MINOR_VERSION \
+ _IOW(RPC_ROUTER_IOCTL_MAGIC, 4, unsigned int)
+
+#endif
diff --git a/drivers/staging/dream/include/linux/wakelock.h b/drivers/staging/dream/include/linux/wakelock.h
new file mode 100644
index 00000000000..93c31a4d1ca
--- /dev/null
+++ b/drivers/staging/dream/include/linux/wakelock.h
@@ -0,0 +1,91 @@
+/* drivers/staging/dream/include/linux/wakelock.h
+ *
+ * Copyright (C) 2007-2008 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _LINUX_WAKELOCK_H
+#define _LINUX_WAKELOCK_H
+
+#include <linux/list.h>
+#include <linux/ktime.h>
+
+/* A wake_lock prevents the system from entering suspend or other low power
+ * states when active. If the type is set to WAKE_LOCK_SUSPEND, the wake_lock
+ * prevents a full system suspend. If the type is WAKE_LOCK_IDLE, low power
+ * states that cause large interrupt latencies or that disable a set of
+ * interrupts will not entered from idle until the wake_locks are released.
+ */
+
+enum {
+ WAKE_LOCK_SUSPEND, /* Prevent suspend */
+ WAKE_LOCK_IDLE, /* Prevent low power idle */
+ WAKE_LOCK_TYPE_COUNT
+};
+
+struct wake_lock {
+#ifdef CONFIG_HAS_WAKELOCK
+ struct list_head link;
+ int flags;
+ const char *name;
+ unsigned long expires;
+#ifdef CONFIG_WAKELOCK_STAT
+ struct {
+ int count;
+ int expire_count;
+ int wakeup_count;
+ ktime_t total_time;
+ ktime_t prevent_suspend_time;
+ ktime_t max_time;
+ ktime_t last_time;
+ } stat;
+#endif
+#endif
+};
+
+#ifdef CONFIG_HAS_WAKELOCK
+
+void wake_lock_init(struct wake_lock *lock, int type, const char *name);
+void wake_lock_destroy(struct wake_lock *lock);
+void wake_lock(struct wake_lock *lock);
+void wake_lock_timeout(struct wake_lock *lock, long timeout);
+void wake_unlock(struct wake_lock *lock);
+
+/* wake_lock_active returns a non-zero value if the wake_lock is currently
+ * locked. If the wake_lock has a timeout, it does not check the timeout
+ * but if the timeout had aready been checked it will return 0.
+ */
+int wake_lock_active(struct wake_lock *lock);
+
+/* has_wake_lock returns 0 if no wake locks of the specified type are active,
+ * and non-zero if one or more wake locks are held. Specifically it returns
+ * -1 if one or more wake locks with no timeout are active or the
+ * number of jiffies until all active wake locks time out.
+ */
+long has_wake_lock(int type);
+
+#else
+
+static inline void wake_lock_init(struct wake_lock *lock, int type,
+ const char *name) {}
+static inline void wake_lock_destroy(struct wake_lock *lock) {}
+static inline void wake_lock(struct wake_lock *lock) {}
+static inline void wake_lock_timeout(struct wake_lock *lock, long timeout) {}
+static inline void wake_unlock(struct wake_lock *lock) {}
+
+static inline int wake_lock_active(struct wake_lock *lock) { return 0; }
+static inline long has_wake_lock(int type) { return 0; }
+
+#endif
+
+#endif
+
diff --git a/drivers/staging/dream/include/mach/camera.h b/drivers/staging/dream/include/mach/camera.h
new file mode 100644
index 00000000000..c20f0423abd
--- /dev/null
+++ b/drivers/staging/dream/include/mach/camera.h
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2008-2009 QUALCOMM Incorporated.
+ */
+
+#ifndef __ASM__ARCH_CAMERA_H
+#define __ASM__ARCH_CAMERA_H
+
+#include <linux/list.h>
+#include <linux/poll.h>
+#include <linux/cdev.h>
+#include <linux/platform_device.h>
+#include "linux/types.h"
+
+#include <mach/board.h>
+#include <media/msm_camera.h>
+
+#ifdef CONFIG_MSM_CAMERA_DEBUG
+#define CDBG(fmt, args...) printk(KERN_INFO "msm_camera: " fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#endif
+
+#define MSM_CAMERA_MSG 0
+#define MSM_CAMERA_EVT 1
+#define NUM_WB_EXP_NEUTRAL_REGION_LINES 4
+#define NUM_WB_EXP_STAT_OUTPUT_BUFFERS 3
+#define NUM_AUTOFOCUS_MULTI_WINDOW_GRIDS 16
+#define NUM_AF_STAT_OUTPUT_BUFFERS 3
+
+enum msm_queue {
+ MSM_CAM_Q_CTRL, /* control command or control command status */
+ MSM_CAM_Q_VFE_EVT, /* adsp event */
+ MSM_CAM_Q_VFE_MSG, /* adsp message */
+ MSM_CAM_Q_V4L2_REQ, /* v4l2 request */
+};
+
+enum vfe_resp_msg {
+ VFE_EVENT,
+ VFE_MSG_GENERAL,
+ VFE_MSG_SNAPSHOT,
+ VFE_MSG_OUTPUT1,
+ VFE_MSG_OUTPUT2,
+ VFE_MSG_STATS_AF,
+ VFE_MSG_STATS_WE,
+};
+
+struct msm_vfe_phy_info {
+ uint32_t sbuf_phy;
+ uint32_t y_phy;
+ uint32_t cbcr_phy;
+};
+
+struct msm_vfe_resp {
+ enum vfe_resp_msg type;
+ struct msm_vfe_evt_msg evt_msg;
+ struct msm_vfe_phy_info phy;
+ void *extdata;
+ int32_t extlen;
+};
+
+struct msm_vfe_callback {
+ void (*vfe_resp)(struct msm_vfe_resp *,
+ enum msm_queue, void *syncdata);
+ void* (*vfe_alloc)(int, void *syncdata);
+};
+
+struct msm_camvfe_fn {
+ int (*vfe_init)(struct msm_vfe_callback *, struct platform_device *);
+ int (*vfe_enable)(struct camera_enable_cmd *);
+ int (*vfe_config)(struct msm_vfe_cfg_cmd *, void *);
+ int (*vfe_disable)(struct camera_enable_cmd *,
+ struct platform_device *dev);
+ void (*vfe_release)(struct platform_device *);
+};
+
+struct msm_sensor_ctrl {
+ int (*s_init)(const struct msm_camera_sensor_info *);
+ int (*s_release)(void);
+ int (*s_config)(void __user *);
+};
+
+struct msm_sync {
+ /* These two queues are accessed from a process context only. */
+ struct hlist_head frame; /* most-frequently accessed */
+ struct hlist_head stats;
+
+ /* The message queue is used by the control thread to send commands
+ * to the config thread, and also by the DSP to send messages to the
+ * config thread. Thus it is the only queue that is accessed from
+ * both interrupt and process context.
+ */
+ spinlock_t msg_event_q_lock;
+ struct list_head msg_event_q;
+ wait_queue_head_t msg_event_wait;
+
+ /* This queue contains preview frames. It is accessed by the DSP (in
+ * in interrupt context, and by the frame thread.
+ */
+ spinlock_t prev_frame_q_lock;
+ struct list_head prev_frame_q;
+ wait_queue_head_t prev_frame_wait;
+ int unblock_poll_frame;
+
+ /* This queue contains snapshot frames. It is accessed by the DSP (in
+ * interrupt context, and by the control thread.
+ */
+ spinlock_t pict_frame_q_lock;
+ struct list_head pict_frame_q;
+ wait_queue_head_t pict_frame_wait;
+
+ struct msm_camera_sensor_info *sdata;
+ struct msm_camvfe_fn vfefn;
+ struct msm_sensor_ctrl sctrl;
+ struct platform_device *pdev;
+ uint8_t opencnt;
+ void *cropinfo;
+ int croplen;
+ unsigned pict_pp;
+
+ const char *apps_id;
+
+ struct mutex lock;
+ struct list_head list;
+};
+
+#define MSM_APPS_ID_V4L2 "msm_v4l2"
+#define MSM_APPS_ID_PROP "msm_qct"
+
+struct msm_device {
+ struct msm_sync *sync; /* most-frequently accessed */
+ struct device *device;
+ struct cdev cdev;
+ /* opened is meaningful only for the config and frame nodes,
+ * which may be opened only once.
+ */
+ atomic_t opened;
+};
+
+struct msm_control_device_queue {
+ spinlock_t ctrl_status_q_lock;
+ struct list_head ctrl_status_q;
+ wait_queue_head_t ctrl_status_wait;
+};
+
+struct msm_control_device {
+ struct msm_device *pmsm;
+
+ /* This queue used by the config thread to send responses back to the
+ * control thread. It is accessed only from a process context.
+ */
+ struct msm_control_device_queue ctrl_q;
+};
+
+/* this structure is used in kernel */
+struct msm_queue_cmd {
+ struct list_head list;
+ enum msm_queue type;
+ void *command;
+};
+
+struct register_address_value_pair {
+ uint16_t register_address;
+ uint16_t register_value;
+};
+
+struct msm_pmem_region {
+ struct hlist_node list;
+ int type;
+ void *vaddr;
+ unsigned long paddr;
+ unsigned long len;
+ struct file *file;
+ uint32_t y_off;
+ uint32_t cbcr_off;
+ int fd;
+ uint8_t active;
+};
+
+struct axidata {
+ uint32_t bufnum1;
+ uint32_t bufnum2;
+ struct msm_pmem_region *region;
+};
+
+#ifdef CONFIG_MSM_CAMERA_FLASH
+int msm_camera_flash_set_led_state(unsigned led_state);
+#else
+static inline int msm_camera_flash_set_led_state(unsigned led_state)
+{
+ return -ENOTSUPP;
+}
+#endif
+
+/* Below functions are added for V4L2 kernel APIs */
+struct msm_v4l2_driver {
+ struct msm_sync *sync;
+ int (*open)(struct msm_sync *, const char *apps_id);
+ int (*release)(struct msm_sync *);
+ int (*ctrl)(struct msm_sync *, struct msm_ctrl_cmd *);
+ int (*reg_pmem)(struct msm_sync *, struct msm_pmem_info *);
+ int (*get_frame) (struct msm_sync *, struct msm_frame *);
+ int (*put_frame) (struct msm_sync *, struct msm_frame *);
+ int (*get_pict) (struct msm_sync *, struct msm_ctrl_cmd *);
+ unsigned int (*drv_poll) (struct msm_sync *, struct file *,
+ struct poll_table_struct *);
+};
+
+int msm_v4l2_register(struct msm_v4l2_driver *);
+int msm_v4l2_unregister(struct msm_v4l2_driver *);
+
+void msm_camvfe_init(void);
+int msm_camvfe_check(void *);
+void msm_camvfe_fn_init(struct msm_camvfe_fn *, void *);
+int msm_camera_drv_start(struct platform_device *dev,
+ int (*sensor_probe)(const struct msm_camera_sensor_info *,
+ struct msm_sensor_ctrl *));
+
+enum msm_camio_clk_type {
+ CAMIO_VFE_MDC_CLK,
+ CAMIO_MDC_CLK,
+ CAMIO_VFE_CLK,
+ CAMIO_VFE_AXI_CLK,
+
+ CAMIO_MAX_CLK
+};
+
+enum msm_camio_clk_src_type {
+ MSM_CAMIO_CLK_SRC_INTERNAL,
+ MSM_CAMIO_CLK_SRC_EXTERNAL,
+ MSM_CAMIO_CLK_SRC_MAX
+};
+
+enum msm_s_test_mode {
+ S_TEST_OFF,
+ S_TEST_1,
+ S_TEST_2,
+ S_TEST_3
+};
+
+enum msm_s_resolution {
+ S_QTR_SIZE,
+ S_FULL_SIZE,
+ S_INVALID_SIZE
+};
+
+enum msm_s_reg_update {
+ /* Sensor egisters that need to be updated during initialization */
+ S_REG_INIT,
+ /* Sensor egisters that needs periodic I2C writes */
+ S_UPDATE_PERIODIC,
+ /* All the sensor Registers will be updated */
+ S_UPDATE_ALL,
+ /* Not valid update */
+ S_UPDATE_INVALID
+};
+
+enum msm_s_setting {
+ S_RES_PREVIEW,
+ S_RES_CAPTURE
+};
+
+int msm_camio_enable(struct platform_device *dev);
+
+int msm_camio_clk_enable(enum msm_camio_clk_type clk);
+int msm_camio_clk_disable(enum msm_camio_clk_type clk);
+int msm_camio_clk_config(uint32_t freq);
+void msm_camio_clk_rate_set(int rate);
+void msm_camio_clk_axi_rate_set(int rate);
+
+void msm_camio_camif_pad_reg_reset(void);
+void msm_camio_camif_pad_reg_reset_2(void);
+
+void msm_camio_vfe_blk_reset(void);
+
+void msm_camio_clk_sel(enum msm_camio_clk_src_type);
+void msm_camio_disable(struct platform_device *);
+int msm_camio_probe_on(struct platform_device *);
+int msm_camio_probe_off(struct platform_device *);
+#endif
diff --git a/drivers/staging/dream/include/mach/msm_adsp.h b/drivers/staging/dream/include/mach/msm_adsp.h
new file mode 100644
index 00000000000..a081683328a
--- /dev/null
+++ b/drivers/staging/dream/include/mach/msm_adsp.h
@@ -0,0 +1,112 @@
+/* include/asm-arm/arch-msm/msm_adsp.h
+ *
+ * Copyright (C) 2008 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __ASM__ARCH_MSM_ADSP_H
+#define __ASM__ARCH_MSM_ADSP_H
+
+struct msm_adsp_module;
+
+struct msm_adsp_ops {
+ /* event is called from interrupt context when a message
+ * arrives from the DSP. Use the provided function pointer
+ * to copy the message into a local buffer. Do NOT call
+ * it multiple times.
+ */
+ void (*event)(void *driver_data, unsigned id, size_t len,
+ void (*getevent)(void *ptr, size_t len));
+};
+
+/* Get, Put, Enable, and Disable are synchronous and must only
+ * be called from thread context. Enable and Disable will block
+ * up to one second in the event of a fatal DSP error but are
+ * much faster otherwise.
+ */
+int msm_adsp_get(const char *name, struct msm_adsp_module **module,
+ struct msm_adsp_ops *ops, void *driver_data);
+void msm_adsp_put(struct msm_adsp_module *module);
+int msm_adsp_enable(struct msm_adsp_module *module);
+int msm_adsp_disable(struct msm_adsp_module *module);
+int adsp_set_clkrate(struct msm_adsp_module *module, unsigned long clk_rate);
+
+/* Write is safe to call from interrupt context.
+ */
+int msm_adsp_write(struct msm_adsp_module *module,
+ unsigned queue_id,
+ void *data, size_t len);
+
+#if CONFIG_MSM_AMSS_VERSION >= 6350
+/* Command Queue Indexes */
+#define QDSP_lpmCommandQueue 0
+#define QDSP_mpuAfeQueue 1
+#define QDSP_mpuGraphicsCmdQueue 2
+#define QDSP_mpuModmathCmdQueue 3
+#define QDSP_mpuVDecCmdQueue 4
+#define QDSP_mpuVDecPktQueue 5
+#define QDSP_mpuVEncCmdQueue 6
+#define QDSP_rxMpuDecCmdQueue 7
+#define QDSP_rxMpuDecPktQueue 8
+#define QDSP_txMpuEncQueue 9
+#define QDSP_uPAudPPCmd1Queue 10
+#define QDSP_uPAudPPCmd2Queue 11
+#define QDSP_uPAudPPCmd3Queue 12
+#define QDSP_uPAudPlay0BitStreamCtrlQueue 13
+#define QDSP_uPAudPlay1BitStreamCtrlQueue 14
+#define QDSP_uPAudPlay2BitStreamCtrlQueue 15
+#define QDSP_uPAudPlay3BitStreamCtrlQueue 16
+#define QDSP_uPAudPlay4BitStreamCtrlQueue 17
+#define QDSP_uPAudPreProcCmdQueue 18
+#define QDSP_uPAudRecBitStreamQueue 19
+#define QDSP_uPAudRecCmdQueue 20
+#define QDSP_uPDiagQueue 21
+#define QDSP_uPJpegActionCmdQueue 22
+#define QDSP_uPJpegCfgCmdQueue 23
+#define QDSP_uPVocProcQueue 24
+#define QDSP_vfeCommandQueue 25
+#define QDSP_vfeCommandScaleQueue 26
+#define QDSP_vfeCommandTableQueue 27
+#define QDSP_MAX_NUM_QUEUES 28
+#else
+/* Command Queue Indexes */
+#define QDSP_lpmCommandQueue 0
+#define QDSP_mpuAfeQueue 1
+#define QDSP_mpuGraphicsCmdQueue 2
+#define QDSP_mpuModmathCmdQueue 3
+#define QDSP_mpuVDecCmdQueue 4
+#define QDSP_mpuVDecPktQueue 5
+#define QDSP_mpuVEncCmdQueue 6
+#define QDSP_rxMpuDecCmdQueue 7
+#define QDSP_rxMpuDecPktQueue 8
+#define QDSP_txMpuEncQueue 9
+#define QDSP_uPAudPPCmd1Queue 10
+#define QDSP_uPAudPPCmd2Queue 11
+#define QDSP_uPAudPPCmd3Queue 12
+#define QDSP_uPAudPlay0BitStreamCtrlQueue 13
+#define QDSP_uPAudPlay1BitStreamCtrlQueue 14
+#define QDSP_uPAudPlay2BitStreamCtrlQueue 15
+#define QDSP_uPAudPlay3BitStreamCtrlQueue 16
+#define QDSP_uPAudPlay4BitStreamCtrlQueue 17
+#define QDSP_uPAudPreProcCmdQueue 18
+#define QDSP_uPAudRecBitStreamQueue 19
+#define QDSP_uPAudRecCmdQueue 20
+#define QDSP_uPJpegActionCmdQueue 21
+#define QDSP_uPJpegCfgCmdQueue 22
+#define QDSP_uPVocProcQueue 23
+#define QDSP_vfeCommandQueue 24
+#define QDSP_vfeCommandScaleQueue 25
+#define QDSP_vfeCommandTableQueue 26
+#define QDSP_QUEUE_MAX 26
+#endif
+
+#endif
diff --git a/drivers/staging/dream/include/mach/msm_rpcrouter.h b/drivers/staging/dream/include/mach/msm_rpcrouter.h
new file mode 100644
index 00000000000..9724ece1c97
--- /dev/null
+++ b/drivers/staging/dream/include/mach/msm_rpcrouter.h
@@ -0,0 +1,179 @@
+/** include/asm-arm/arch-msm/msm_rpcrouter.h
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2007-2009 QUALCOMM Incorporated
+ * Author: San Mehat <san@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __ASM__ARCH_MSM_RPCROUTER_H
+#define __ASM__ARCH_MSM_RPCROUTER_H
+
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/platform_device.h>
+
+#if CONFIG_MSM_AMSS_VERSION >= 6350
+/* RPC API version structure
+ * Version bit 31 : 1->hashkey versioning,
+ * 0->major-minor (backward compatible) versioning
+ * hashkey versioning:
+ * Version bits 31-0 hashkey
+ * major-minor (backward compatible) versioning
+ * Version bits 30-28 reserved (no match)
+ * Version bits 27-16 major (must match)
+ * Version bits 15-0 minor (greater or equal)
+ */
+#define RPC_VERSION_MODE_MASK 0x80000000
+#define RPC_VERSION_MAJOR_MASK 0x0fff0000
+#define RPC_VERSION_MAJOR_OFFSET 16
+#define RPC_VERSION_MINOR_MASK 0x0000ffff
+
+#define MSM_RPC_VERS(major, minor) \
+ ((uint32_t)((((major) << RPC_VERSION_MAJOR_OFFSET) & \
+ RPC_VERSION_MAJOR_MASK) | \
+ ((minor) & RPC_VERSION_MINOR_MASK)))
+#define MSM_RPC_GET_MAJOR(vers) (((vers) & RPC_VERSION_MAJOR_MASK) >> \
+ RPC_VERSION_MAJOR_OFFSET)
+#define MSM_RPC_GET_MINOR(vers) ((vers) & RPC_VERSION_MINOR_MASK)
+#else
+#define MSM_RPC_VERS(major, minor) (major)
+#define MSM_RPC_GET_MAJOR(vers) (vers)
+#define MSM_RPC_GET_MINOR(vers) 0
+#endif
+
+struct msm_rpc_endpoint;
+
+struct rpcsvr_platform_device
+{
+ struct platform_device base;
+ uint32_t prog;
+ uint32_t vers;
+};
+
+#define RPC_DATA_IN 0
+/*
+ * Structures for sending / receiving direct RPC requests
+ * XXX: Any cred/verif lengths > 0 not supported
+ */
+
+struct rpc_request_hdr
+{
+ uint32_t xid;
+ uint32_t type; /* 0 */
+ uint32_t rpc_vers; /* 2 */
+ uint32_t prog;
+ uint32_t vers;
+ uint32_t procedure;
+ uint32_t cred_flavor;
+ uint32_t cred_length;
+ uint32_t verf_flavor;
+ uint32_t verf_length;
+};
+
+typedef struct
+{
+ uint32_t low;
+ uint32_t high;
+} rpc_reply_progmismatch_data;
+
+typedef struct
+{
+} rpc_denied_reply_hdr;
+
+typedef struct
+{
+ uint32_t verf_flavor;
+ uint32_t verf_length;
+ uint32_t accept_stat;
+#define RPC_ACCEPTSTAT_SUCCESS 0
+#define RPC_ACCEPTSTAT_PROG_UNAVAIL 1
+#define RPC_ACCEPTSTAT_PROG_MISMATCH 2
+#define RPC_ACCEPTSTAT_PROC_UNAVAIL 3
+#define RPC_ACCEPTSTAT_GARBAGE_ARGS 4
+#define RPC_ACCEPTSTAT_SYSTEM_ERR 5
+#define RPC_ACCEPTSTAT_PROG_LOCKED 6
+ /*
+ * Following data is dependant on accept_stat
+ * If ACCEPTSTAT == PROG_MISMATCH then there is a
+ * 'rpc_reply_progmismatch_data' structure following the header.
+ * Otherwise the data is procedure specific
+ */
+} rpc_accepted_reply_hdr;
+
+struct rpc_reply_hdr
+{
+ uint32_t xid;
+ uint32_t type;
+ uint32_t reply_stat;
+#define RPCMSG_REPLYSTAT_ACCEPTED 0
+#define RPCMSG_REPLYSTAT_DENIED 1
+ union {
+ rpc_accepted_reply_hdr acc_hdr;
+ rpc_denied_reply_hdr dny_hdr;
+ } data;
+};
+
+/* flags for msm_rpc_connect() */
+#define MSM_RPC_UNINTERRUPTIBLE 0x0001
+
+/* use IS_ERR() to check for failure */
+struct msm_rpc_endpoint *msm_rpc_open(void);
+/* Connect with the specified server version */
+struct msm_rpc_endpoint *msm_rpc_connect(uint32_t prog, uint32_t vers, unsigned flags);
+uint32_t msm_rpc_get_vers(struct msm_rpc_endpoint *ept);
+/* check if server version can handle client requested version */
+int msm_rpc_is_compatible_version(uint32_t server_version,
+ uint32_t client_version);
+
+int msm_rpc_close(struct msm_rpc_endpoint *ept);
+int msm_rpc_write(struct msm_rpc_endpoint *ept,
+ void *data, int len);
+int msm_rpc_read(struct msm_rpc_endpoint *ept,
+ void **data, unsigned len, long timeout);
+void msm_rpc_setup_req(struct rpc_request_hdr *hdr,
+ uint32_t prog, uint32_t vers, uint32_t proc);
+int msm_rpc_register_server(struct msm_rpc_endpoint *ept,
+ uint32_t prog, uint32_t vers);
+int msm_rpc_unregister_server(struct msm_rpc_endpoint *ept,
+ uint32_t prog, uint32_t vers);
+
+/* simple blocking rpc call
+ *
+ * request is mandatory and must have a rpc_request_hdr
+ * at the start. The header will be filled out for you.
+ *
+ * reply provides a buffer for replies of reply_max_size
+ */
+int msm_rpc_call_reply(struct msm_rpc_endpoint *ept, uint32_t proc,
+ void *request, int request_size,
+ void *reply, int reply_max_size,
+ long timeout);
+int msm_rpc_call(struct msm_rpc_endpoint *ept, uint32_t proc,
+ void *request, int request_size,
+ long timeout);
+
+struct msm_rpc_server
+{
+ struct list_head list;
+ uint32_t flags;
+
+ uint32_t prog;
+ uint32_t vers;
+
+ int (*rpc_call)(struct msm_rpc_server *server,
+ struct rpc_request_hdr *req, unsigned len);
+};
+
+int msm_rpc_create_server(struct msm_rpc_server *server);
+
+#endif
diff --git a/drivers/staging/dream/include/mach/msm_smd.h b/drivers/staging/dream/include/mach/msm_smd.h
new file mode 100644
index 00000000000..bdf7731ab68
--- /dev/null
+++ b/drivers/staging/dream/include/mach/msm_smd.h
@@ -0,0 +1,107 @@
+/* linux/include/asm-arm/arch-msm/msm_smd.h
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Author: Brian Swetland <swetland@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __ASM_ARCH_MSM_SMD_H
+#define __ASM_ARCH_MSM_SMD_H
+
+typedef struct smd_channel smd_channel_t;
+
+/* warning: notify() may be called before open returns */
+int smd_open(const char *name, smd_channel_t **ch, void *priv,
+ void (*notify)(void *priv, unsigned event));
+
+#define SMD_EVENT_DATA 1
+#define SMD_EVENT_OPEN 2
+#define SMD_EVENT_CLOSE 3
+
+int smd_close(smd_channel_t *ch);
+
+/* passing a null pointer for data reads and discards */
+int smd_read(smd_channel_t *ch, void *data, int len);
+
+/* Write to stream channels may do a partial write and return
+** the length actually written.
+** Write to packet channels will never do a partial write --
+** it will return the requested length written or an error.
+*/
+int smd_write(smd_channel_t *ch, const void *data, int len);
+
+int smd_write_avail(smd_channel_t *ch);
+int smd_read_avail(smd_channel_t *ch);
+
+/* Returns the total size of the current packet being read.
+** Returns 0 if no packets available or a stream channel.
+*/
+int smd_cur_packet_size(smd_channel_t *ch);
+
+/* used for tty unthrottling and the like -- causes the notify()
+** callback to be called from the same lock context as is used
+** when it is called from channel updates
+*/
+void smd_kick(smd_channel_t *ch);
+
+
+#if 0
+/* these are interruptable waits which will block you until the specified
+** number of bytes are readable or writable.
+*/
+int smd_wait_until_readable(smd_channel_t *ch, int bytes);
+int smd_wait_until_writable(smd_channel_t *ch, int bytes);
+#endif
+
+typedef enum
+{
+ SMD_PORT_DS = 0,
+ SMD_PORT_DIAG,
+ SMD_PORT_RPC_CALL,
+ SMD_PORT_RPC_REPLY,
+ SMD_PORT_BT,
+ SMD_PORT_CONTROL,
+ SMD_PORT_MEMCPY_SPARE1,
+ SMD_PORT_DATA1,
+ SMD_PORT_DATA2,
+ SMD_PORT_DATA3,
+ SMD_PORT_DATA4,
+ SMD_PORT_DATA5,
+ SMD_PORT_DATA6,
+ SMD_PORT_DATA7,
+ SMD_PORT_DATA8,
+ SMD_PORT_DATA9,
+ SMD_PORT_DATA10,
+ SMD_PORT_DATA11,
+ SMD_PORT_DATA12,
+ SMD_PORT_DATA13,
+ SMD_PORT_DATA14,
+ SMD_PORT_DATA15,
+ SMD_PORT_DATA16,
+ SMD_PORT_DATA17,
+ SMD_PORT_DATA18,
+ SMD_PORT_DATA19,
+ SMD_PORT_DATA20,
+ SMD_PORT_GPS_NMEA,
+ SMD_PORT_BRIDGE_1,
+ SMD_PORT_BRIDGE_2,
+ SMD_PORT_BRIDGE_3,
+ SMD_PORT_BRIDGE_4,
+ SMD_PORT_BRIDGE_5,
+ SMD_PORT_LOOPBACK,
+ SMD_PORT_CS_APPS_MODEM,
+ SMD_PORT_CS_APPS_DSP,
+ SMD_PORT_CS_MODEM_DSP,
+ SMD_NUM_PORTS,
+} smd_port_id_type;
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5audplaycmdi.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5audplaycmdi.h
new file mode 100644
index 00000000000..0b6a31259bb
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5audplaycmdi.h
@@ -0,0 +1,94 @@
+#ifndef QDSP5AUDPLAYCMDI_H
+#define QDSP5AUDPLAYCMDI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+ Q D S P 5 A U D I O P L A Y T A S K C O M M A N D S
+
+GENERAL DESCRIPTION
+ Command Interface for AUDPLAYTASK on QDSP5
+
+REFERENCES
+ None
+
+EXTERNALIZED FUNCTIONS
+
+ audplay_cmd_dec_data_avail
+ Send buffer to AUDPLAY task
+
+
+Copyright(c) 1992 - 2009 by QUALCOMM, Incorporated.
+
+This software is licensed under the terms of the GNU General Public
+License version 2, as published by the Free Software Foundation, and
+may be copied, distributed, and modified under those terms.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+ EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/Audio/drivers/QDSP5Driver/QDSP5Interface/main/latest/qdsp5audplaycmdi.h#2 $
+
+===========================================================================*/
+
+#define AUDPLAY_CMD_BITSTREAM_DATA_AVAIL 0x0000
+#define AUDPLAY_CMD_BITSTREAM_DATA_AVAIL_LEN \
+ sizeof(audplay_cmd_bitstream_data_avail)
+
+/* Type specification of dec_data_avail message sent to AUDPLAYTASK
+*/
+typedef struct {
+ /*command ID*/
+ unsigned int cmd_id;
+
+ /* Decoder ID for which message is being sent */
+ unsigned int decoder_id;
+
+ /* Start address of data in ARM global memory */
+ unsigned int buf_ptr;
+
+ /* Number of 16-bit words of bit-stream data contiguously available at the
+ * above-mentioned address. */
+ unsigned int buf_size;
+
+ /* Partition number used by audPlayTask to communicate with DSP's RTOS
+ * kernel */
+ unsigned int partition_number;
+} __attribute__((packed)) audplay_cmd_bitstream_data_avail;
+
+#define AUDPLAY_CMD_HPCM_BUF_CFG 0x0003
+#define AUDPLAY_CMD_HPCM_BUF_CFG_LEN \
+ sizeof(struct audplay_cmd_hpcm_buf_cfg)
+
+struct audplay_cmd_hpcm_buf_cfg {
+ unsigned int cmd_id;
+ unsigned int hostpcm_config;
+ unsigned int feedback_frequency;
+ unsigned int byte_swap;
+ unsigned int max_buffers;
+ unsigned int partition_number;
+} __attribute__((packed));
+
+#define AUDPLAY_CMD_BUFFER_REFRESH 0x0004
+#define AUDPLAY_CMD_BUFFER_REFRESH_LEN \
+ sizeof(struct audplay_cmd_buffer_update)
+
+struct audplay_cmd_buffer_refresh {
+ unsigned int cmd_id;
+ unsigned int num_buffers;
+ unsigned int buf_read_count;
+ unsigned int buf0_address;
+ unsigned int buf0_length;
+ unsigned int buf1_address;
+ unsigned int buf1_length;
+} __attribute__((packed));
+#endif /* QDSP5AUDPLAYCMD_H */
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5audplaymsg.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5audplaymsg.h
new file mode 100644
index 00000000000..c63034b8bf1
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5audplaymsg.h
@@ -0,0 +1,70 @@
+#ifndef QDSP5AUDPLAYMSG_H
+#define QDSP5AUDPLAYMSG_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+ Q D S P 5 A U D I O P L A Y T A S K M S G
+
+GENERAL DESCRIPTION
+ Message sent by AUDPLAY task
+
+REFERENCES
+ None
+
+
+Copyright(c) 1992 - 2009 by QUALCOMM, Incorporated.
+
+This software is licensed under the terms of the GNU General Public
+License version 2, as published by the Free Software Foundation, and
+may be copied, distributed, and modified under those terms.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+ EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/Audio/drivers/QDSP5Driver/QDSP5Interface/main/latest/qdsp5audplaymsg.h#3 $
+
+===========================================================================*/
+#define AUDPLAY_MSG_DEC_NEEDS_DATA 0x0001
+#define AUDPLAY_MSG_DEC_NEEDS_DATA_MSG_LEN \
+ sizeof(audplay_msg_dec_needs_data)
+
+typedef struct{
+ /* reserved*/
+ unsigned int dec_id;
+
+ /* The read pointer offset of external memory until which the
+ * bitstream has been DMAed in. */
+ unsigned int adecDataReadPtrOffset;
+
+ /* The buffer size of external memory. */
+ unsigned int adecDataBufSize;
+
+ unsigned int bitstream_free_len;
+ unsigned int bitstream_write_ptr;
+ unsigned int bitstarem_buf_start;
+ unsigned int bitstream_buf_len;
+} __attribute__((packed)) audplay_msg_dec_needs_data;
+
+#define AUDPLAY_MSG_BUFFER_UPDATE 0x0004
+#define AUDPLAY_MSG_BUFFER_UPDATE_LEN \
+ sizeof(struct audplay_msg_buffer_update)
+
+struct audplay_msg_buffer_update {
+ unsigned int buffer_write_count;
+ unsigned int num_of_buffer;
+ unsigned int buf0_address;
+ unsigned int buf0_length;
+ unsigned int buf1_address;
+ unsigned int buf1_length;
+} __attribute__((packed));
+#endif /* QDSP5AUDPLAYMSG_H */
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5audppcmdi.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5audppcmdi.h
new file mode 100644
index 00000000000..8bee9c62980
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5audppcmdi.h
@@ -0,0 +1,914 @@
+#ifndef QDSP5AUDPPCMDI_H
+#define QDSP5AUDPPCMDI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+ A U D I O P O S T P R O C E S S I N G I N T E R N A L C O M M A N D S
+
+GENERAL DESCRIPTION
+ This file contains defintions of format blocks of commands
+ that are accepted by AUDPP Task
+
+REFERENCES
+ None
+
+EXTERNALIZED FUNCTIONS
+ None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+This software is licensed under the terms of the GNU General Public
+License version 2, as published by the Free Software Foundation, and
+may be copied, distributed, and modified under those terms.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+ EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/Audio/drivers/QDSP5Driver/QDSP5Interface/main/latest/qdsp5audppcmdi.h#2 $
+
+===========================================================================*/
+
+/*
+ * ARM to AUDPPTASK Commands
+ *
+ * ARM uses three command queues to communicate with AUDPPTASK
+ * 1)uPAudPPCmd1Queue : Used for more frequent and shorter length commands
+ * Location : MEMA
+ * Buffer Size : 6 words
+ * No of buffers in a queue : 20 for gaming audio and 5 for other images
+ * 2)uPAudPPCmd2Queue : Used for commands which are not much lengthier
+ * Location : MEMA
+ * Buffer Size : 23
+ * No of buffers in a queue : 2
+ * 3)uPAudOOCmd3Queue : Used for lengthier and more frequent commands
+ * Location : MEMA
+ * Buffer Size : 145
+ * No of buffers in a queue : 3
+ */
+
+/*
+ * Commands Related to uPAudPPCmd1Queue
+ */
+
+/*
+ * Command Structure to enable or disable the active decoders
+ */
+
+#define AUDPP_CMD_CFG_DEC_TYPE 0x0001
+#define AUDPP_CMD_CFG_DEC_TYPE_LEN sizeof(audpp_cmd_cfg_dec_type)
+
+/* Enable the decoder */
+#define AUDPP_CMD_DEC_TYPE_M 0x000F
+
+#define AUDPP_CMD_ENA_DEC_V 0x4000
+#define AUDPP_CMD_DIS_DEC_V 0x0000
+#define AUDPP_CMD_DEC_STATE_M 0x4000
+
+#define AUDPP_CMD_UPDATDE_CFG_DEC 0x8000
+#define AUDPP_CMD_DONT_UPDATE_CFG_DEC 0x0000
+
+
+/* Type specification of cmd_cfg_dec */
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short dec0_cfg;
+ unsigned short dec1_cfg;
+ unsigned short dec2_cfg;
+ unsigned short dec3_cfg;
+ unsigned short dec4_cfg;
+} __attribute__((packed)) audpp_cmd_cfg_dec_type;
+
+/*
+ * Command Structure to Pause , Resume and flushes the selected audio decoders
+ */
+
+#define AUDPP_CMD_DEC_CTRL 0x0002
+#define AUDPP_CMD_DEC_CTRL_LEN sizeof(audpp_cmd_dec_ctrl)
+
+/* Decoder control commands for pause, resume and flush */
+#define AUDPP_CMD_FLUSH_V 0x2000
+
+#define AUDPP_CMD_PAUSE_V 0x4000
+#define AUDPP_CMD_RESUME_V 0x0000
+
+#define AUDPP_CMD_UPDATE_V 0x8000
+#define AUDPP_CMD_IGNORE_V 0x0000
+
+
+/* Type Spec for decoder control command*/
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short dec0_ctrl;
+ unsigned short dec1_ctrl;
+ unsigned short dec2_ctrl;
+ unsigned short dec3_ctrl;
+ unsigned short dec4_ctrl;
+} __attribute__((packed)) audpp_cmd_dec_ctrl;
+
+/*
+ * Command Structure to Configure the AVSync FeedBack Mechanism
+ */
+
+#define AUDPP_CMD_AVSYNC 0x0003
+#define AUDPP_CMD_AVSYNC_LEN sizeof(audpp_cmd_avsync)
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short object_number;
+ unsigned short interrupt_interval_lsw;
+ unsigned short interrupt_interval_msw;
+} __attribute__((packed)) audpp_cmd_avsync;
+
+/*
+ * Command Structure to enable or disable(sleep) the AUDPPTASK
+ */
+
+#define AUDPP_CMD_CFG 0x0004
+#define AUDPP_CMD_CFG_LEN sizeof(audpp_cmd_cfg)
+
+#define AUDPP_CMD_CFG_SLEEP 0x0000
+#define AUDPP_CMD_CFG_ENABLE 0xFFFF
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short cfg;
+} __attribute__((packed)) audpp_cmd_cfg;
+
+/*
+ * Command Structure to Inject or drop the specified no of samples
+ */
+
+#define AUDPP_CMD_ADJUST_SAMP 0x0005
+#define AUDPP_CMD_ADJUST_SAMP_LEN sizeof(audpp_cmd_adjust_samp)
+
+#define AUDPP_CMD_SAMP_DROP -1
+#define AUDPP_CMD_SAMP_INSERT 0x0001
+
+#define AUDPP_CMD_NUM_SAMPLES 0x0001
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short object_no;
+ signed short sample_insert_or_drop;
+ unsigned short num_samples;
+} __attribute__((packed)) audpp_cmd_adjust_samp;
+
+/*
+ * Command Structure to Configure AVSync Feedback Mechanism
+ */
+
+#define AUDPP_CMD_AVSYNC_CMD_2 0x0006
+#define AUDPP_CMD_AVSYNC_CMD_2_LEN sizeof(audpp_cmd_avsync_cmd_2)
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short object_number;
+ unsigned short interrupt_interval_lsw;
+ unsigned short interrupt_interval_msw;
+ unsigned short sample_counter_dlsw;
+ unsigned short sample_counter_dmsw;
+ unsigned short sample_counter_msw;
+ unsigned short byte_counter_dlsw;
+ unsigned short byte_counter_dmsw;
+ unsigned short byte_counter_msw;
+} __attribute__((packed)) audpp_cmd_avsync_cmd_2;
+
+/*
+ * Command Structure to Configure AVSync Feedback Mechanism
+ */
+
+#define AUDPP_CMD_AVSYNC_CMD_3 0x0007
+#define AUDPP_CMD_AVSYNC_CMD_3_LEN sizeof(audpp_cmd_avsync_cmd_3)
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short object_number;
+ unsigned short interrupt_interval_lsw;
+ unsigned short interrupt_interval_msw;
+ unsigned short sample_counter_dlsw;
+ unsigned short sample_counter_dmsw;
+ unsigned short sample_counter_msw;
+ unsigned short byte_counter_dlsw;
+ unsigned short byte_counter_dmsw;
+ unsigned short byte_counter_msw;
+} __attribute__((packed)) audpp_cmd_avsync_cmd_3;
+
+#define AUDPP_CMD_ROUTING_MODE 0x0008
+#define AUDPP_CMD_ROUTING_MODE_LEN \
+sizeof(struct audpp_cmd_routing_mode)
+
+struct audpp_cmd_routing_mode {
+ unsigned short cmd_id;
+ unsigned short object_number;
+ unsigned short routing_mode;
+} __attribute__((packed));
+
+/*
+ * Commands Related to uPAudPPCmd2Queue
+ */
+
+/*
+ * Command Structure to configure Per decoder Parameters (Common)
+ */
+
+#define AUDPP_CMD_CFG_ADEC_PARAMS 0x0000
+#define AUDPP_CMD_CFG_ADEC_PARAMS_COMMON_LEN \
+ sizeof(audpp_cmd_cfg_adec_params_common)
+
+#define AUDPP_CMD_STATUS_MSG_FLAG_ENA_FCM 0x4000
+#define AUDPP_CMD_STATUS_MSG_FLAG_DIS_FCM 0x0000
+
+#define AUDPP_CMD_STATUS_MSG_FLAG_ENA_DCM 0x8000
+#define AUDPP_CMD_STATUS_MSG_FLAG_DIS_DCM 0x0000
+
+/* Sampling frequency*/
+#define AUDPP_CMD_SAMP_RATE_96000 0x0000
+#define AUDPP_CMD_SAMP_RATE_88200 0x0001
+#define AUDPP_CMD_SAMP_RATE_64000 0x0002
+#define AUDPP_CMD_SAMP_RATE_48000 0x0003
+#define AUDPP_CMD_SAMP_RATE_44100 0x0004
+#define AUDPP_CMD_SAMP_RATE_32000 0x0005
+#define AUDPP_CMD_SAMP_RATE_24000 0x0006
+#define AUDPP_CMD_SAMP_RATE_22050 0x0007
+#define AUDPP_CMD_SAMP_RATE_16000 0x0008
+#define AUDPP_CMD_SAMP_RATE_12000 0x0009
+#define AUDPP_CMD_SAMP_RATE_11025 0x000A
+#define AUDPP_CMD_SAMP_RATE_8000 0x000B
+
+
+/*
+ * Type specification of cmd_adec_cfg sent to all decoder
+ */
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short length;
+ unsigned short dec_id;
+ unsigned short status_msg_flag;
+ unsigned short decoder_frame_counter_msg_period;
+ unsigned short input_sampling_frequency;
+} __attribute__((packed)) audpp_cmd_cfg_adec_params_common;
+
+/*
+ * Command Structure to configure Per decoder Parameters (Wav)
+ */
+
+#define AUDPP_CMD_CFG_ADEC_PARAMS_WAV_LEN \
+ sizeof(audpp_cmd_cfg_adec_params_wav)
+
+
+#define AUDPP_CMD_WAV_STEREO_CFG_MONO 0x0001
+#define AUDPP_CMD_WAV_STEREO_CFG_STEREO 0x0002
+
+#define AUDPP_CMD_WAV_PCM_WIDTH_8 0x0000
+#define AUDPP_CMD_WAV_PCM_WIDTH_16 0x0001
+#define AUDPP_CMD_WAV_PCM_WIDTH_32 0x0002
+
+typedef struct {
+ audpp_cmd_cfg_adec_params_common common;
+ unsigned short stereo_cfg;
+ unsigned short pcm_width;
+ unsigned short sign;
+} __attribute__((packed)) audpp_cmd_cfg_adec_params_wav;
+
+/*
+ * Command Structure to configure Per decoder Parameters (ADPCM)
+ */
+
+#define AUDPP_CMD_CFG_ADEC_PARAMS_ADPCM_LEN \
+ sizeof(audpp_cmd_cfg_adec_params_adpcm)
+
+
+#define AUDPP_CMD_ADPCM_STEREO_CFG_MONO 0x0001
+#define AUDPP_CMD_ADPCM_STEREO_CFG_STEREO 0x0002
+
+typedef struct {
+ audpp_cmd_cfg_adec_params_common common;
+ unsigned short stereo_cfg;
+ unsigned short block_size;
+} __attribute__((packed)) audpp_cmd_cfg_adec_params_adpcm;
+
+/*
+ * Command Structure to configure Per decoder Parameters (MP3)
+ */
+
+#define AUDPP_CMD_CFG_ADEC_PARAMS_MP3_LEN \
+ sizeof(audpp_cmd_cfg_adec_params_mp3)
+
+typedef struct {
+ audpp_cmd_cfg_adec_params_common common;
+} __attribute__((packed)) audpp_cmd_cfg_adec_params_mp3;
+
+
+/*
+ * Command Structure to configure Per decoder Parameters (AAC)
+ */
+
+#define AUDPP_CMD_CFG_ADEC_PARAMS_AAC_LEN \
+ sizeof(audpp_cmd_cfg_adec_params_aac)
+
+
+#define AUDPP_CMD_AAC_FORMAT_ADTS -1
+#define AUDPP_CMD_AAC_FORMAT_RAW 0x0000
+#define AUDPP_CMD_AAC_FORMAT_PSUEDO_RAW 0x0001
+#define AUDPP_CMD_AAC_FORMAT_LOAS 0x0002
+
+#define AUDPP_CMD_AAC_AUDIO_OBJECT_LC 0x0002
+#define AUDPP_CMD_AAC_AUDIO_OBJECT_LTP 0x0004
+#define AUDPP_CMD_AAC_AUDIO_OBJECT_ERLC 0x0011
+
+#define AUDPP_CMD_AAC_SBR_ON_FLAG_ON 0x0001
+#define AUDPP_CMD_AAC_SBR_ON_FLAG_OFF 0x0000
+
+#define AUDPP_CMD_AAC_SBR_PS_ON_FLAG_ON 0x0001
+#define AUDPP_CMD_AAC_SBR_PS_ON_FLAG_OFF 0x0000
+
+typedef struct {
+ audpp_cmd_cfg_adec_params_common common;
+ signed short format;
+ unsigned short audio_object;
+ unsigned short ep_config;
+ unsigned short aac_section_data_resilience_flag;
+ unsigned short aac_scalefactor_data_resilience_flag;
+ unsigned short aac_spectral_data_resilience_flag;
+ unsigned short sbr_on_flag;
+ unsigned short sbr_ps_on_flag;
+ unsigned short dual_mono_mode;
+ unsigned short channel_configuration;
+} __attribute__((packed)) audpp_cmd_cfg_adec_params_aac;
+
+/*
+ * Command Structure to configure Per decoder Parameters (V13K)
+ */
+
+#define AUDPP_CMD_CFG_ADEC_PARAMS_V13K_LEN \
+ sizeof(struct audpp_cmd_cfg_adec_params_v13k)
+
+
+#define AUDPP_CMD_STEREO_CFG_MONO 0x0001
+#define AUDPP_CMD_STEREO_CFG_STEREO 0x0002
+
+struct audpp_cmd_cfg_adec_params_v13k {
+ audpp_cmd_cfg_adec_params_common common;
+ unsigned short stereo_cfg;
+} __attribute__((packed));
+
+#define AUDPP_CMD_CFG_ADEC_PARAMS_EVRC_LEN \
+ sizeof(struct audpp_cmd_cfg_adec_params_evrc)
+
+struct audpp_cmd_cfg_adec_params_evrc {
+ audpp_cmd_cfg_adec_params_common common;
+ unsigned short stereo_cfg;
+} __attribute__ ((packed));
+
+/*
+ * Command Structure to configure the HOST PCM interface
+ */
+
+#define AUDPP_CMD_PCM_INTF 0x0001
+#define AUDPP_CMD_PCM_INTF_2 0x0002
+#define AUDPP_CMD_PCM_INTF_LEN sizeof(audpp_cmd_pcm_intf)
+
+#define AUDPP_CMD_PCM_INTF_MONO_V 0x0001
+#define AUDPP_CMD_PCM_INTF_STEREO_V 0x0002
+
+/* These two values differentiate the two types of commands that could be issued
+ * Interface configuration command and Buffer update command */
+
+#define AUDPP_CMD_PCM_INTF_CONFIG_CMD_V 0x0000
+#define AUDPP_CMD_PCM_INTF_BUFFER_CMD_V -1
+
+#define AUDPP_CMD_PCM_INTF_RX_ENA_M 0x000F
+#define AUDPP_CMD_PCM_INTF_RX_ENA_ARMTODSP_V 0x0008
+#define AUDPP_CMD_PCM_INTF_RX_ENA_DSPTOARM_V 0x0004
+
+/* These flags control the enabling and disabling of the interface together
+ * with host interface bit mask. */
+
+#define AUDPP_CMD_PCM_INTF_ENA_V -1
+#define AUDPP_CMD_PCM_INTF_DIS_V 0x0000
+
+
+#define AUDPP_CMD_PCM_INTF_FULL_DUPLEX 0x0
+#define AUDPP_CMD_PCM_INTF_HALF_DUPLEX_TODSP 0x1
+
+
+#define AUDPP_CMD_PCM_INTF_OBJECT_NUM 0x5
+#define AUDPP_CMD_PCM_INTF_COMMON_OBJECT_NUM 0x6
+
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short object_num;
+ signed short config;
+ unsigned short intf_type;
+
+ /* DSP -> ARM Configuration */
+ unsigned short read_buf1LSW;
+ unsigned short read_buf1MSW;
+ unsigned short read_buf1_len;
+
+ unsigned short read_buf2LSW;
+ unsigned short read_buf2MSW;
+ unsigned short read_buf2_len;
+ /* 0:HOST_PCM_INTF disable
+ ** 0xFFFF: HOST_PCM_INTF enable
+ */
+ signed short dsp_to_arm_flag;
+ unsigned short partition_number;
+
+ /* ARM -> DSP Configuration */
+ unsigned short write_buf1LSW;
+ unsigned short write_buf1MSW;
+ unsigned short write_buf1_len;
+
+ unsigned short write_buf2LSW;
+ unsigned short write_buf2MSW;
+ unsigned short write_buf2_len;
+
+ /* 0:HOST_PCM_INTF disable
+ ** 0xFFFF: HOST_PCM_INTF enable
+ */
+ signed short arm_to_rx_flag;
+ unsigned short weight_decoder_to_rx;
+ unsigned short weight_arm_to_rx;
+
+ unsigned short partition_number_arm_to_dsp;
+ unsigned short sample_rate;
+ unsigned short channel_mode;
+} __attribute__((packed)) audpp_cmd_pcm_intf;
+
+/*
+ ** BUFFER UPDATE COMMAND
+ */
+#define AUDPP_CMD_PCM_INTF_SEND_BUF_PARAMS_LEN \
+ sizeof(audpp_cmd_pcm_intf_send_buffer)
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short host_pcm_object;
+ /* set config = 0xFFFF for configuration*/
+ signed short config;
+ unsigned short intf_type;
+ unsigned short dsp_to_arm_buf_id;
+ unsigned short arm_to_dsp_buf_id;
+ unsigned short arm_to_dsp_buf_len;
+} __attribute__((packed)) audpp_cmd_pcm_intf_send_buffer;
+
+
+/*
+ * Commands Related to uPAudPPCmd3Queue
+ */
+
+/*
+ * Command Structure to configure post processing params (Commmon)
+ */
+
+#define AUDPP_CMD_CFG_OBJECT_PARAMS 0x0000
+#define AUDPP_CMD_CFG_OBJECT_PARAMS_COMMON_LEN \
+ sizeof(audpp_cmd_cfg_object_params_common)
+
+#define AUDPP_CMD_OBJ0_UPDATE 0x8000
+#define AUDPP_CMD_OBJ0_DONT_UPDATE 0x0000
+
+#define AUDPP_CMD_OBJ1_UPDATE 0x8000
+#define AUDPP_CMD_OBJ1_DONT_UPDATE 0x0000
+
+#define AUDPP_CMD_OBJ2_UPDATE 0x8000
+#define AUDPP_CMD_OBJ2_DONT_UPDATE 0x0000
+
+#define AUDPP_CMD_OBJ3_UPDATE 0x8000
+#define AUDPP_CMD_OBJ3_DONT_UPDATE 0x0000
+
+#define AUDPP_CMD_OBJ4_UPDATE 0x8000
+#define AUDPP_CMD_OBJ4_DONT_UPDATE 0x0000
+
+#define AUDPP_CMD_HPCM_UPDATE 0x8000
+#define AUDPP_CMD_HPCM_DONT_UPDATE 0x0000
+
+#define AUDPP_CMD_COMMON_CFG_UPDATE 0x8000
+#define AUDPP_CMD_COMMON_CFG_DONT_UPDATE 0x0000
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short obj0_cfg;
+ unsigned short obj1_cfg;
+ unsigned short obj2_cfg;
+ unsigned short obj3_cfg;
+ unsigned short obj4_cfg;
+ unsigned short host_pcm_obj_cfg;
+ unsigned short comman_cfg;
+ unsigned short command_type;
+} __attribute__((packed)) audpp_cmd_cfg_object_params_common;
+
+/*
+ * Command Structure to configure post processing params (Volume)
+ */
+
+#define AUDPP_CMD_CFG_OBJECT_PARAMS_VOLUME_LEN \
+ sizeof(audpp_cmd_cfg_object_params_volume)
+
+typedef struct {
+ audpp_cmd_cfg_object_params_common common;
+ unsigned short volume;
+ unsigned short pan;
+} __attribute__((packed)) audpp_cmd_cfg_object_params_volume;
+
+/*
+ * Command Structure to configure post processing params (PCM Filter) --DOUBT
+ */
+
+typedef struct {
+ unsigned short numerator_b0_filter_lsw;
+ unsigned short numerator_b0_filter_msw;
+ unsigned short numerator_b1_filter_lsw;
+ unsigned short numerator_b1_filter_msw;
+ unsigned short numerator_b2_filter_lsw;
+ unsigned short numerator_b2_filter_msw;
+} __attribute__((packed)) numerator;
+
+typedef struct {
+ unsigned short denominator_a0_filter_lsw;
+ unsigned short denominator_a0_filter_msw;
+ unsigned short denominator_a1_filter_lsw;
+ unsigned short denominator_a1_filter_msw;
+} __attribute__((packed)) denominator;
+
+typedef struct {
+ unsigned short shift_factor_0;
+} __attribute__((packed)) shift_factor;
+
+typedef struct {
+ unsigned short pan_filter_0;
+} __attribute__((packed)) pan;
+
+typedef struct {
+ numerator numerator_filter;
+ denominator denominator_filter;
+ shift_factor shift_factor_filter;
+ pan pan_filter;
+} __attribute__((packed)) filter_1;
+
+typedef struct {
+ numerator numerator_filter[2];
+ denominator denominator_filter[2];
+ shift_factor shift_factor_filter[2];
+ pan pan_filter[2];
+} __attribute__((packed)) filter_2;
+
+typedef struct {
+ numerator numerator_filter[3];
+ denominator denominator_filter[3];
+ shift_factor shift_factor_filter[3];
+ pan pan_filter[3];
+} __attribute__((packed)) filter_3;
+
+typedef struct {
+ numerator numerator_filter[4];
+ denominator denominator_filter[4];
+ shift_factor shift_factor_filter[4];
+ pan pan_filter[4];
+} __attribute__((packed)) filter_4;
+
+#define AUDPP_CMD_CFG_OBJECT_PARAMS_PCM_LEN \
+ sizeof(audpp_cmd_cfg_object_params_pcm)
+
+
+typedef struct {
+ audpp_cmd_cfg_object_params_common common;
+ unsigned short active_flag;
+ unsigned short num_bands;
+ union {
+ filter_1 filter_1_params;
+ filter_2 filter_2_params;
+ filter_3 filter_3_params;
+ filter_4 filter_4_params;
+ } __attribute__((packed)) params_filter;
+} __attribute__((packed)) audpp_cmd_cfg_object_params_pcm;
+
+
+/*
+ * Command Structure to configure post processing parameters (equalizer)
+ */
+
+#define AUDPP_CMD_CFG_OBJECT_PARAMS_EQALIZER_LEN \
+ sizeof(audpp_cmd_cfg_object_params_eqalizer)
+
+typedef struct {
+ unsigned short numerator_coeff_0_lsw;
+ unsigned short numerator_coeff_0_msw;
+ unsigned short numerator_coeff_1_lsw;
+ unsigned short numerator_coeff_1_msw;
+ unsigned short numerator_coeff_2_lsw;
+ unsigned short numerator_coeff_2_msw;
+} __attribute__((packed)) eq_numerator;
+
+typedef struct {
+ unsigned short denominator_coeff_0_lsw;
+ unsigned short denominator_coeff_0_msw;
+ unsigned short denominator_coeff_1_lsw;
+ unsigned short denominator_coeff_1_msw;
+} __attribute__((packed)) eq_denominator;
+
+typedef struct {
+ unsigned short shift_factor;
+} __attribute__((packed)) eq_shiftfactor;
+
+typedef struct {
+ eq_numerator numerator;
+ eq_denominator denominator;
+ eq_shiftfactor shiftfactor;
+} __attribute__((packed)) eq_coeff_1;
+
+typedef struct {
+ eq_numerator numerator[2];
+ eq_denominator denominator[2];
+ eq_shiftfactor shiftfactor[2];
+} __attribute__((packed)) eq_coeff_2;
+
+typedef struct {
+ eq_numerator numerator[3];
+ eq_denominator denominator[3];
+ eq_shiftfactor shiftfactor[3];
+} __attribute__((packed)) eq_coeff_3;
+
+typedef struct {
+ eq_numerator numerator[4];
+ eq_denominator denominator[4];
+ eq_shiftfactor shiftfactor[4];
+} __attribute__((packed)) eq_coeff_4;
+
+typedef struct {
+ eq_numerator numerator[5];
+ eq_denominator denominator[5];
+ eq_shiftfactor shiftfactor[5];
+} __attribute__((packed)) eq_coeff_5;
+
+typedef struct {
+ eq_numerator numerator[6];
+ eq_denominator denominator[6];
+ eq_shiftfactor shiftfactor[6];
+} __attribute__((packed)) eq_coeff_6;
+
+typedef struct {
+ eq_numerator numerator[7];
+ eq_denominator denominator[7];
+ eq_shiftfactor shiftfactor[7];
+} __attribute__((packed)) eq_coeff_7;
+
+typedef struct {
+ eq_numerator numerator[8];
+ eq_denominator denominator[8];
+ eq_shiftfactor shiftfactor[8];
+} __attribute__((packed)) eq_coeff_8;
+
+typedef struct {
+ eq_numerator numerator[9];
+ eq_denominator denominator[9];
+ eq_shiftfactor shiftfactor[9];
+} __attribute__((packed)) eq_coeff_9;
+
+typedef struct {
+ eq_numerator numerator[10];
+ eq_denominator denominator[10];
+ eq_shiftfactor shiftfactor[10];
+} __attribute__((packed)) eq_coeff_10;
+
+typedef struct {
+ eq_numerator numerator[11];
+ eq_denominator denominator[11];
+ eq_shiftfactor shiftfactor[11];
+} __attribute__((packed)) eq_coeff_11;
+
+typedef struct {
+ eq_numerator numerator[12];
+ eq_denominator denominator[12];
+ eq_shiftfactor shiftfactor[12];
+} __attribute__((packed)) eq_coeff_12;
+
+
+typedef struct {
+ audpp_cmd_cfg_object_params_common common;
+ unsigned short eq_flag;
+ unsigned short num_bands;
+ union {
+ eq_coeff_1 eq_coeffs_1;
+ eq_coeff_2 eq_coeffs_2;
+ eq_coeff_3 eq_coeffs_3;
+ eq_coeff_4 eq_coeffs_4;
+ eq_coeff_5 eq_coeffs_5;
+ eq_coeff_6 eq_coeffs_6;
+ eq_coeff_7 eq_coeffs_7;
+ eq_coeff_8 eq_coeffs_8;
+ eq_coeff_9 eq_coeffs_9;
+ eq_coeff_10 eq_coeffs_10;
+ eq_coeff_11 eq_coeffs_11;
+ eq_coeff_12 eq_coeffs_12;
+ } __attribute__((packed)) eq_coeff;
+} __attribute__((packed)) audpp_cmd_cfg_object_params_eqalizer;
+
+
+/*
+ * Command Structure to configure post processing parameters (ADRC)
+ */
+
+#define AUDPP_CMD_CFG_OBJECT_PARAMS_ADRC_LEN \
+ sizeof(audpp_cmd_cfg_object_params_adrc)
+
+
+#define AUDPP_CMD_ADRC_FLAG_DIS 0x0000
+#define AUDPP_CMD_ADRC_FLAG_ENA -1
+
+typedef struct {
+ audpp_cmd_cfg_object_params_common common;
+ signed short adrc_flag;
+ unsigned short compression_th;
+ unsigned short compression_slope;
+ unsigned short rms_time;
+ unsigned short attack_const_lsw;
+ unsigned short attack_const_msw;
+ unsigned short release_const_lsw;
+ unsigned short release_const_msw;
+ unsigned short adrc_system_delay;
+} __attribute__((packed)) audpp_cmd_cfg_object_params_adrc;
+
+/*
+ * Command Structure to configure post processing parameters(Spectrum Analizer)
+ */
+
+#define AUDPP_CMD_CFG_OBJECT_PARAMS_SPECTRAM_LEN \
+ sizeof(audpp_cmd_cfg_object_params_spectram)
+
+
+typedef struct {
+ audpp_cmd_cfg_object_params_common common;
+ unsigned short sample_interval;
+ unsigned short num_coeff;
+} __attribute__((packed)) audpp_cmd_cfg_object_params_spectram;
+
+/*
+ * Command Structure to configure post processing parameters (QConcert)
+ */
+
+#define AUDPP_CMD_CFG_OBJECT_PARAMS_QCONCERT_LEN \
+ sizeof(audpp_cmd_cfg_object_params_qconcert)
+
+
+#define AUDPP_CMD_QCON_ENA_FLAG_ENA -1
+#define AUDPP_CMD_QCON_ENA_FLAG_DIS 0x0000
+
+#define AUDPP_CMD_QCON_OP_MODE_HEADPHONE -1
+#define AUDPP_CMD_QCON_OP_MODE_SPEAKER_FRONT 0x0000
+#define AUDPP_CMD_QCON_OP_MODE_SPEAKER_SIDE 0x0001
+#define AUDPP_CMD_QCON_OP_MODE_SPEAKER_DESKTOP 0x0002
+
+#define AUDPP_CMD_QCON_GAIN_UNIT 0x7FFF
+#define AUDPP_CMD_QCON_GAIN_SIX_DB 0x4027
+
+
+#define AUDPP_CMD_QCON_EXPANSION_MAX 0x7FFF
+
+
+typedef struct {
+ audpp_cmd_cfg_object_params_common common;
+ signed short enable_flag;
+ signed short output_mode;
+ signed short gain;
+ signed short expansion;
+ signed short delay;
+ unsigned short stages_per_mode;
+} __attribute__((packed)) audpp_cmd_cfg_object_params_qconcert;
+
+/*
+ * Command Structure to configure post processing parameters (Side Chain)
+ */
+
+#define AUDPP_CMD_CFG_OBJECT_PARAMS_SIDECHAIN_LEN \
+ sizeof(audpp_cmd_cfg_object_params_sidechain)
+
+
+#define AUDPP_CMD_SIDECHAIN_ACTIVE_FLAG_DIS 0x0000
+#define AUDPP_CMD_SIDECHAIN_ACTIVE_FLAG_ENA -1
+
+typedef struct {
+ audpp_cmd_cfg_object_params_common common;
+ signed short active_flag;
+ unsigned short num_bands;
+ union {
+ filter_1 filter_1_params;
+ filter_2 filter_2_params;
+ filter_3 filter_3_params;
+ filter_4 filter_4_params;
+ } __attribute__((packed)) params_filter;
+} __attribute__((packed)) audpp_cmd_cfg_object_params_sidechain;
+
+
+/*
+ * Command Structure to configure post processing parameters (QAFX)
+ */
+
+#define AUDPP_CMD_CFG_OBJECT_PARAMS_QAFX_LEN \
+ sizeof(audpp_cmd_cfg_object_params_qafx)
+
+#define AUDPP_CMD_QAFX_ENA_DISA 0x0000
+#define AUDPP_CMD_QAFX_ENA_ENA_CFG -1
+#define AUDPP_CMD_QAFX_ENA_DIS_CFG 0x0001
+
+#define AUDPP_CMD_QAFX_CMD_TYPE_ENV 0x0100
+#define AUDPP_CMD_QAFX_CMD_TYPE_OBJ 0x0010
+#define AUDPP_CMD_QAFX_CMD_TYPE_QUERY 0x1000
+
+#define AUDPP_CMD_QAFX_CMDS_ENV_OP_MODE 0x0100
+#define AUDPP_CMD_QAFX_CMDS_ENV_LIS_POS 0x0101
+#define AUDPP_CMD_QAFX_CMDS_ENV_LIS_ORI 0x0102
+#define AUDPP_CMD_QAFX_CMDS_ENV_LIS_VEL 0X0103
+#define AUDPP_CMD_QAFX_CMDS_ENV_ENV_RES 0x0107
+
+#define AUDPP_CMD_QAFX_CMDS_OBJ_SAMP_FREQ 0x0010
+#define AUDPP_CMD_QAFX_CMDS_OBJ_VOL 0x0011
+#define AUDPP_CMD_QAFX_CMDS_OBJ_DIST 0x0012
+#define AUDPP_CMD_QAFX_CMDS_OBJ_POS 0x0013
+#define AUDPP_CMD_QAFX_CMDS_OBJ_VEL 0x0014
+
+
+typedef struct {
+ audpp_cmd_cfg_object_params_common common;
+ signed short enable;
+ unsigned short command_type;
+ unsigned short num_commands;
+ unsigned short commands;
+} __attribute__((packed)) audpp_cmd_cfg_object_params_qafx;
+
+/*
+ * Command Structure to enable , disable or configure the reverberation effect
+ * (Common)
+ */
+
+#define AUDPP_CMD_REVERB_CONFIG 0x0001
+#define AUDPP_CMD_REVERB_CONFIG_COMMON_LEN \
+ sizeof(audpp_cmd_reverb_config_common)
+
+#define AUDPP_CMD_ENA_ENA 0xFFFF
+#define AUDPP_CMD_ENA_DIS 0x0000
+#define AUDPP_CMD_ENA_CFG 0x0001
+
+#define AUDPP_CMD_CMD_TYPE_ENV 0x0104
+#define AUDPP_CMD_CMD_TYPE_OBJ 0x0015
+#define AUDPP_CMD_CMD_TYPE_QUERY 0x1000
+
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short enable;
+ unsigned short cmd_type;
+} __attribute__((packed)) audpp_cmd_reverb_config_common;
+
+/*
+ * Command Structure to enable , disable or configure the reverberation effect
+ * (ENV-0x0104)
+ */
+
+#define AUDPP_CMD_REVERB_CONFIG_ENV_104_LEN \
+ sizeof(audpp_cmd_reverb_config_env_104)
+
+typedef struct {
+ audpp_cmd_reverb_config_common common;
+ unsigned short env_gain;
+ unsigned short decay_msw;
+ unsigned short decay_lsw;
+ unsigned short decay_timeratio_msw;
+ unsigned short decay_timeratio_lsw;
+ unsigned short delay_time;
+ unsigned short reverb_gain;
+ unsigned short reverb_delay;
+} __attribute__((packed)) audpp_cmd_reverb_config_env_104;
+
+/*
+ * Command Structure to enable , disable or configure the reverberation effect
+ * (ENV-0x0015)
+ */
+
+#define AUDPP_CMD_REVERB_CONFIG_ENV_15_LEN \
+ sizeof(audpp_cmd_reverb_config_env_15)
+
+typedef struct {
+ audpp_cmd_reverb_config_common common;
+ unsigned short object_num;
+ unsigned short absolute_gain;
+} __attribute__((packed)) audpp_cmd_reverb_config_env_15;
+
+
+#endif /* QDSP5AUDPPCMDI_H */
+
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5audppmsg.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5audppmsg.h
new file mode 100644
index 00000000000..44fea224001
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5audppmsg.h
@@ -0,0 +1,318 @@
+#ifndef QDSP5AUDPPMSG_H
+#define QDSP5AUDPPMSG_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+ Q D S P 5 A U D I O P O S T P R O C E S S I N G M S G
+
+GENERAL DESCRIPTION
+ Messages sent by AUDPPTASK to ARM
+
+REFERENCES
+ None
+
+EXTERNALIZED FUNCTIONS
+ None
+
+Copyright(c) 1992 - 2009 by QUALCOMM, Incorporated.
+
+This software is licensed under the terms of the GNU General Public
+License version 2, as published by the Free Software Foundation, and
+may be copied, distributed, and modified under those terms.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+ EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+ $Header: //source/qcom/qct/multimedia2/Audio/drivers/QDSP5Driver/QDSP5Interface/main/latest/qdsp5audppmsg.h#4 $
+
+===========================================================================*/
+
+/*
+ * AUDPPTASK uses audPPuPRlist to send messages to the ARM
+ * Location : MEMA
+ * Buffer Size : 45
+ * No of Buffers in a queue : 5 for gaming audio and 1 for other images
+ */
+
+/*
+ * MSG to Informs the ARM os Success/Failure of bringing up the decoder
+ */
+
+#define AUDPP_MSG_STATUS_MSG 0x0001
+#define AUDPP_MSG_STATUS_MSG_LEN \
+ sizeof(audpp_msg_status_msg)
+
+#define AUDPP_MSG_STATUS_SLEEP 0x0000
+#define AUDPP_MSG__STATUS_INIT 0x0001
+#define AUDPP_MSG_MSG_STATUS_CFG 0x0002
+#define AUDPP_MSG_STATUS_PLAY 0x0003
+
+#define AUDPP_MSG_REASON_MIPS 0x0000
+#define AUDPP_MSG_REASON_MEM 0x0001
+
+typedef struct{
+ unsigned short dec_id;
+ unsigned short status;
+ unsigned short reason;
+} __attribute__((packed)) audpp_msg_status_msg;
+
+/*
+ * MSG to communicate the spectrum analyzer output bands to the ARM
+ */
+#define AUDPP_MSG_SPA_BANDS 0x0002
+#define AUDPP_MSG_SPA_BANDS_LEN \
+ sizeof(audpp_msg_spa_bands)
+
+typedef struct {
+ unsigned short current_object;
+ unsigned short spa_band_1;
+ unsigned short spa_band_2;
+ unsigned short spa_band_3;
+ unsigned short spa_band_4;
+ unsigned short spa_band_5;
+ unsigned short spa_band_6;
+ unsigned short spa_band_7;
+ unsigned short spa_band_8;
+ unsigned short spa_band_9;
+ unsigned short spa_band_10;
+ unsigned short spa_band_11;
+ unsigned short spa_band_12;
+ unsigned short spa_band_13;
+ unsigned short spa_band_14;
+ unsigned short spa_band_15;
+ unsigned short spa_band_16;
+ unsigned short spa_band_17;
+ unsigned short spa_band_18;
+ unsigned short spa_band_19;
+ unsigned short spa_band_20;
+ unsigned short spa_band_21;
+ unsigned short spa_band_22;
+ unsigned short spa_band_23;
+ unsigned short spa_band_24;
+ unsigned short spa_band_25;
+ unsigned short spa_band_26;
+ unsigned short spa_band_27;
+ unsigned short spa_band_28;
+ unsigned short spa_band_29;
+ unsigned short spa_band_30;
+ unsigned short spa_band_31;
+ unsigned short spa_band_32;
+} __attribute__((packed)) audpp_msg_spa_bands;
+
+/*
+ * MSG to communicate the PCM I/O buffer status to ARM
+ */
+#define AUDPP_MSG_HOST_PCM_INTF_MSG 0x0003
+#define AUDPP_MSG_HOST_PCM_INTF_MSG_LEN \
+ sizeof(audpp_msg_host_pcm_intf_msg)
+
+#define AUDPP_MSG_HOSTPCM_ID_TX_ARM 0x0000
+#define AUDPP_MSG_HOSTPCM_ID_ARM_TX 0x0001
+#define AUDPP_MSG_HOSTPCM_ID_RX_ARM 0x0002
+#define AUDPP_MSG_HOSTPCM_ID_ARM_RX 0x0003
+
+#define AUDPP_MSG_SAMP_FREQ_INDX_96000 0x0000
+#define AUDPP_MSG_SAMP_FREQ_INDX_88200 0x0001
+#define AUDPP_MSG_SAMP_FREQ_INDX_64000 0x0002
+#define AUDPP_MSG_SAMP_FREQ_INDX_48000 0x0003
+#define AUDPP_MSG_SAMP_FREQ_INDX_44100 0x0004
+#define AUDPP_MSG_SAMP_FREQ_INDX_32000 0x0005
+#define AUDPP_MSG_SAMP_FREQ_INDX_24000 0x0006
+#define AUDPP_MSG_SAMP_FREQ_INDX_22050 0x0007
+#define AUDPP_MSG_SAMP_FREQ_INDX_16000 0x0008
+#define AUDPP_MSG_SAMP_FREQ_INDX_12000 0x0009
+#define AUDPP_MSG_SAMP_FREQ_INDX_11025 0x000A
+#define AUDPP_MSG_SAMP_FREQ_INDX_8000 0x000B
+
+#define AUDPP_MSG_CHANNEL_MODE_MONO 0x0001
+#define AUDPP_MSG_CHANNEL_MODE_STEREO 0x0002
+
+typedef struct{
+ unsigned short obj_num;
+ unsigned short numbers_of_samples;
+ unsigned short host_pcm_id;
+ unsigned short buf_indx;
+ unsigned short samp_freq_indx;
+ unsigned short channel_mode;
+} __attribute__((packed)) audpp_msg_host_pcm_intf_msg;
+
+
+/*
+ * MSG to communicate 3D position of the source and listener , source volume
+ * source rolloff, source orientation
+ */
+
+#define AUDPP_MSG_QAFX_POS 0x0004
+#define AUDPP_MSG_QAFX_POS_LEN \
+ sizeof(audpp_msg_qafx_pos)
+
+typedef struct {
+ unsigned short current_object;
+ unsigned short x_pos_lis_msw;
+ unsigned short x_pos_lis_lsw;
+ unsigned short y_pos_lis_msw;
+ unsigned short y_pos_lis_lsw;
+ unsigned short z_pos_lis_msw;
+ unsigned short z_pos_lis_lsw;
+ unsigned short x_fwd_msw;
+ unsigned short x_fwd_lsw;
+ unsigned short y_fwd_msw;
+ unsigned short y_fwd_lsw;
+ unsigned short z_fwd_msw;
+ unsigned short z_fwd_lsw;
+ unsigned short x_up_msw;
+ unsigned short x_up_lsw;
+ unsigned short y_up_msw;
+ unsigned short y_up_lsw;
+ unsigned short z_up_msw;
+ unsigned short z_up_lsw;
+ unsigned short x_vel_lis_msw;
+ unsigned short x_vel_lis_lsw;
+ unsigned short y_vel_lis_msw;
+ unsigned short y_vel_lis_lsw;
+ unsigned short z_vel_lis_msw;
+ unsigned short z_vel_lis_lsw;
+ unsigned short threed_enable_flag;
+ unsigned short volume;
+ unsigned short x_pos_source_msw;
+ unsigned short x_pos_source_lsw;
+ unsigned short y_pos_source_msw;
+ unsigned short y_pos_source_lsw;
+ unsigned short z_pos_source_msw;
+ unsigned short z_pos_source_lsw;
+ unsigned short max_dist_0_msw;
+ unsigned short max_dist_0_lsw;
+ unsigned short min_dist_0_msw;
+ unsigned short min_dist_0_lsw;
+ unsigned short roll_off_factor;
+ unsigned short mute_after_max_flag;
+ unsigned short x_vel_source_msw;
+ unsigned short x_vel_source_lsw;
+ unsigned short y_vel_source_msw;
+ unsigned short y_vel_source_lsw;
+ unsigned short z_vel_source_msw;
+ unsigned short z_vel_source_lsw;
+} __attribute__((packed)) audpp_msg_qafx_pos;
+
+/*
+ * MSG to provide AVSYNC feedback from DSP to ARM
+ */
+
+#define AUDPP_MSG_AVSYNC_MSG 0x0005
+#define AUDPP_MSG_AVSYNC_MSG_LEN \
+ sizeof(audpp_msg_avsync_msg)
+
+typedef struct {
+ unsigned short active_flag;
+ unsigned short num_samples_counter0_HSW;
+ unsigned short num_samples_counter0_MSW;
+ unsigned short num_samples_counter0_LSW;
+ unsigned short num_bytes_counter0_HSW;
+ unsigned short num_bytes_counter0_MSW;
+ unsigned short num_bytes_counter0_LSW;
+ unsigned short samp_freq_obj_0;
+ unsigned short samp_freq_obj_1;
+ unsigned short samp_freq_obj_2;
+ unsigned short samp_freq_obj_3;
+ unsigned short samp_freq_obj_4;
+ unsigned short samp_freq_obj_5;
+ unsigned short samp_freq_obj_6;
+ unsigned short samp_freq_obj_7;
+ unsigned short samp_freq_obj_8;
+ unsigned short samp_freq_obj_9;
+ unsigned short samp_freq_obj_10;
+ unsigned short samp_freq_obj_11;
+ unsigned short samp_freq_obj_12;
+ unsigned short samp_freq_obj_13;
+ unsigned short samp_freq_obj_14;
+ unsigned short samp_freq_obj_15;
+ unsigned short num_samples_counter4_HSW;
+ unsigned short num_samples_counter4_MSW;
+ unsigned short num_samples_counter4_LSW;
+ unsigned short num_bytes_counter4_HSW;
+ unsigned short num_bytes_counter4_MSW;
+ unsigned short num_bytes_counter4_LSW;
+} __attribute__((packed)) audpp_msg_avsync_msg;
+
+/*
+ * MSG to provide PCM DMA Missed feedback from the DSP to ARM
+ */
+
+#define AUDPP_MSG_PCMDMAMISSED 0x0006
+#define AUDPP_MSG_PCMDMAMISSED_LEN \
+ sizeof(audpp_msg_pcmdmamissed);
+
+typedef struct{
+ /*
+ ** Bit 0 0 = PCM DMA not missed for object 0
+ ** 1 = PCM DMA missed for object0
+ ** Bit 1 0 = PCM DMA not missed for object 1
+ ** 1 = PCM DMA missed for object1
+ ** Bit 2 0 = PCM DMA not missed for object 2
+ ** 1 = PCM DMA missed for object2
+ ** Bit 3 0 = PCM DMA not missed for object 3
+ ** 1 = PCM DMA missed for object3
+ ** Bit 4 0 = PCM DMA not missed for object 4
+ ** 1 = PCM DMA missed for object4
+ */
+ unsigned short pcmdmamissed;
+} __attribute__((packed)) audpp_msg_pcmdmamissed;
+
+/*
+ * MSG to AUDPP enable or disable feedback form DSP to ARM
+ */
+
+#define AUDPP_MSG_CFG_MSG 0x0007
+#define AUDPP_MSG_CFG_MSG_LEN \
+ sizeof(audpp_msg_cfg_msg)
+
+#define AUDPP_MSG_ENA_ENA 0xFFFF
+#define AUDPP_MSG_ENA_DIS 0x0000
+
+typedef struct{
+ /* Enabled - 0xffff
+ ** Disabled - 0
+ */
+ unsigned short enabled;
+} __attribute__((packed)) audpp_msg_cfg_msg;
+
+/*
+ * MSG to communicate the reverb per object volume
+ */
+
+#define AUDPP_MSG_QREVERB_VOLUME 0x0008
+#define AUDPP_MSG_QREVERB_VOLUME_LEN \
+ sizeof(audpp_msg_qreverb_volume)
+
+
+typedef struct {
+ unsigned short obj_0_gain;
+ unsigned short obj_1_gain;
+ unsigned short obj_2_gain;
+ unsigned short obj_3_gain;
+ unsigned short obj_4_gain;
+ unsigned short hpcm_obj_volume;
+} __attribute__((packed)) audpp_msg_qreverb_volume;
+
+#define AUDPP_MSG_ROUTING_ACK 0x0009
+#define AUDPP_MSG_ROUTING_ACK_LEN \
+ sizeof(struct audpp_msg_routing_ack)
+
+struct audpp_msg_routing_ack {
+ unsigned short dec_id;
+ unsigned short routing_mode;
+} __attribute__((packed));
+
+#define AUDPP_MSG_FLUSH_ACK 0x000A
+
+#endif /* QDSP5AUDPPMSG_H */
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5audpreproccmdi.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5audpreproccmdi.h
new file mode 100644
index 00000000000..06d33d57158
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5audpreproccmdi.h
@@ -0,0 +1,256 @@
+#ifndef QDSP5AUDPREPROCCMDI_H
+#define QDSP5AUDPREPROCCMDI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+ A U D I O P R E P R O C E S S I N G I N T E R N A L C O M M A N D S
+
+GENERAL DESCRIPTION
+ This file contains defintions of format blocks of commands
+ that are accepted by AUDPREPROC Task
+
+REFERENCES
+ None
+
+EXTERNALIZED FUNCTIONS
+ None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+This software is licensed under the terms of the GNU General Public
+License version 2, as published by the Free Software Foundation, and
+may be copied, distributed, and modified under those terms.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+ EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/Audio/drivers/QDSP5Driver/QDSP5Interface/main/latest/qdsp5audpreproccmdi.h#2 $
+
+===========================================================================*/
+
+/*
+ * AUDIOPREPROC COMMANDS:
+ * ARM uses uPAudPreProcCmdQueue to communicate with AUDPREPROCTASK
+ * Location : MEMB
+ * Buffer size : 51
+ * Number of buffers in a queue : 3
+ */
+
+/*
+ * Command to configure the parameters of AGC
+ */
+
+#define AUDPREPROC_CMD_CFG_AGC_PARAMS 0x0000
+#define AUDPREPROC_CMD_CFG_AGC_PARAMS_LEN \
+ sizeof(audpreproc_cmd_cfg_agc_params)
+
+#define AUDPREPROC_CMD_TX_AGC_PARAM_MASK_COMP_SLOPE 0x0009
+#define AUDPREPROC_CMD_TX_AGC_PARAM_MASK_COMP_TH 0x000A
+#define AUDPREPROC_CMD_TX_AGC_PARAM_MASK_EXP_SLOPE 0x000B
+#define AUDPREPROC_CMD_TX_AGC_PARAM_MASK_EXP_TH 0x000C
+#define AUDPREPROC_CMD_TX_AGC_PARAM_MASK_COMP_AIG_FLAG 0x000D
+#define AUDPREPROC_CMD_TX_AGC_PARAM_MASK_COMP_STATIC_GAIN 0x000E
+#define AUDPREPROC_CMD_TX_AGC_PARAM_MASK_TX_AGC_ENA_FLAG 0x000F
+
+#define AUDPREPROC_CMD_TX_AGC_ENA_FLAG_ENA -1
+#define AUDPREPROC_CMD_TX_AGC_ENA_FLAG_DIS 0x0000
+
+#define AUDPREPROC_CMD_ADP_GAIN_FLAG_ENA_ADP_GAIN -1
+#define AUDPREPROC_CMD_ADP_GAIN_FLAG_ENA_STATIC_GAIN 0x0000
+
+#define AUDPREPROC_CMD_PARAM_MASK_RMS_TAY 0x0004
+#define AUDPREPROC_CMD_PARAM_MASK_RELEASEK 0x0005
+#define AUDPREPROC_CMD_PARAM_MASK_DELAY 0x0006
+#define AUDPREPROC_CMD_PARAM_MASK_ATTACKK 0x0007
+#define AUDPREPROC_CMD_PARAM_MASK_LEAKRATE_SLOW 0x0008
+#define AUDPREPROC_CMD_PARAM_MASK_LEAKRATE_FAST 0x0009
+#define AUDPREPROC_CMD_PARAM_MASK_AIG_RELEASEK 0x000A
+#define AUDPREPROC_CMD_PARAM_MASK_AIG_MIN 0x000B
+#define AUDPREPROC_CMD_PARAM_MASK_AIG_MAX 0x000C
+#define AUDPREPROC_CMD_PARAM_MASK_LEAK_UP 0x000D
+#define AUDPREPROC_CMD_PARAM_MASK_LEAK_DOWN 0x000E
+#define AUDPREPROC_CMD_PARAM_MASK_AIG_ATTACKK 0x000F
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short tx_agc_param_mask;
+ unsigned short tx_agc_enable_flag;
+ unsigned short static_gain;
+ signed short adaptive_gain_flag;
+ unsigned short expander_th;
+ unsigned short expander_slope;
+ unsigned short compressor_th;
+ unsigned short compressor_slope;
+ unsigned short param_mask;
+ unsigned short aig_attackk;
+ unsigned short aig_leak_down;
+ unsigned short aig_leak_up;
+ unsigned short aig_max;
+ unsigned short aig_min;
+ unsigned short aig_releasek;
+ unsigned short aig_leakrate_fast;
+ unsigned short aig_leakrate_slow;
+ unsigned short attackk_msw;
+ unsigned short attackk_lsw;
+ unsigned short delay;
+ unsigned short releasek_msw;
+ unsigned short releasek_lsw;
+ unsigned short rms_tav;
+} __attribute__((packed)) audpreproc_cmd_cfg_agc_params;
+
+
+/*
+ * Command to configure the params of Advanved AGC
+ */
+
+#define AUDPREPROC_CMD_CFG_AGC_PARAMS_2 0x0001
+#define AUDPREPROC_CMD_CFG_AGC_PARAMS_2_LEN \
+ sizeof(audpreproc_cmd_cfg_agc_params_2)
+
+#define AUDPREPROC_CMD_2_TX_AGC_ENA_FLAG_ENA -1;
+#define AUDPREPROC_CMD_2_TX_AGC_ENA_FLAG_DIS 0x0000;
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short agc_param_mask;
+ signed short tx_agc_enable_flag;
+ unsigned short comp_static_gain;
+ unsigned short exp_th;
+ unsigned short exp_slope;
+ unsigned short comp_th;
+ unsigned short comp_slope;
+ unsigned short comp_rms_tav;
+ unsigned short comp_samp_mask;
+ unsigned short comp_attackk_msw;
+ unsigned short comp_attackk_lsw;
+ unsigned short comp_releasek_msw;
+ unsigned short comp_releasek_lsw;
+ unsigned short comp_delay;
+ unsigned short comp_makeup_gain;
+} __attribute__((packed)) audpreproc_cmd_cfg_agc_params_2;
+
+/*
+ * Command to configure params for ns
+ */
+
+#define AUDPREPROC_CMD_CFG_NS_PARAMS 0x0002
+#define AUDPREPROC_CMD_CFG_NS_PARAMS_LEN \
+ sizeof(audpreproc_cmd_cfg_ns_params)
+
+#define AUDPREPROC_CMD_EC_MODE_NEW_NLMS_ENA 0x0001
+#define AUDPREPROC_CMD_EC_MODE_NEW_NLMS_DIS 0x0000
+#define AUDPREPROC_CMD_EC_MODE_NEW_DES_ENA 0x0002
+#define AUDPREPROC_CMD_EC_MODE_NEW_DES_DIS 0x0000
+#define AUDPREPROC_CMD_EC_MODE_NEW_NS_ENA 0x0004
+#define AUDPREPROC_CMD_EC_MODE_NEW_NS_DIS 0x0000
+#define AUDPREPROC_CMD_EC_MODE_NEW_CNI_ENA 0x0008
+#define AUDPREPROC_CMD_EC_MODE_NEW_CNI_DIS 0x0000
+
+#define AUDPREPROC_CMD_EC_MODE_NEW_NLES_ENA 0x0010
+#define AUDPREPROC_CMD_EC_MODE_NEW_NLES_DIS 0x0000
+#define AUDPREPROC_CMD_EC_MODE_NEW_HB_ENA 0x0020
+#define AUDPREPROC_CMD_EC_MODE_NEW_HB_DIS 0x0000
+#define AUDPREPROC_CMD_EC_MODE_NEW_VA_ENA 0x0040
+#define AUDPREPROC_CMD_EC_MODE_NEW_VA_DIS 0x0000
+#define AUDPREPROC_CMD_EC_MODE_NEW_PCD_ENA 0x0080
+#define AUDPREPROC_CMD_EC_MODE_NEW_PCD_DIS 0x0000
+#define AUDPREPROC_CMD_EC_MODE_NEW_FEHI_ENA 0x0100
+#define AUDPREPROC_CMD_EC_MODE_NEW_FEHI_DIS 0x0000
+#define AUDPREPROC_CMD_EC_MODE_NEW_NEHI_ENA 0x0200
+#define AUDPREPROC_CMD_EC_MODE_NEW_NEHI_DIS 0x0000
+#define AUDPREPROC_CMD_EC_MODE_NEW_NLPP_ENA 0x0400
+#define AUDPREPROC_CMD_EC_MODE_NEW_NLPP_DIS 0x0000
+#define AUDPREPROC_CMD_EC_MODE_NEW_FNE_ENA 0x0800
+#define AUDPREPROC_CMD_EC_MODE_NEW_FNE_DIS 0x0000
+#define AUDPREPROC_CMD_EC_MODE_NEW_PRENLMS_ENA 0x1000
+#define AUDPREPROC_CMD_EC_MODE_NEW_PRENLMS_DIS 0x0000
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short ec_mode_new;
+ unsigned short dens_gamma_n;
+ unsigned short dens_nfe_block_size;
+ unsigned short dens_limit_ns;
+ unsigned short dens_limit_ns_d;
+ unsigned short wb_gamma_e;
+ unsigned short wb_gamma_n;
+} __attribute__((packed)) audpreproc_cmd_cfg_ns_params;
+
+/*
+ * Command to configure parameters for IIR tuning filter
+ */
+
+#define AUDPREPROC_CMD_CFG_IIR_TUNING_FILTER_PARAMS 0x0003
+#define AUDPREPROC_CMD_CFG_IIR_TUNING_FILTER_PARAMS_LEN \
+ sizeof(audpreproc_cmd_cfg_iir_tuning_filter_params)
+
+#define AUDPREPROC_CMD_IIR_ACTIVE_FLAG_DIS 0x0000
+#define AUDPREPROC_CMD_IIR_ACTIVE_FLAG_ENA 0x0001
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short active_flag;
+ unsigned short num_bands;
+ unsigned short numerator_coeff_b0_filter0_lsw;
+ unsigned short numerator_coeff_b0_filter0_msw;
+ unsigned short numerator_coeff_b1_filter0_lsw;
+ unsigned short numerator_coeff_b1_filter0_msw;
+ unsigned short numerator_coeff_b2_filter0_lsw;
+ unsigned short numerator_coeff_b2_filter0_msw;
+ unsigned short numerator_coeff_b0_filter1_lsw;
+ unsigned short numerator_coeff_b0_filter1_msw;
+ unsigned short numerator_coeff_b1_filter1_lsw;
+ unsigned short numerator_coeff_b1_filter1_msw;
+ unsigned short numerator_coeff_b2_filter1_lsw;
+ unsigned short numerator_coeff_b2_filter1_msw;
+ unsigned short numerator_coeff_b0_filter2_lsw;
+ unsigned short numerator_coeff_b0_filter2_msw;
+ unsigned short numerator_coeff_b1_filter2_lsw;
+ unsigned short numerator_coeff_b1_filter2_msw;
+ unsigned short numerator_coeff_b2_filter2_lsw;
+ unsigned short numerator_coeff_b2_filter2_msw;
+ unsigned short numerator_coeff_b0_filter3_lsw;
+ unsigned short numerator_coeff_b0_filter3_msw;
+ unsigned short numerator_coeff_b1_filter3_lsw;
+ unsigned short numerator_coeff_b1_filter3_msw;
+ unsigned short numerator_coeff_b2_filter3_lsw;
+ unsigned short numerator_coeff_b2_filter3_msw;
+ unsigned short denominator_coeff_a0_filter0_lsw;
+ unsigned short denominator_coeff_a0_filter0_msw;
+ unsigned short denominator_coeff_a1_filter0_lsw;
+ unsigned short denominator_coeff_a1_filter0_msw;
+ unsigned short denominator_coeff_a0_filter1_lsw;
+ unsigned short denominator_coeff_a0_filter1_msw;
+ unsigned short denominator_coeff_a1_filter1_lsw;
+ unsigned short denominator_coeff_a1_filter1_msw;
+ unsigned short denominator_coeff_a0_filter2_lsw;
+ unsigned short denominator_coeff_a0_filter2_msw;
+ unsigned short denominator_coeff_a1_filter2_lsw;
+ unsigned short denominator_coeff_a1_filter2_msw;
+ unsigned short denominator_coeff_a0_filter3_lsw;
+ unsigned short denominator_coeff_a0_filter3_msw;
+ unsigned short denominator_coeff_a1_filter3_lsw;
+ unsigned short denominator_coeff_a1_filter3_msw;
+
+ unsigned short shift_factor_filter0;
+ unsigned short shift_factor_filter1;
+ unsigned short shift_factor_filter2;
+ unsigned short shift_factor_filter3;
+
+ unsigned short channel_selected0;
+ unsigned short channel_selected1;
+ unsigned short channel_selected2;
+ unsigned short channel_selected3;
+} __attribute__((packed))audpreproc_cmd_cfg_iir_tuning_filter_params;
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5audpreprocmsg.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5audpreprocmsg.h
new file mode 100644
index 00000000000..f40e41e7673
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5audpreprocmsg.h
@@ -0,0 +1,85 @@
+#ifndef QDSP5AUDPREPROCMSG_H
+#define QDSP5AUDPREPROCMSG_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+ A U D I O P R E P R O C E S S I N G M E S S A G E S
+
+GENERAL DESCRIPTION
+ This file contains defintions of format blocks of messages
+ that are rcvd by AUDPREPROC Task
+
+REFERENCES
+ None
+
+EXTERNALIZED FUNCTIONS
+ None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+This software is licensed under the terms of the GNU General Public
+License version 2, as published by the Free Software Foundation, and
+may be copied, distributed, and modified under those terms.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+ EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+ $Header: //source/qcom/qct/multimedia2/Audio/drivers/QDSP5Driver/QDSP5Interface/main/latest/qdsp5audpreprocmsg.h#3 $
+
+===========================================================================*/
+
+/*
+ * ADSPREPROCTASK Messages
+ * AUDPREPROCTASK uses audPreProcUpRlist to communicate with ARM
+ * Location : MEMA
+ * Message Length : 2
+ */
+
+/*
+ * Message to indicate particular feature has been enabled or disabled
+ */
+
+
+#define AUDPREPROC_MSG_CMD_CFG_DONE_MSG 0x0000
+#define AUDPREPROC_MSG_CMD_CFG_DONE_MSG_LEN \
+ sizeof(audpreproc_msg_cmd_cfg_done_msg)
+
+#define AUDPREPROC_MSG_TYPE_AGC 0x0000
+#define AUDPREPROC_MSG_TYPE_NOISE_REDUCTION 0x0001
+#define AUDPREPROC_MSG_TYPE_IIR_FILTER 0x0002
+
+
+#define AUDPREPROC_MSG_STATUS_FLAG_ENA -1
+#define AUDPREPROC_MSG_STATUS_FLAG_DIS 0x0000
+
+typedef struct {
+ unsigned short type;
+ signed short status_flag;
+} __attribute__((packed)) audpreproc_msg_cmd_cfg_done_msg;
+
+
+/*
+ * Message to indicate particular feature has selected for wrong samp freq
+ */
+
+#define AUDPREPROC_MSG_ERROR_MSG_ID 0x0001
+#define AUDPREPROC_MSG_ERROR_MSG_ID_LEN \
+ sizeof(audpreproc_msg_error_msg_id)
+
+#define AUDPREPROC_MSG_ERR_INDEX_NS 0x0000
+
+typedef struct {
+ unsigned short err_index;
+} __attribute__((packed)) audpreproc_msg_error_msg_id;
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5audreccmdi.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5audreccmdi.h
new file mode 100644
index 00000000000..d03ee024ae9
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5audreccmdi.h
@@ -0,0 +1,176 @@
+#ifndef QDSP5AUDRECCMDI_H
+#define QDSP5AUDRECCMDI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+ A U D I O R E C O R D I N T E R N A L C O M M A N D S
+
+GENERAL DESCRIPTION
+ This file contains defintions of format blocks of commands
+ that are accepted by AUDREC Task
+
+REFERENCES
+ None
+
+EXTERNALIZED FUNCTIONS
+ None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+This software is licensed under the terms of the GNU General Public
+License version 2, as published by the Free Software Foundation, and
+may be copied, distributed, and modified under those terms.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+
+/*===========================================================================
+
+ EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+ $Header: //source/qcom/qct/multimedia2/Audio/drivers/QDSP5Driver/QDSP5Interface/main/latest/qdsp5audreccmdi.h#3 $
+
+============================================================================*/
+
+/*
+ * AUDRECTASK COMMANDS
+ * ARM uses 2 queues to communicate with the AUDRECTASK
+ * 1.uPAudRecCmdQueue
+ * Location :MEMC
+ * Buffer Size : 8
+ * No of Buffers in a queue : 3
+ * 2.audRecUpBitStreamQueue
+ * Location : MEMC
+ * Buffer Size : 4
+ * No of buffers in a queue : 2
+ */
+
+/*
+ * Commands on uPAudRecCmdQueue
+ */
+
+/*
+ * Command to initiate and terminate the audio recording section
+ */
+
+#define AUDREC_CMD_CFG 0x0000
+#define AUDREC_CMD_CFG_LEN sizeof(audrec_cmd_cfg)
+
+#define AUDREC_CMD_TYPE_0_INDEX_WAV 0x0000
+#define AUDREC_CMD_TYPE_0_INDEX_AAC 0x0001
+
+#define AUDREC_CMD_TYPE_0_ENA 0x4000
+#define AUDREC_CMD_TYPE_0_DIS 0x0000
+
+#define AUDREC_CMD_TYPE_0_NOUPDATE 0x0000
+#define AUDREC_CMD_TYPE_0_UPDATE 0x8000
+
+#define AUDREC_CMD_TYPE_1_INDEX_SBC 0x0002
+
+#define AUDREC_CMD_TYPE_1_ENA 0x4000
+#define AUDREC_CMD_TYPE_1_DIS 0x0000
+
+#define AUDREC_CMD_TYPE_1_NOUPDATE 0x0000
+#define AUDREC_CMD_TYPE_1_UPDATE 0x8000
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short type_0;
+ unsigned short type_1;
+} __attribute__((packed)) audrec_cmd_cfg;
+
+
+/*
+ * Command to configure the recording parameters for RecType0(AAC/WAV) encoder
+ */
+
+#define AUDREC_CMD_AREC0PARAM_CFG 0x0001
+#define AUDREC_CMD_AREC0PARAM_CFG_LEN \
+ sizeof(audrec_cmd_arec0param_cfg)
+
+#define AUDREC_CMD_SAMP_RATE_INDX_8000 0x000B
+#define AUDREC_CMD_SAMP_RATE_INDX_11025 0x000A
+#define AUDREC_CMD_SAMP_RATE_INDX_12000 0x0009
+#define AUDREC_CMD_SAMP_RATE_INDX_16000 0x0008
+#define AUDREC_CMD_SAMP_RATE_INDX_22050 0x0007
+#define AUDREC_CMD_SAMP_RATE_INDX_24000 0x0006
+#define AUDREC_CMD_SAMP_RATE_INDX_32000 0x0005
+#define AUDREC_CMD_SAMP_RATE_INDX_44100 0x0004
+#define AUDREC_CMD_SAMP_RATE_INDX_48000 0x0003
+
+#define AUDREC_CMD_STEREO_MODE_MONO 0x0000
+#define AUDREC_CMD_STEREO_MODE_STEREO 0x0001
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short ptr_to_extpkt_buffer_msw;
+ unsigned short ptr_to_extpkt_buffer_lsw;
+ unsigned short buf_len;
+ unsigned short samp_rate_index;
+ unsigned short stereo_mode;
+ unsigned short rec_quality;
+} __attribute__((packed)) audrec_cmd_arec0param_cfg;
+
+/*
+ * Command to configure the recording parameters for RecType1(SBC) encoder
+ */
+
+#define AUDREC_CMD_AREC1PARAM_CFG 0x0002
+#define AUDREC_CMD_AREC1PARAM_CFG_LEN \
+ sizeof(audrec_cmd_arec1param_cfg)
+
+#define AUDREC_CMD_PARAM_BUF_BLOCKS_4 0x0000
+#define AUDREC_CMD_PARAM_BUF_BLOCKS_8 0x0001
+#define AUDREC_CMD_PARAM_BUF_BLOCKS_12 0x0002
+#define AUDREC_CMD_PARAM_BUF_BLOCKS_16 0x0003
+
+#define AUDREC_CMD_PARAM_BUF_SUB_BANDS_8 0x0010
+#define AUDREC_CMD_PARAM_BUF_MODE_MONO 0x0000
+#define AUDREC_CMD_PARAM_BUF_MODE_DUAL 0x0040
+#define AUDREC_CMD_PARAM_BUF_MODE_STEREO 0x0050
+#define AUDREC_CMD_PARAM_BUF_MODE_JSTEREO 0x0060
+#define AUDREC_CMD_PARAM_BUF_LOUDNESS 0x0000
+#define AUDREC_CMD_PARAM_BUF_SNR 0x0100
+#define AUDREC_CMD_PARAM_BUF_BASIC_VER 0x0000
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short ptr_to_extpkt_buffer_msw;
+ unsigned short ptr_to_extpkt_buffer_lsw;
+ unsigned short buf_len;
+ unsigned short param_buf;
+ unsigned short bit_rate_0;
+ unsigned short bit_rate_1;
+} __attribute__((packed)) audrec_cmd_arec1param_cfg;
+
+
+/*
+ * Commands on audRecUpBitStreamQueue
+ */
+
+/*
+ * Command to indicate the current packet read count
+ */
+
+#define AUDREC_CMD_PACKET_EXT_PTR 0x0000
+#define AUDREC_CMD_PACKET_EXT_PTR_LEN \
+ sizeof(audrec_cmd_packet_ext_ptr)
+
+#define AUDREC_CMD_TYPE_0 0x0000
+#define AUDREC_CMD_TYPE_1 0x0001
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short type;
+ unsigned short curr_rec_count_msw;
+ unsigned short curr_rec_count_lsw;
+} __attribute__((packed)) audrec_cmd_packet_ext_ptr;
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5audrecmsg.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5audrecmsg.h
new file mode 100644
index 00000000000..bb6eb5093cf
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5audrecmsg.h
@@ -0,0 +1,127 @@
+#ifndef QDSP5AUDRECMSGI_H
+#define QDSP5AUDRECMSGI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+ A U D I O R E C O R D M E S S A G E S
+
+GENERAL DESCRIPTION
+ This file contains defintions of format blocks of messages
+ that are sent by AUDREC Task
+
+REFERENCES
+ None
+
+EXTERNALIZED FUNCTIONS
+ None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+This software is licensed under the terms of the GNU General Public
+License version 2, as published by the Free Software Foundation, and
+may be copied, distributed, and modified under those terms.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+
+/*===========================================================================
+
+ EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+ $Header: //source/qcom/qct/multimedia2/Audio/drivers/QDSP5Driver/QDSP5Interface/main/latest/qdsp5audrecmsg.h#3 $
+
+============================================================================*/
+
+/*
+ * AUDRECTASK MESSAGES
+ * AUDRECTASK uses audRecUpRlist to communicate with ARM
+ * Location : MEMC
+ * Buffer size : 4
+ * No of buffers in a queue : 2
+ */
+
+/*
+ * Message to notify that config command is done
+ */
+
+#define AUDREC_MSG_CMD_CFG_DONE_MSG 0x0002
+#define AUDREC_MSG_CMD_CFG_DONE_MSG_LEN \
+ sizeof(audrec_msg_cmd_cfg_done_msg)
+
+
+#define AUDREC_MSG_CFG_DONE_TYPE_0_ENA 0x4000
+#define AUDREC_MSG_CFG_DONE_TYPE_0_DIS 0x0000
+
+#define AUDREC_MSG_CFG_DONE_TYPE_0_NO_UPDATE 0x0000
+#define AUDREC_MSG_CFG_DONE_TYPE_0_UPDATE 0x8000
+
+#define AUDREC_MSG_CFG_DONE_TYPE_1_ENA 0x4000
+#define AUDREC_MSG_CFG_DONE_TYPE_1_DIS 0x0000
+
+#define AUDREC_MSG_CFG_DONE_TYPE_1_NO_UPDATE 0x0000
+#define AUDREC_MSG_CFG_DONE_TYPE_1_UPDATE 0x8000
+
+typedef struct {
+ unsigned short type_0;
+ unsigned short type_1;
+} __attribute__((packed))audrec_msg_cmd_cfg_done_msg;
+
+
+/*
+ * Message to notify arec0/1 cfg done and recording params revd by task
+ */
+
+#define AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG 0x0003
+#define AUDREC_MSG_CMD_AREC_PARAM_CFG_DONE_MSG_LEN \
+ sizeof(audrec_msg_cmd_arec_param_cfg_done_msg)
+
+#define AUDREC_MSG_AREC_PARAM_TYPE_0 0x0000
+#define AUDREC_MSG_AREC_PARAM_TYPE_1 0x0001
+
+typedef struct {
+ unsigned short type;
+} __attribute__((packed))audrec_msg_cmd_arec_param_cfg_done_msg;
+
+
+/*
+ * Message to notify no more buffers are available in ext mem to DME
+ */
+
+#define AUDREC_MSG_FATAL_ERR_MSG 0x0004
+#define AUDREC_MSG_FATAL_ERR_MSG_LEN \
+ sizeof(audrec_msg_fatal_err_msg)
+
+#define AUDREC_MSG_FATAL_ERR_TYPE_0 0x0000
+#define AUDREC_MSG_FATAL_ERR_TYPE_1 0x0001
+
+typedef struct {
+ unsigned short type;
+} __attribute__((packed))audrec_msg_fatal_err_msg;
+
+/*
+ * Message to notify DME deliverd the encoded pkt to ext pkt buffer
+ */
+
+#define AUDREC_MSG_PACKET_READY_MSG 0x0005
+#define AUDREC_MSG_PACKET_READY_MSG_LEN \
+ sizeof(audrec_msg_packet_ready_msg)
+
+#define AUDREC_MSG_PACKET_READY_TYPE_0 0x0000
+#define AUDREC_MSG_PACKET_READY_TYPE_1 0x0001
+
+typedef struct {
+ unsigned short type;
+ unsigned short pkt_counter_msw;
+ unsigned short pkt_counter_lsw;
+ unsigned short pkt_read_cnt_msw;
+ unsigned short pkt_read_cnt_lsw;
+} __attribute__((packed))audrec_msg_packet_ready_msg;
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5jpegcmdi.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5jpegcmdi.h
new file mode 100644
index 00000000000..574ad6bbcad
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5jpegcmdi.h
@@ -0,0 +1,376 @@
+#ifndef QDSP5VIDJPEGCMDI_H
+#define QDSP5VIDJPEGCMDI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+ J P E G I N T E R N A L C O M M A N D S
+
+GENERAL DESCRIPTION
+ This file contains defintions of format blocks of commands
+ that are accepted by JPEG Task
+
+REFERENCES
+ None
+
+EXTERNALIZED FUNCTIONS
+ None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+This software is licensed under the terms of the GNU General Public
+License version 2, as published by the Free Software Foundation, and
+may be copied, distributed, and modified under those terms.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+ EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/AdspSvc/7XXX/qdsp5cmd/video/qdsp5jpegcmdi.h#2 $ $DateTime: 2008/07/30 10:50:23 $ $Author: pavanr $
+Revision History:
+when who what, where, why
+-------- --- ----------------------------------------------------------
+06/09/08 sv initial version
+===========================================================================*/
+
+/*
+ * ARM to JPEG configuration commands are passed through the
+ * uPJpegCfgCmdQueue
+ */
+
+/*
+ * Command to configure JPEG Encoder
+ */
+
+#define JPEG_CMD_ENC_CFG 0x0000
+#define JPEG_CMD_ENC_CFG_LEN sizeof(jpeg_cmd_enc_cfg)
+
+#define JPEG_CMD_ENC_PROCESS_CFG_OP_ROTATION_0 0x0000
+#define JPEG_CMD_ENC_PROCESS_CFG_OP_ROTATION_90 0x0100
+#define JPEG_CMD_ENC_PROCESS_CFG_OP_ROTATION_180 0x0200
+#define JPEG_CMD_ENC_PROCESS_CFG_OP_ROTATION_270 0x0300
+#define JPEG_CMD_ENC_PROCESS_CFG_IP_DATA_FORMAT_M 0x0003
+#define JPEG_CMD_ENC_PROCESS_CFG_IP_DATA_FORMAT_H2V2 0x0000
+#define JPEG_CMD_ENC_PROCESS_CFG_IP_DATA_FORMAT_H2V1 0x0001
+#define JPEG_CMD_ENC_PROCESS_CFG_IP_DATA_FORMAT_H1V2 0x0002
+
+#define JPEG_CMD_IP_SIZE_CFG_LUMA_HEIGHT_M 0x0000FFFF
+#define JPEG_CMD_IP_SIZE_CFG_LUMA_WIDTH_M 0xFFFF0000
+#define JPEG_CMD_ENC_UPSAMP_IP_SIZE_CFG_ENA 0x0001
+#define JPEG_CMD_ENC_UPSAMP_IP_SIZE_CFG_DIS 0x0000
+
+#define JPEG_CMD_FRAG_SIZE_LUMA_HEIGHT_M 0xFFFF
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int process_cfg;
+ unsigned int ip_size_cfg;
+ unsigned int op_size_cfg;
+ unsigned int frag_cfg;
+ unsigned int frag_cfg_part[16];
+
+ unsigned int part_num;
+
+ unsigned int op_buf_0_cfg_part1;
+ unsigned int op_buf_0_cfg_part2;
+ unsigned int op_buf_1_cfg_part1;
+ unsigned int op_buf_1_cfg_part2;
+
+ unsigned int luma_qunt_table[32];
+ unsigned int chroma_qunt_table[32];
+
+ unsigned int upsamp_ip_size_cfg;
+ unsigned int upsamp_ip_frame_off;
+ unsigned int upsamp_pp_filter_coeff[64];
+} __attribute__((packed)) jpeg_cmd_enc_cfg;
+
+/*
+ * Command to configure JPEG Decoder
+ */
+
+#define JPEG_CMD_DEC_CFG 0x0001
+#define JPEG_CMD_DEC_CFG_LEN sizeof(jpeg_cmd_dec_cfg)
+
+#define JPEG_CMD_DEC_OP_DATA_FORMAT_M 0x0001
+#define JPEG_CMD_DEC_OP_DATA_FORMAT_H2V2 0x0000
+#define JPEG_CMD_DEC_OP_DATA_FORMAT_H2V1 0x0001
+
+#define JPEG_CMD_DEC_OP_DATA_FORMAT_SCALE_FACTOR_8 0x000000
+#define JPEG_CMD_DEC_OP_DATA_FORMAT_SCALE_FACTOR_4 0x010000
+#define JPEG_CMD_DEC_OP_DATA_FORMAT_SCALE_FACTOR_2 0x020000
+#define JPEG_CMD_DEC_OP_DATA_FORMAT_SCALE_FACTOR_1 0x030000
+
+#define JPEG_CMD_DEC_IP_STREAM_BUF_CFG_PART3_NOT_FINAL 0x0000
+#define JPEG_CMD_DEC_IP_STREAM_BUF_CFG_PART3_FINAL 0x0001
+
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int img_dimension_cfg;
+ unsigned int op_data_format;
+ unsigned int restart_interval;
+ unsigned int ip_buf_partition_num;
+ unsigned int ip_stream_buf_cfg_part1;
+ unsigned int ip_stream_buf_cfg_part2;
+ unsigned int ip_stream_buf_cfg_part3;
+ unsigned int op_stream_buf_0_cfg_part1;
+ unsigned int op_stream_buf_0_cfg_part2;
+ unsigned int op_stream_buf_0_cfg_part3;
+ unsigned int op_stream_buf_1_cfg_part1;
+ unsigned int op_stream_buf_1_cfg_part2;
+ unsigned int op_stream_buf_1_cfg_part3;
+ unsigned int luma_qunt_table_0_3;
+ unsigned int luma_qunt_table_4_7;
+ unsigned int luma_qunt_table_8_11;
+ unsigned int luma_qunt_table_12_15;
+ unsigned int luma_qunt_table_16_19;
+ unsigned int luma_qunt_table_20_23;
+ unsigned int luma_qunt_table_24_27;
+ unsigned int luma_qunt_table_28_31;
+ unsigned int luma_qunt_table_32_35;
+ unsigned int luma_qunt_table_36_39;
+ unsigned int luma_qunt_table_40_43;
+ unsigned int luma_qunt_table_44_47;
+ unsigned int luma_qunt_table_48_51;
+ unsigned int luma_qunt_table_52_55;
+ unsigned int luma_qunt_table_56_59;
+ unsigned int luma_qunt_table_60_63;
+ unsigned int chroma_qunt_table_0_3;
+ unsigned int chroma_qunt_table_4_7;
+ unsigned int chroma_qunt_table_8_11;
+ unsigned int chroma_qunt_table_12_15;
+ unsigned int chroma_qunt_table_16_19;
+ unsigned int chroma_qunt_table_20_23;
+ unsigned int chroma_qunt_table_24_27;
+ unsigned int chroma_qunt_table_28_31;
+ unsigned int chroma_qunt_table_32_35;
+ unsigned int chroma_qunt_table_36_39;
+ unsigned int chroma_qunt_table_40_43;
+ unsigned int chroma_qunt_table_44_47;
+ unsigned int chroma_qunt_table_48_51;
+ unsigned int chroma_qunt_table_52_55;
+ unsigned int chroma_qunt_table_56_59;
+ unsigned int chroma_qunt_table_60_63;
+ unsigned int luma_dc_hm_code_cnt_table_0_3;
+ unsigned int luma_dc_hm_code_cnt_table_4_7;
+ unsigned int luma_dc_hm_code_cnt_table_8_11;
+ unsigned int luma_dc_hm_code_cnt_table_12_15;
+ unsigned int luma_dc_hm_code_val_table_0_3;
+ unsigned int luma_dc_hm_code_val_table_4_7;
+ unsigned int luma_dc_hm_code_val_table_8_11;
+ unsigned int chroma_dc_hm_code_cnt_table_0_3;
+ unsigned int chroma_dc_hm_code_cnt_table_4_7;
+ unsigned int chroma_dc_hm_code_cnt_table_8_11;
+ unsigned int chroma_dc_hm_code_cnt_table_12_15;
+ unsigned int chroma_dc_hm_code_val_table_0_3;
+ unsigned int chroma_dc_hm_code_val_table_4_7;
+ unsigned int chroma_dc_hm_code_val_table_8_11;
+ unsigned int luma_ac_hm_code_cnt_table_0_3;
+ unsigned int luma_ac_hm_code_cnt_table_4_7;
+ unsigned int luma_ac_hm_code_cnt_table_8_11;
+ unsigned int luma_ac_hm_code_cnt_table_12_15;
+ unsigned int luma_ac_hm_code_val_table_0_3;
+ unsigned int luma_ac_hm_code_val_table_4_7;
+ unsigned int luma_ac_hm_code_val_table_8_11;
+ unsigned int luma_ac_hm_code_val_table_12_15;
+ unsigned int luma_ac_hm_code_val_table_16_19;
+ unsigned int luma_ac_hm_code_val_table_20_23;
+ unsigned int luma_ac_hm_code_val_table_24_27;
+ unsigned int luma_ac_hm_code_val_table_28_31;
+ unsigned int luma_ac_hm_code_val_table_32_35;
+ unsigned int luma_ac_hm_code_val_table_36_39;
+ unsigned int luma_ac_hm_code_val_table_40_43;
+ unsigned int luma_ac_hm_code_val_table_44_47;
+ unsigned int luma_ac_hm_code_val_table_48_51;
+ unsigned int luma_ac_hm_code_val_table_52_55;
+ unsigned int luma_ac_hm_code_val_table_56_59;
+ unsigned int luma_ac_hm_code_val_table_60_63;
+ unsigned int luma_ac_hm_code_val_table_64_67;
+ unsigned int luma_ac_hm_code_val_table_68_71;
+ unsigned int luma_ac_hm_code_val_table_72_75;
+ unsigned int luma_ac_hm_code_val_table_76_79;
+ unsigned int luma_ac_hm_code_val_table_80_83;
+ unsigned int luma_ac_hm_code_val_table_84_87;
+ unsigned int luma_ac_hm_code_val_table_88_91;
+ unsigned int luma_ac_hm_code_val_table_92_95;
+ unsigned int luma_ac_hm_code_val_table_96_99;
+ unsigned int luma_ac_hm_code_val_table_100_103;
+ unsigned int luma_ac_hm_code_val_table_104_107;
+ unsigned int luma_ac_hm_code_val_table_108_111;
+ unsigned int luma_ac_hm_code_val_table_112_115;
+ unsigned int luma_ac_hm_code_val_table_116_119;
+ unsigned int luma_ac_hm_code_val_table_120_123;
+ unsigned int luma_ac_hm_code_val_table_124_127;
+ unsigned int luma_ac_hm_code_val_table_128_131;
+ unsigned int luma_ac_hm_code_val_table_132_135;
+ unsigned int luma_ac_hm_code_val_table_136_139;
+ unsigned int luma_ac_hm_code_val_table_140_143;
+ unsigned int luma_ac_hm_code_val_table_144_147;
+ unsigned int luma_ac_hm_code_val_table_148_151;
+ unsigned int luma_ac_hm_code_val_table_152_155;
+ unsigned int luma_ac_hm_code_val_table_156_159;
+ unsigned int luma_ac_hm_code_val_table_160_161;
+ unsigned int chroma_ac_hm_code_cnt_table_0_3;
+ unsigned int chroma_ac_hm_code_cnt_table_4_7;
+ unsigned int chroma_ac_hm_code_cnt_table_8_11;
+ unsigned int chroma_ac_hm_code_cnt_table_12_15;
+ unsigned int chroma_ac_hm_code_val_table_0_3;
+ unsigned int chroma_ac_hm_code_val_table_4_7;
+ unsigned int chroma_ac_hm_code_val_table_8_11;
+ unsigned int chroma_ac_hm_code_val_table_12_15;
+ unsigned int chroma_ac_hm_code_val_table_16_19;
+ unsigned int chroma_ac_hm_code_val_table_20_23;
+ unsigned int chroma_ac_hm_code_val_table_24_27;
+ unsigned int chroma_ac_hm_code_val_table_28_31;
+ unsigned int chroma_ac_hm_code_val_table_32_35;
+ unsigned int chroma_ac_hm_code_val_table_36_39;
+ unsigned int chroma_ac_hm_code_val_table_40_43;
+ unsigned int chroma_ac_hm_code_val_table_44_47;
+ unsigned int chroma_ac_hm_code_val_table_48_51;
+ unsigned int chroma_ac_hm_code_val_table_52_55;
+ unsigned int chroma_ac_hm_code_val_table_56_59;
+ unsigned int chroma_ac_hm_code_val_table_60_63;
+ unsigned int chroma_ac_hm_code_val_table_64_67;
+ unsigned int chroma_ac_hm_code_val_table_68_71;
+ unsigned int chroma_ac_hm_code_val_table_72_75;
+ unsigned int chroma_ac_hm_code_val_table_76_79;
+ unsigned int chroma_ac_hm_code_val_table_80_83;
+ unsigned int chroma_ac_hm_code_val_table_84_87;
+ unsigned int chroma_ac_hm_code_val_table_88_91;
+ unsigned int chroma_ac_hm_code_val_table_92_95;
+ unsigned int chroma_ac_hm_code_val_table_96_99;
+ unsigned int chroma_ac_hm_code_val_table_100_103;
+ unsigned int chroma_ac_hm_code_val_table_104_107;
+ unsigned int chroma_ac_hm_code_val_table_108_111;
+ unsigned int chroma_ac_hm_code_val_table_112_115;
+ unsigned int chroma_ac_hm_code_val_table_116_119;
+ unsigned int chroma_ac_hm_code_val_table_120_123;
+ unsigned int chroma_ac_hm_code_val_table_124_127;
+ unsigned int chroma_ac_hm_code_val_table_128_131;
+ unsigned int chroma_ac_hm_code_val_table_132_135;
+ unsigned int chroma_ac_hm_code_val_table_136_139;
+ unsigned int chroma_ac_hm_code_val_table_140_143;
+ unsigned int chroma_ac_hm_code_val_table_144_147;
+ unsigned int chroma_ac_hm_code_val_table_148_151;
+ unsigned int chroma_ac_hm_code_val_table_152_155;
+ unsigned int chroma_ac_hm_code_val_table_156_159;
+ unsigned int chroma_ac_hm_code_val_table_160_161;
+} __attribute__((packed)) jpeg_cmd_dec_cfg;
+
+
+/*
+ * ARM to JPEG configuration commands are passed through the
+ * uPJpegActionCmdQueue
+ */
+
+/*
+ * Command to start the encode process
+ */
+
+#define JPEG_CMD_ENC_ENCODE 0x0000
+#define JPEG_CMD_ENC_ENCODE_LEN sizeof(jpeg_cmd_enc_encode)
+
+
+typedef struct {
+ unsigned short cmd_id;
+} __attribute__((packed)) jpeg_cmd_enc_encode;
+
+
+/*
+ * Command to transition from current state of encoder to IDLE state
+ */
+
+#define JPEG_CMD_ENC_IDLE 0x0001
+#define JPEG_CMD_ENC_IDLE_LEN sizeof(jpeg_cmd_enc_idle)
+
+
+typedef struct {
+ unsigned short cmd_id;
+} __attribute__((packed)) jpeg_cmd_enc_idle;
+
+
+/*
+ * Command to inform the encoder that another buffer is ready
+ */
+
+#define JPEG_CMD_ENC_OP_CONSUMED 0x0002
+#define JPEG_CMD_ENC_OP_CONSUMED_LEN sizeof(jpeg_cmd_enc_op_consumed)
+
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int op_buf_addr;
+ unsigned int op_buf_size;
+} __attribute__((packed)) jpeg_cmd_enc_op_consumed;
+
+
+/*
+ * Command to start the decoding process
+ */
+
+#define JPEG_CMD_DEC_DECODE 0x0003
+#define JPEG_CMD_DEC_DECODE_LEN sizeof(jpeg_cmd_dec_decode)
+
+
+typedef struct {
+ unsigned short cmd_id;
+} __attribute__((packed)) jpeg_cmd_dec_decode;
+
+
+/*
+ * Command to transition from the current state of decoder to IDLE
+ */
+
+#define JPEG_CMD_DEC_IDLE 0x0004
+#define JPEG_CMD_DEC_IDLE_LEN sizeof(jpeg_cmd_dec_idle)
+
+
+typedef struct {
+ unsigned short cmd_id;
+} __attribute__((packed)) jpeg_cmd_dec_idle;
+
+
+/*
+ * Command to inform that an op buffer is ready for use
+ */
+
+#define JPEG_CMD_DEC_OP_CONSUMED 0x0005
+#define JPEG_CMD_DEC_OP_CONSUMED_LEN sizeof(jpeg_cmd_dec_op_consumed)
+
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int luma_op_buf_addr;
+ unsigned int luma_op_buf_size;
+ unsigned int chroma_op_buf_addr;
+} __attribute__((packed)) jpeg_cmd_dec_op_consumed;
+
+
+/*
+ * Command to pass a new ip buffer to the jpeg decoder
+ */
+
+#define JPEG_CMD_DEC_IP 0x0006
+#define JPEG_CMD_DEC_IP_LEN sizeof(jpeg_cmd_dec_ip_len)
+
+#define JPEG_CMD_EOI_INDICATOR_NOT_END 0x0000
+#define JPEG_CMD_EOI_INDICATOR_END 0x0001
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int ip_buf_addr;
+ unsigned int ip_buf_size;
+ unsigned int eoi_indicator;
+} __attribute__((packed)) jpeg_cmd_dec_ip;
+
+
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5jpegmsg.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5jpegmsg.h
new file mode 100644
index 00000000000..d11aa3fbccb
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5jpegmsg.h
@@ -0,0 +1,177 @@
+#ifndef QDSP5VIDJPEGMSGI_H
+#define QDSP5VIDJPEGMSGI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+ J P E G I N T E R N A L M E S S A G E S
+
+GENERAL DESCRIPTION
+ This file contains defintions of format blocks of messages
+ that are sent by JPEG Task
+
+REFERENCES
+ None
+
+EXTERNALIZED FUNCTIONS
+ None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+This software is licensed under the terms of the GNU General Public
+License version 2, as published by the Free Software Foundation, and
+may be copied, distributed, and modified under those terms.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+ EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/AdspSvc/7XXX/qdsp5cmd/video/qdsp5jpegmsg.h#2 $ $DateTime: 2008/07/30 10:50:23 $ $Author: pavanr $
+Revision History:
+
+when who what, where, why
+-------- --- ----------------------------------------------------------
+05/10/08 sv initial version
+===========================================================================*/
+
+/*
+ * Messages from JPEG task to ARM through jpeguPMsgQueue
+ */
+
+/*
+ * Message is ACK for CMD_JPEGE_ENCODE cmd
+ */
+
+#define JPEG_MSG_ENC_ENCODE_ACK 0x0000
+#define JPEG_MSG_ENC_ENCODE_ACK_LEN \
+ sizeof(jpeg_msg_enc_encode_ack)
+
+typedef struct {
+} __attribute__((packed)) jpeg_msg_enc_encode_ack;
+
+
+/*
+ * Message informs the up when op buffer is ready for consumption and
+ * when encoding is complete or errors
+ */
+
+#define JPEG_MSG_ENC_OP_PRODUCED 0x0001
+#define JPEG_MSG_ENC_OP_PRODUCED_LEN \
+ sizeof(jpeg_msg_enc_op_produced)
+
+#define JPEG_MSGOP_OP_BUF_STATUS_ENC_DONE_PROGRESS 0x0000
+#define JPEG_MSGOP_OP_BUF_STATUS_ENC_DONE_COMPLETE 0x0001
+#define JPEG_MSGOP_OP_BUF_STATUS_ENC_ERR 0x10000
+
+typedef struct {
+ unsigned int op_buf_addr;
+ unsigned int op_buf_size;
+ unsigned int op_buf_status;
+} __attribute__((packed)) jpeg_msg_enc_op_produced;
+
+
+/*
+ * Message to ack CMD_JPEGE_IDLE
+ */
+
+#define JPEG_MSG_ENC_IDLE_ACK 0x0002
+#define JPEG_MSG_ENC_IDLE_ACK_LEN sizeof(jpeg_msg_enc_idle_ack)
+
+
+typedef struct {
+} __attribute__ ((packed)) jpeg_msg_enc_idle_ack;
+
+
+/*
+ * Message to indicate the illegal command
+ */
+
+#define JPEG_MSG_ENC_ILLEGAL_COMMAND 0x0003
+#define JPEG_MSG_ENC_ILLEGAL_COMMAND_LEN \
+ sizeof(jpeg_msg_enc_illegal_command)
+
+typedef struct {
+ unsigned int status;
+} __attribute__((packed)) jpeg_msg_enc_illegal_command;
+
+
+/*
+ * Message to ACK CMD_JPEGD_DECODE
+ */
+
+#define JPEG_MSG_DEC_DECODE_ACK 0x0004
+#define JPEG_MSG_DEC_DECODE_ACK_LEN \
+ sizeof(jpeg_msg_dec_decode_ack)
+
+
+typedef struct {
+} __attribute__((packed)) jpeg_msg_dec_decode_ack;
+
+
+/*
+ * Message to inform up that an op buffer is ready for consumption and when
+ * decoding is complete or an error occurs
+ */
+
+#define JPEG_MSG_DEC_OP_PRODUCED 0x0005
+#define JPEG_MSG_DEC_OP_PRODUCED_LEN \
+ sizeof(jpeg_msg_dec_op_produced)
+
+#define JPEG_MSG_DEC_OP_BUF_STATUS_PROGRESS 0x0000
+#define JPEG_MSG_DEC_OP_BUF_STATUS_DONE 0x0001
+
+typedef struct {
+ unsigned int luma_op_buf_addr;
+ unsigned int chroma_op_buf_addr;
+ unsigned int num_mcus;
+ unsigned int op_buf_status;
+} __attribute__((packed)) jpeg_msg_dec_op_produced;
+
+/*
+ * Message to ack CMD_JPEGD_IDLE cmd
+ */
+
+#define JPEG_MSG_DEC_IDLE_ACK 0x0006
+#define JPEG_MSG_DEC_IDLE_ACK_LEN sizeof(jpeg_msg_dec_idle_ack)
+
+
+typedef struct {
+} __attribute__((packed)) jpeg_msg_dec_idle_ack;
+
+
+/*
+ * Message to indicate illegal cmd was received
+ */
+
+#define JPEG_MSG_DEC_ILLEGAL_COMMAND 0x0007
+#define JPEG_MSG_DEC_ILLEGAL_COMMAND_LEN \
+ sizeof(jpeg_msg_dec_illegal_command)
+
+
+typedef struct {
+ unsigned int status;
+} __attribute__((packed)) jpeg_msg_dec_illegal_command;
+
+/*
+ * Message to request up for the next segment of ip bit stream
+ */
+
+#define JPEG_MSG_DEC_IP_REQUEST 0x0008
+#define JPEG_MSG_DEC_IP_REQUEST_LEN \
+ sizeof(jpeg_msg_dec_ip_request)
+
+
+typedef struct {
+} __attribute__((packed)) jpeg_msg_dec_ip_request;
+
+
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5lpmcmdi.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5lpmcmdi.h
new file mode 100644
index 00000000000..6c76e2c20cf
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5lpmcmdi.h
@@ -0,0 +1,82 @@
+#ifndef QDSP5LPMCMDI_H
+#define QDSP5LPMCMDI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+ L P M I N T E R N A L C O M M A N D S
+
+GENERAL DESCRIPTION
+ This file contains defintions of format blocks of commands
+ that are accepted by LPM Task
+
+REFERENCES
+ None
+
+EXTERNALIZED FUNCTIONS
+ None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+This software is licensed under the terms of the GNU General Public
+License version 2, as published by the Free Software Foundation, and
+may be copied, distributed, and modified under those terms.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+ EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+
+$Header: //source/qcom/qct/multimedia2/AdspSvc/7XXX/qdsp5cmd/video/qdsp5lpmcmdi.h#2 $ $DateTime: 2008/07/30 10:50:23 $ $Author: pavanr $
+Revision History:
+
+when who what, where, why
+-------- --- ----------------------------------------------------------
+06/12/08 sv initial version
+===========================================================================*/
+
+
+/*
+ * Command to start LPM processing based on the config params
+ */
+
+#define LPM_CMD_START 0x0000
+#define LPM_CMD_START_LEN sizeof(lpm_cmd_start)
+
+#define LPM_CMD_SPATIAL_FILTER_PART_OPMODE_0 0x00000000
+#define LPM_CMD_SPATIAL_FILTER_PART_OPMODE_1 0x00010000
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int ip_data_cfg_part1;
+ unsigned int ip_data_cfg_part2;
+ unsigned int ip_data_cfg_part3;
+ unsigned int ip_data_cfg_part4;
+ unsigned int op_data_cfg_part1;
+ unsigned int op_data_cfg_part2;
+ unsigned int op_data_cfg_part3;
+ unsigned int spatial_filter_part[32];
+} __attribute__((packed)) lpm_cmd_start;
+
+
+
+/*
+ * Command to stop LPM processing
+ */
+
+#define LPM_CMD_IDLE 0x0001
+#define LPM_CMD_IDLE_LEN sizeof(lpm_cmd_idle)
+
+typedef struct {
+ unsigned int cmd_id;
+} __attribute__((packed)) lpm_cmd_idle;
+
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5lpmmsg.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5lpmmsg.h
new file mode 100644
index 00000000000..3d1039d6ba4
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5lpmmsg.h
@@ -0,0 +1,80 @@
+#ifndef QDSP5LPMMSGI_H
+#define QDSP5LPMMSGI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+ L P M I N T E R N A L M E S S A G E S
+
+GENERAL DESCRIPTION
+ This file contains defintions of format blocks of commands
+ that are accepted by LPM Task
+
+REFERENCES
+ None
+
+EXTERNALIZED FUNCTIONS
+ None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+This software is licensed under the terms of the GNU General Public
+License version 2, as published by the Free Software Foundation, and
+may be copied, distributed, and modified under those terms.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+ EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/AdspSvc/7XXX/qdsp5cmd/video/qdsp5lpmmsg.h#2 $ $DateTime: 2008/07/30 10:50:23 $ $Author: pavanr $
+Revision History:
+
+when who what, where, why
+-------- --- ----------------------------------------------------------
+06/12/08 sv initial version
+===========================================================================*/
+
+/*
+ * Message to acknowledge CMD_LPM_IDLE command
+ */
+
+#define LPM_MSG_IDLE_ACK 0x0000
+#define LPM_MSG_IDLE_ACK_LEN sizeof(lpm_msg_idle_ack)
+
+typedef struct {
+} __attribute__((packed)) lpm_msg_idle_ack;
+
+
+/*
+ * Message to acknowledge CMD_LPM_START command
+ */
+
+
+#define LPM_MSG_START_ACK 0x0001
+#define LPM_MSG_START_ACK_LEN sizeof(lpm_msg_start_ack)
+
+
+typedef struct {
+} __attribute__((packed)) lpm_msg_start_ack;
+
+
+/*
+ * Message to notify the ARM that LPM processing is complete
+ */
+
+#define LPM_MSG_DONE 0x0002
+#define LPM_MSG_DONE_LEN sizeof(lpm_msg_done)
+
+typedef struct {
+} __attribute__((packed)) lpm_msg_done;
+
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5vdeccmdi.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5vdeccmdi.h
new file mode 100644
index 00000000000..3a32ee99c6e
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5vdeccmdi.h
@@ -0,0 +1,235 @@
+#ifndef QDSP5VIDDECCMDI_H
+#define QDSP5VIDDECCMDI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+ V I D E O D E C O D E R I N T E R N A L C O M M A N D S
+
+GENERAL DESCRIPTION
+ This file contains defintions of format blocks of commands
+ that are accepted by VIDDEC Task
+
+REFERENCES
+ None
+
+EXTERNALIZED FUNCTIONS
+ None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+This software is licensed under the terms of the GNU General Public
+License version 2, as published by the Free Software Foundation, and
+may be copied, distributed, and modified under those terms.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+ EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/AdspSvc/7XXX/qdsp5cmd/video/qdsp5vdeccmdi.h#2 $ $DateTime: 2008/07/30 10:50:23 $ $Author: pavanr $
+Revision History:
+
+when who what, where, why
+-------- --- ----------------------------------------------------------
+05/10/08 ac initial version
+===========================================================================*/
+
+
+/*
+ * Command to inform VIDDEC that new subframe packet is ready
+ */
+
+#define VIDDEC_CMD_SUBFRAME_PKT 0x0000
+#define VIDDEC_CMD_SUBFRAME_PKT_LEN \
+ sizeof(viddec_cmd_subframe_pkt)
+
+#define VIDDEC_CMD_SF_INFO_1_DM_DMA_STATS_EXCHANGE_FLAG_DM 0x0000
+#define VIDDEC_CMD_SF_INFO_1_DM_DMA_STATS_EXCHANGE_FLAG_DMA 0x0001
+
+#define VIDDEC_CMD_SF_INFO_0_SUBFRAME_CONTI 0x0000
+#define VIDDEC_CMD_SF_INFO_0_SUBFRAME_FIRST 0x0001
+#define VIDDEC_CMD_SF_INFO_0_SUBFRAME_LAST 0x0002
+#define VIDDEC_CMD_SF_INFO_0_SUBFRAME_FIRST_AND_LAST 0x0003
+
+#define VIDDEC_CMD_CODEC_SELECTION_WORD_MPEG_4 0x0000
+#define VIDDEC_CMD_CODEC_SELECTION_WORD_H_263_P0 0x0001
+#define VIDDEC_CMD_CODEC_SELECTION_WORD_H_264 0x0002
+#define VIDDEC_CMD_CODEC_SELECTION_WORD_H_263_p3 0x0003
+#define VIDDEC_CMD_CODEC_SELECTION_WORD_RV9 0x0004
+#define VIDDEC_CMD_CODEC_SELECTION_WORD_WMV9 0x0005
+#define VIDDEC_CMD_CODEC_SELECTION_WORD_SMCDB 0x0006
+#define VIDDEC_CMD_CODEC_SELECTION_WORD_QFRE 0x0007
+#define VIDDEC_CMD_CODEC_SELECTION_WORD_VLD 0x0008
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short packet_seq_number;
+ unsigned short codec_instance_id;
+ unsigned short subframe_packet_size_high;
+ unsigned short subframe_packet_size_low;
+ unsigned short subframe_packet_high;
+ unsigned short subframe_packet_low;
+ unsigned short subframe_packet_partition;
+ unsigned short statistics_packet_size_high;
+ unsigned short statistics_packet_size_low;
+ unsigned short statistics_packet_high;
+ unsigned short statistics_packet_low;
+ unsigned short statistics_partition;
+ unsigned short subframe_info_1;
+ unsigned short subframe_info_0;
+ unsigned short codec_selection_word;
+ unsigned short num_mbs;
+} __attribute__((packed)) viddec_cmd_subframe_pkt;
+
+
+/*
+ * Command to inform VIDDEC task that post processing is required for the frame
+ */
+
+#define VIDDEC_CMD_PP_ENABLE 0x0001
+#define VIDDEC_CMD_PP_ENABLE_LEN \
+ sizeof(viddec_cmd_pp_enable)
+
+#define VIDDEC_CMD_PP_INFO_0_DM_DMA_LS_EXCHANGE_FLAG_DM 0x0000
+#define VIDDEC_CMD_PP_INFO_0_DM_DMA_LS_EXCHANGE_FLAG_DMA 0x0001
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short packet_seq_num;
+ unsigned short codec_instance_id;
+ unsigned short postproc_info_0;
+ unsigned short codec_selection_word;
+ unsigned short pp_output_addr_high;
+ unsigned short pp_output_addr_low;
+ unsigned short postproc_info_1;
+ unsigned short load_sharing_packet_size_high;
+ unsigned short load_sharing_packet_size_low;
+ unsigned short load_sharing_packet_high;
+ unsigned short load_sharing_packet_low;
+ unsigned short load_sharing_partition;
+ unsigned short pp_param_0;
+ unsigned short pp_param_1;
+ unsigned short pp_param_2;
+ unsigned short pp_param_3;
+} __attribute__((packed)) viddec_cmd_pp_enable;
+
+
+/*
+ * FRAME Header Packet : It is at the start of new frame
+ */
+
+#define VIDDEC_CMD_FRAME_HEADER_PACKET 0x0002
+#define VIDDEC_CMD_FRAME_HEADER_PACKET_LEN \
+ sizeof(viddec_cmd_frame_header_packet)
+
+#define VIDDEC_CMD_FRAME_INFO_0_ERROR_SKIP 0x0000
+#define VIDDEC_CMD_FRAME_INFO_0_ERROR_BLACK 0x0800
+
+typedef struct {
+ unsigned short packet_id;
+ unsigned short x_dimension;
+ unsigned short y_dimension;
+ unsigned short line_width;
+ unsigned short frame_info_0;
+ unsigned short frame_buffer_0_high;
+ unsigned short frame_buffer_0_low;
+ unsigned short frame_buffer_1_high;
+ unsigned short frame_buffer_1_low;
+ unsigned short frame_buffer_2_high;
+ unsigned short frame_buffer_2_low;
+ unsigned short frame_buffer_3_high;
+ unsigned short frame_buffer_3_low;
+ unsigned short frame_buffer_4_high;
+ unsigned short frame_buffer_4_low;
+ unsigned short frame_buffer_5_high;
+ unsigned short frame_buffer_5_low;
+ unsigned short frame_buffer_6_high;
+ unsigned short frame_buffer_6_low;
+ unsigned short frame_buffer_7_high;
+ unsigned short frame_buffer_7_low;
+ unsigned short frame_buffer_8_high;
+ unsigned short frame_buffer_8_low;
+ unsigned short frame_buffer_9_high;
+ unsigned short frame_buffer_9_low;
+ unsigned short frame_buffer_10_high;
+ unsigned short frame_buffer_10_low;
+ unsigned short frame_buffer_11_high;
+ unsigned short frame_buffer_11_low;
+ unsigned short frame_buffer_12_high;
+ unsigned short frame_buffer_12_low;
+ unsigned short frame_buffer_13_high;
+ unsigned short frame_buffer_13_low;
+ unsigned short frame_buffer_14_high;
+ unsigned short frame_buffer_14_low;
+ unsigned short frame_buffer_15_high;
+ unsigned short frame_buffer_15_low;
+ unsigned short output_frame_buffer_high;
+ unsigned short output_frame_buffer_low;
+ unsigned short end_of_packet_marker;
+} __attribute__((packed)) viddec_cmd_frame_header_packet;
+
+
+/*
+ * SLICE HEADER PACKET
+ * I-Slice and P-Slice
+ */
+
+#define VIDDEC_CMD_SLICE_HEADER_PKT_ISLICE 0x0003
+#define VIDDEC_CMD_SLICE_HEADER_PKT_ISLICE_LEN \
+ sizeof(viddec_cmd_slice_header_pkt_islice)
+
+#define VIDDEC_CMD_ISLICE_INFO_1_MOD_SLICE_TYPE_PSLICE 0x0000
+#define VIDDEC_CMD_ISLICE_INFO_1_MOD_SLICE_TYPE_BSLICE 0x0100
+#define VIDDEC_CMD_ISLICE_INFO_1_MOD_SLICE_TYPE_ISLICE 0x0200
+#define VIDDEC_CMD_ISLICE_INFO_1_MOD_SLICE_TYPE_SPSLICE 0x0300
+#define VIDDEC_CMD_ISLICE_INFO_1_MOD_SLICE_TYPE_SISLICE 0x0400
+#define VIDDEC_CMD_ISLICE_INFO_1_NOPADDING 0x0000
+#define VIDDEC_CMD_ISLICE_INFO_1_PADDING 0x0800
+
+#define VIDDEC_CMD_ISLICE_EOP_MARKER 0x7FFF
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short packet_id;
+ unsigned short slice_info_0;
+ unsigned short slice_info_1;
+ unsigned short slice_info_2;
+ unsigned short num_bytes_in_rbsp_high;
+ unsigned short num_bytes_in_rbsp_low;
+ unsigned short num_bytes_in_rbsp_consumed;
+ unsigned short end_of_packet_marker;
+} __attribute__((packed)) viddec_cmd_slice_header_pkt_islice;
+
+
+#define VIDDEC_CMD_SLICE_HEADER_PKT_PSLICE 0x0003
+#define VIDDEC_CMD_SLICE_HEADER_PKT_PSLICE_LEN \
+ sizeof(viddec_cmd_slice_header_pkt_pslice)
+
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short packet_id;
+ unsigned short slice_info_0;
+ unsigned short slice_info_1;
+ unsigned short slice_info_2;
+ unsigned short slice_info_3;
+ unsigned short refidx_l0_map_tab_info_0;
+ unsigned short refidx_l0_map_tab_info_1;
+ unsigned short refidx_l0_map_tab_info_2;
+ unsigned short refidx_l0_map_tab_info_3;
+ unsigned short num_bytes_in_rbsp_high;
+ unsigned short num_bytes_in_rbsp_low;
+ unsigned short num_bytes_in_rbsp_consumed;
+ unsigned short end_of_packet_marker;
+} __attribute__((packed)) viddec_cmd_slice_header_pkt_pslice;
+
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5vdecmsg.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5vdecmsg.h
new file mode 100644
index 00000000000..c1744c1644d
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5vdecmsg.h
@@ -0,0 +1,107 @@
+#ifndef QDSP5VIDDECMSGI_H
+#define QDSP5VIDDECMSGI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+ V I D E O D E C O D E R I N T E R N A L M E S S A G E S
+
+GENERAL DESCRIPTION
+ This file contains defintions of format blocks of messages
+ that are sent by VIDDEC Task
+
+REFERENCES
+ None
+
+EXTERNALIZED FUNCTIONS
+ None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+This software is licensed under the terms of the GNU General Public
+License version 2, as published by the Free Software Foundation, and
+may be copied, distributed, and modified under those terms.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+ EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/AdspSvc/7XXX/qdsp5cmd/video/qdsp5vdecmsg.h#2 $ $DateTime: 2008/07/30 10:50:23 $ $Author: pavanr $
+Revision History:
+
+when who what, where, why
+-------- --- ----------------------------------------------------------
+05/10/08 ac initial version
+===========================================================================*/
+
+/*
+ * Message to inform ARM which VDEC_SUBFRAME_PKT_CMD processed by VIDDEC TASK
+ */
+
+#define VIDDEC_MSG_SUBF_DONE 0x0000
+#define VIDDEC_MSG_SUBF_DONE_LEN \
+ sizeof(viddec_msg_subf_done)
+
+typedef struct {
+ unsigned short packet_seq_number;
+ unsigned short codec_instance_id;
+} __attribute__((packed)) viddec_msg_subf_done;
+
+
+/*
+ * Message to inform ARM one frame has been decoded
+ */
+
+#define VIDDEC_MSG_FRAME_DONE 0x0001
+#define VIDDEC_MSG_FRAME_DONE_LEN \
+ sizeof(viddec_msg_frame_done)
+
+typedef struct {
+ unsigned short packet_seq_number;
+ unsigned short codec_instance_id;
+} __attribute__((packed)) viddec_msg_frame_done;
+
+
+/*
+ * Message to inform ARM that post processing frame has been decoded
+ */
+
+#define VIDDEC_MSG_PP_ENABLE_CMD_DONE 0x0002
+#define VIDDEC_MSG_PP_ENABLE_CMD_DONE_LEN \
+ sizeof(viddec_msg_pp_enable_cmd_done)
+
+typedef struct {
+ unsigned short packet_seq_number;
+ unsigned short codec_instance_id;
+} __attribute__((packed)) viddec_msg_pp_enable_cmd_done;
+
+
+/*
+ * Message to inform ARM that one post processing frame has been decoded
+ */
+
+
+#define VIDDEC_MSG_PP_FRAME_DONE 0x0003
+#define VIDDEC_MSG_PP_FRAME_DONE_LEN \
+ sizeof(viddec_msg_pp_frame_done)
+
+#define VIDDEC_MSG_DISP_WORTHY_DISP 0x0000
+#define VIDDEC_MSG_DISP_WORTHY_DISP_NONE 0xFFFF
+
+
+typedef struct {
+ unsigned short packet_seq_number;
+ unsigned short codec_instance_id;
+ unsigned short display_worthy;
+} __attribute__((packed)) viddec_msg_pp_frame_done;
+
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5venccmdi.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5venccmdi.h
new file mode 100644
index 00000000000..819544d186d
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5venccmdi.h
@@ -0,0 +1,212 @@
+#ifndef QDSP5VIDENCCMDI_H
+#define QDSP5VIDENCCMDI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+ V I D E O E N C O D E R I N T E R N A L C O M M A N D S
+
+GENERAL DESCRIPTION
+ This file contains defintions of format blocks of commands
+ that are accepted by VIDENC Task
+
+REFERENCES
+ None
+
+EXTERNALIZED FUNCTIONS
+ None
+
+Copyright(c) 2008 by QUALCOMM, Incorporated.
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+ EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+Revision History:
+
+when who what, where, why
+-------- --- ----------------------------------------------------------
+09/25/08 umeshp initial version
+===========================================================================*/
+
+ #define VIDENC_CMD_CFG 0x0000
+ #define VIDENC_CMD_ACTIVE 0x0001
+ #define VIDENC_CMD_IDLE 0x0002
+ #define VIDENC_CMD_FRAME_START 0x0003
+ #define VIDENC_CMD_STATUS_QUERY 0x0004
+ #define VIDENC_CMD_RC_CFG 0x0005
+ #define VIDENC_CMD_DIS_CFG 0x0006
+ #define VIDENC_CMD_DIS 0x0007
+ #define VIDENC_CMD_INTRA_REFRESH 0x0008
+ #define VIDENC_CMD_DIGITAL_ZOOM 0x0009
+
+
+/*
+ * Command to pass the frame message information to VIDENC
+ */
+
+
+#define VIDENC_CMD_FRAME_START_LEN \
+ sizeof(videnc_cmd_frame_start)
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short frame_info;
+ unsigned short frame_rho_budget_word_high;
+ unsigned short frame_rho_budget_word_low;
+ unsigned short input_luma_addr_high;
+ unsigned short input_luma_addr_low;
+ unsigned short input_chroma_addr_high;
+ unsigned short input_chroma_addr_low;
+ unsigned short ref_vop_buf_ptr_high;
+ unsigned short ref_vop_buf_ptr_low;
+ unsigned short enc_pkt_buf_ptr_high;
+ unsigned short enc_pkt_buf_ptr_low;
+ unsigned short enc_pkt_buf_size_high;
+ unsigned short enc_pkt_buf_size_low;
+ unsigned short unfilt_recon_vop_buf_ptr_high;
+ unsigned short unfilt_recon_vop_buf_ptr_low;
+ unsigned short filt_recon_vop_buf_ptr_high;
+ unsigned short filt_recon_vop_buf_ptr_low;
+} __attribute__((packed)) videnc_cmd_frame_start;
+
+/*
+ * Command to pass the frame-level digital stabilization parameters to VIDENC
+ */
+
+
+#define VIDENC_CMD_DIS_LEN \
+ sizeof(videnc_cmd_dis)
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short vfe_out_prev_luma_addr_high;
+ unsigned short vfe_out_prev_luma_addr_low;
+ unsigned short stabilization_info;
+} __attribute__((packed)) videnc_cmd_dis;
+
+/*
+ * Command to pass the codec related parameters to VIDENC
+ */
+
+
+#define VIDENC_CMD_CFG_LEN \
+ sizeof(videnc_cmd_cfg)
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short cfg_info_0;
+ unsigned short cfg_info_1;
+ unsigned short four_mv_threshold;
+ unsigned short ise_fse_mv_cost_fac;
+ unsigned short venc_frame_dim;
+ unsigned short venc_DM_partition;
+} __attribute__((packed)) videnc_cmd_cfg;
+
+/*
+ * Command to start the video encoding
+ */
+
+
+#define VIDENC_CMD_ACTIVE_LEN \
+ sizeof(videnc_cmd_active)
+
+typedef struct {
+ unsigned short cmd_id;
+} __attribute__((packed)) videnc_cmd_active;
+
+/*
+ * Command to stop the video encoding
+ */
+
+
+#define VIDENC_CMD_IDLE_LEN \
+ sizeof(videnc_cmd_idle)
+
+typedef struct {
+ unsigned short cmd_id;
+} __attribute__((packed)) videnc_cmd_idle;
+
+/*
+ * Command to query staus of VIDENC
+ */
+
+
+#define VIDENC_CMD_STATUS_QUERY_LEN \
+ sizeof(videnc_cmd_status_query)
+
+typedef struct {
+ unsigned short cmd_id;
+} __attribute__((packed)) videnc_cmd_status_query;
+
+/*
+ * Command to set rate control for a frame
+ */
+
+
+#define VIDENC_CMD_RC_CFG_LEN \
+ sizeof(videnc_cmd_rc_cfg)
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short max_frame_qp_delta;
+ unsigned short max_min_frame_qp;
+} __attribute__((packed)) videnc_cmd_rc_cfg;
+
+/*
+ * Command to set intra-refreshing
+ */
+
+
+#define VIDENC_CMD_INTRA_REFRESH_LEN \
+ sizeof(videnc_cmd_intra_refresh)
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short num_mb_refresh;
+ unsigned short mb_index[15];
+} __attribute__((packed)) videnc_cmd_intra_refresh;
+
+/*
+ * Command to pass digital zoom information to the VIDENC
+ */
+#define VIDENC_CMD_DIGITAL_ZOOM_LEN \
+ sizeof(videnc_cmd_digital_zoom)
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short digital_zoom_en;
+ unsigned short luma_frame_shift_X;
+ unsigned short luma_frame_shift_Y;
+ unsigned short up_ip_luma_rows;
+ unsigned short up_ip_luma_cols;
+ unsigned short up_ip_chroma_rows;
+ unsigned short up_ip_chroma_cols;
+ unsigned short luma_ph_incr_V_low;
+ unsigned short luma_ph_incr_V_high;
+ unsigned short luma_ph_incr_H_low;
+ unsigned short luma_ph_incr_H_high;
+ unsigned short chroma_ph_incr_V_low;
+ unsigned short chroma_ph_incr_V_high;
+ unsigned short chroma_ph_incr_H_low;
+ unsigned short chroma_ph_incr_H_high;
+} __attribute__((packed)) videnc_cmd_digital_zoom;
+
+/*
+ * Command to configure digital stabilization parameters
+ */
+
+#define VIDENC_CMD_DIS_CFG_LEN \
+ sizeof(videnc_cmd_dis_cfg)
+
+typedef struct {
+ unsigned short cmd_id;
+ unsigned short image_stab_subf_start_row_col;
+ unsigned short image_stab_subf_dim;
+ unsigned short image_stab_info_0;
+} __attribute__((packed)) videnc_cmd_dis_cfg;
+
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5vfecmdi.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5vfecmdi.h
new file mode 100644
index 00000000000..55e8fc2269f
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5vfecmdi.h
@@ -0,0 +1,910 @@
+#ifndef QDSP5VFECMDI_H
+#define QDSP5VFECMDI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+ V F E I N T E R N A L C O M M A N D S
+
+GENERAL DESCRIPTION
+ This file contains defintions of format blocks of commands
+ that are accepted by VFE Task
+
+REFERENCES
+ None
+
+EXTERNALIZED FUNCTIONS
+ None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+This software is licensed under the terms of the GNU General Public
+License version 2, as published by the Free Software Foundation, and
+may be copied, distributed, and modified under those terms.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+ EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/AdspSvc/7XXX/qdsp5cmd/video/qdsp5vfecmdi.h#2 $ $DateTime: 2008/07/30 10:50:23 $ $Author: pavanr $
+Revision History:
+
+when who what, where, why
+-------- --- ----------------------------------------------------------
+06/12/08 sv initial version
+===========================================================================*/
+
+/******************************************************************************
+ * Commands through vfeCommandScaleQueue
+ *****************************************************************************/
+
+/*
+ * Command to program scaler for op1 . max op of scaler is VGA
+ */
+
+
+#define VFE_CMD_SCALE_OP1_CFG 0x0000
+#define VFE_CMD_SCALE_OP1_CFG_LEN \
+ sizeof(vfe_cmd_scale_op1_cfg)
+
+#define VFE_CMD_SCALE_OP1_SEL_IP_SEL_Y_STANDARD 0x0000
+#define VFE_CMD_SCALE_OP1_SEL_IP_SEL_Y_CASCADED 0x0001
+#define VFE_CMD_SCALE_OP1_SEL_H_Y_SCALER_DIS 0x0000
+#define VFE_CMD_SCALE_OP1_SEL_H_Y_SCALER_ENA 0x0002
+#define VFE_CMD_SCALE_OP1_SEL_H_PP_Y_SCALER_DIS 0x0000
+#define VFE_CMD_SCALE_OP1_SEL_H_PP_Y_SCALER_ENA 0x0004
+#define VFE_CMD_SCALE_OP1_SEL_V_Y_SCALER_DIS 0x0000
+#define VFE_CMD_SCALE_OP1_SEL_V_Y_SCALER_ENA 0x0008
+#define VFE_CMD_SCALE_OP1_SEL_V_PP_Y_SCALER_DIS 0x0000
+#define VFE_CMD_SCALE_OP1_SEL_V_PP_Y_SCALER_ENA 0x0010
+#define VFE_CMD_SCALE_OP1_SEL_IP_SEL_CBCR_STANDARD 0x0000
+#define VFE_CMD_SCALE_OP1_SEL_IP_SEL_CBCR_CASCADED 0x0020
+#define VFE_CMD_SCALE_OP1_SEL_H_CBCR_SCALER_DIS 0x0000
+#define VFE_CMD_SCALE_OP1_SEL_H_CBCR_SCALER_ENA 0x0040
+#define VFE_CMD_SCALE_OP1_SEL_V_CBCR_SCALER_DIS 0x0000
+#define VFE_CMD_SCALE_OP1_SEL_V_CBCR_SCALER_ENA 0x0080
+
+#define VFE_CMD_OP1_PP_Y_SCALER_CFG_PART1_DONT_LOAD_COEFFS 0x80000000
+#define VFE_CMD_OP1_PP_Y_SCALER_CFG_PART1_LOAD_COEFFS 0x80000000
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int scale_op1_sel;
+ unsigned int y_scaler_cfg_part1;
+ unsigned int y_scaler_cfg_part2;
+ unsigned int cbcr_scaler_cfg_part1;
+ unsigned int cbcr_scaler_cfg_part2;
+ unsigned int cbcr_scaler_cfg_part3;
+ unsigned int pp_y_scaler_cfg_part1;
+ unsigned int pp_y_scaler_cfg_part2;
+ unsigned int y_scaler_v_coeff_bank_part1[16];
+ unsigned int y_scaler_v_coeff_bank_part2[16];
+ unsigned int y_scaler_h_coeff_bank_part1[16];
+ unsigned int y_scaler_h_coeff_bank_part2[16];
+} __attribute__((packed)) vfe_cmd_scale_op1_cfg;
+
+
+/*
+ * Command to program scaler for op2
+ */
+
+#define VFE_CMD_SCALE_OP2_CFG 0x0001
+#define VFE_CMD_SCALE_OP2_CFG_LEN \
+ sizeof(vfe_cmd_scale_op2_cfg)
+
+#define VFE_CMD_SCALE_OP2_SEL_IP_SEL_Y_STANDARD 0x0000
+#define VFE_CMD_SCALE_OP2_SEL_IP_SEL_Y_CASCADED 0x0001
+#define VFE_CMD_SCALE_OP2_SEL_H_Y_SCALER_DIS 0x0000
+#define VFE_CMD_SCALE_OP2_SEL_H_Y_SCALER_ENA 0x0002
+#define VFE_CMD_SCALE_OP2_SEL_H_PP_Y_SCALER_DIS 0x0000
+#define VFE_CMD_SCALE_OP2_SEL_H_PP_Y_SCALER_ENA 0x0004
+#define VFE_CMD_SCALE_OP2_SEL_V_Y_SCALER_DIS 0x0000
+#define VFE_CMD_SCALE_OP2_SEL_V_Y_SCALER_ENA 0x0008
+#define VFE_CMD_SCALE_OP2_SEL_V_PP_Y_SCALER_DIS 0x0000
+#define VFE_CMD_SCALE_OP2_SEL_V_PP_Y_SCALER_ENA 0x0010
+#define VFE_CMD_SCALE_OP2_SEL_IP_SEL_CBCR_STANDARD 0x0000
+#define VFE_CMD_SCALE_OP2_SEL_IP_SEL_CBCR_CASCADED 0x0020
+#define VFE_CMD_SCALE_OP2_SEL_H_CBCR_SCALER_DIS 0x0000
+#define VFE_CMD_SCALE_OP2_SEL_H_CBCR_SCALER_ENA 0x0040
+#define VFE_CMD_SCALE_OP2_SEL_V_CBCR_SCALER_DIS 0x0000
+#define VFE_CMD_SCALE_OP2_SEL_V_CBCR_SCALER_ENA 0x0080
+
+#define VFE_CMD_OP2_PP_Y_SCALER_CFG_PART1_DONT_LOAD_COEFFS 0x80000000
+#define VFE_CMD_OP2_PP_Y_SCALER_CFG_PART1_LOAD_COEFFS 0x80000000
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int scale_op2_sel;
+ unsigned int y_scaler_cfg_part1;
+ unsigned int y_scaler_cfg_part2;
+ unsigned int cbcr_scaler_cfg_part1;
+ unsigned int cbcr_scaler_cfg_part2;
+ unsigned int cbcr_scaler_cfg_part3;
+ unsigned int pp_y_scaler_cfg_part1;
+ unsigned int pp_y_scaler_cfg_part2;
+ unsigned int y_scaler_v_coeff_bank_part1[16];
+ unsigned int y_scaler_v_coeff_bank_part2[16];
+ unsigned int y_scaler_h_coeff_bank_part1[16];
+ unsigned int y_scaler_h_coeff_bank_part2[16];
+} __attribute__((packed)) vfe_cmd_scale_op2_cfg;
+
+
+/******************************************************************************
+ * Commands through vfeCommandTableQueue
+ *****************************************************************************/
+
+/*
+ * Command to program the AXI ip paths
+ */
+
+#define VFE_CMD_AXI_IP_CFG 0x0000
+#define VFE_CMD_AXI_IP_CFG_LEN sizeof(vfe_cmd_axi_ip_cfg)
+
+#define VFE_CMD_IP_SEL_IP_FORMAT_8 0x0000
+#define VFE_CMD_IP_SEL_IP_FORMAT_10 0x0001
+#define VFE_CMD_IP_SEL_IP_FORMAT_12 0x0002
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int ip_sel;
+ unsigned int ip_cfg_part1;
+ unsigned int ip_cfg_part2;
+ unsigned int ip_unpack_cfg_part[6];
+ unsigned int ip_buf_addr[8];
+} __attribute__ ((packed)) vfe_cmd_axi_ip_cfg;
+
+
+/*
+ * Command to program axi op paths
+ */
+
+#define VFE_CMD_AXI_OP_CFG 0x0001
+#define VFE_CMD_AXI_OP_CFG_LEN sizeof(vfe_cmd_axi_op_cfg)
+
+#define VFE_CMD_OP_SEL_OP1 0x0000
+#define VFE_CMD_OP_SEL_OP2 0x0001
+#define VFE_CMD_OP_SEL_OP1_OP2 0x0002
+#define VFE_CMD_OP_SEL_CTOA 0x0003
+#define VFE_CMD_OP_SEL_CTOA_OP1 0x0004
+#define VFE_CMD_OP_SEL_CTOA_OP2 0x0005
+#define VFE_CMD_OP_SEL_OP_FORMAT_8 0x0000
+#define VFE_CMD_OP_SEL_OP_FORMAT_10 0x0008
+#define VFE_CMD_OP_SEL_OP_FORMAT_12 0x0010
+
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int op_sel;
+ unsigned int op1_y_cfg_part1;
+ unsigned int op1_y_cfg_part2;
+ unsigned int op1_cbcr_cfg_part1;
+ unsigned int op1_cbcr_cfg_part2;
+ unsigned int op2_y_cfg_part1;
+ unsigned int op2_y_cfg_part2;
+ unsigned int op2_cbcr_cfg_part1;
+ unsigned int op2_cbcr_cfg_part2;
+ unsigned int op1_buf1_addr[16];
+ unsigned int op2_buf1_addr[16];
+} __attribute__((packed)) vfe_cmd_axi_op_cfg;
+
+
+
+
+/*
+ * Command to program the roll off correction module
+ */
+
+#define VFE_CMD_ROLLOFF_CFG 0x0002
+#define VFE_CMD_ROLLOFF_CFG_LEN \
+ sizeof(vfe_cmd_rolloff_cfg)
+
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int correction_opt_center_pos;
+ unsigned int radius_square_entry[32];
+ unsigned int red_table_entry[32];
+ unsigned int green_table_entry[32];
+ unsigned int blue_table_entry[32];
+} __attribute__((packed)) vfe_cmd_rolloff_cfg;
+
+/*
+ * Command to program RGB gamma table
+ */
+
+#define VFE_CMD_RGB_GAMMA_CFG 0x0003
+#define VFE_CMD_RGB_GAMMA_CFG_LEN \
+ sizeof(vfe_cmd_rgb_gamma_cfg)
+
+#define VFE_CMD_RGB_GAMMA_SEL_LINEAR 0x0000
+#define VFE_CMD_RGB_GAMMA_SEL_PW_LINEAR 0x0001
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int rgb_gamma_sel;
+ unsigned int rgb_gamma_entry[256];
+} __attribute__((packed)) vfe_cmd_rgb_gamma_cfg;
+
+
+/*
+ * Command to program luma gamma table for the noise reduction path
+ */
+
+#define VFE_CMD_Y_GAMMA_CFG 0x0004
+#define VFE_CMD_Y_GAMMA_CFG_LEN \
+ sizeof(vfe_cmd_y_gamma_cfg)
+
+#define VFE_CMD_Y_GAMMA_SEL_LINEAR 0x0000
+#define VFE_CMD_Y_GAMMA_SEL_PW_LINEAR 0x0001
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int y_gamma_sel;
+ unsigned int y_gamma_entry[256];
+} __attribute__((packed)) vfe_cmd_y_gamma_cfg;
+
+
+
+/******************************************************************************
+ * Commands through vfeCommandQueue
+ *****************************************************************************/
+
+/*
+ * Command to reset the VFE to a known good state.All previously programmed
+ * Params will be lost
+ */
+
+
+#define VFE_CMD_RESET 0x0000
+#define VFE_CMD_RESET_LEN sizeof(vfe_cmd_reset)
+
+
+typedef struct {
+ unsigned short cmd_id;
+} __attribute__((packed)) vfe_cmd_reset;
+
+
+/*
+ * Command to start VFE processing based on the config params
+ */
+
+
+#define VFE_CMD_START 0x0001
+#define VFE_CMD_START_LEN sizeof(vfe_cmd_start)
+
+#define VFE_CMD_STARTUP_PARAMS_SRC_CAMIF 0x0000
+#define VFE_CMD_STARTUP_PARAMS_SRC_AXI 0x0001
+#define VFE_CMD_STARTUP_PARAMS_MODE_CONTINUOUS 0x0000
+#define VFE_CMD_STARTUP_PARAMS_MODE_SNAPSHOT 0x0002
+
+#define VFE_CMD_IMAGE_PL_BLACK_LVL_CORR_DIS 0x0000
+#define VFE_CMD_IMAGE_PL_BLACK_LVL_CORR_ENA 0x0001
+#define VFE_CMD_IMAGE_PL_ROLLOFF_CORR_DIS 0x0000
+#define VFE_CMD_IMAGE_PL_ROLLOFF_CORR_ENA 0x0002
+#define VFE_CMD_IMAGE_PL_WHITE_BAL_DIS 0x0000
+#define VFE_CMD_IMAGE_PL_WHITE_BAL_ENA 0x0004
+#define VFE_CMD_IMAGE_PL_RGB_GAMMA_DIS 0x0000
+#define VFE_CMD_IMAGE_PL_RGB_GAMMA_ENA 0x0008
+#define VFE_CMD_IMAGE_PL_LUMA_NOISE_RED_PATH_DIS 0x0000
+#define VFE_CMD_IMAGE_PL_LUMA_NOISE_RED_PATH_ENA 0x0010
+#define VFE_CMD_IMAGE_PL_ADP_FILTER_DIS 0x0000
+#define VFE_CMD_IMAGE_PL_ADP_FILTER_ENA 0x0020
+#define VFE_CMD_IMAGE_PL_CHROMA_SAMP_DIS 0x0000
+#define VFE_CMD_IMAGE_PL_CHROMA_SAMP_ENA 0x0040
+
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int startup_params;
+ unsigned int image_pipeline;
+ unsigned int frame_dimension;
+} __attribute__((packed)) vfe_cmd_start;
+
+
+/*
+ * Command to halt all processing
+ */
+
+#define VFE_CMD_STOP 0x0002
+#define VFE_CMD_STOP_LEN sizeof(vfe_cmd_stop)
+
+typedef struct {
+ unsigned short cmd_id;
+} __attribute__((packed)) vfe_cmd_stop;
+
+
+/*
+ * Command to commit the params that have been programmed to take
+ * effect on the next frame
+ */
+
+#define VFE_CMD_UPDATE 0x0003
+#define VFE_CMD_UPDATE_LEN sizeof(vfe_cmd_update)
+
+
+typedef struct {
+ unsigned short cmd_id;
+} __attribute__((packed)) vfe_cmd_update;
+
+
+/*
+ * Command to program CAMIF module
+ */
+
+#define VFE_CMD_CAMIF_CFG 0x0004
+#define VFE_CMD_CAMIF_CFG_LEN sizeof(vfe_cmd_camif_cfg)
+
+#define VFE_CMD_CFG_VSYNC_SYNC_EDGE_HIGH 0x0000
+#define VFE_CMD_CFG_VSYNC_SYNC_EDGE_LOW 0x0002
+#define VFE_CMD_CFG_HSYNC_SYNC_EDGE_HIGH 0x0000
+#define VFE_CMD_CFG_HSYNC_SYNC_EDGE_LOW 0x0004
+#define VFE_CMD_CFG_SYNC_MODE_APS 0x0000
+#define VFE_CMD_CFG_SYNC_MODE_EFS 0X0008
+#define VFE_CMD_CFG_SYNC_MODE_ELS 0x0010
+#define VFE_CMD_CFG_SYNC_MODE_RVD 0x0018
+#define VFE_CMD_CFG_VFE_SUBSAMP_EN_DIS 0x0000
+#define VFE_CMD_CFG_VFE_SUBSAMP_EN_ENA 0x0020
+#define VFE_CMD_CFG_BUS_SUBSAMP_EN_DIS 0x0000
+#define VFE_CMD_CFG_BUS_SUBSAMP_EN_ENA 0x0080
+#define VFE_CMD_CFG_IRQ_SUBSAMP_EN_DIS 0x0000
+#define VFE_CMD_CFG_IRQ_SUBSAMP_EN_ENA 0x0800
+
+#define VFE_CMD_SUBSAMP2_CFG_PIXEL_SKIP_16 0x0000
+#define VFE_CMD_SUBSAMP2_CFG_PIXEL_SKIP_12 0x0010
+
+#define VFE_CMD_EPOCH_IRQ_1_DIS 0x0000
+#define VFE_CMD_EPOCH_IRQ_1_ENA 0x4000
+#define VFE_CMD_EPOCH_IRQ_2_DIS 0x0000
+#define VFE_CMD_EPOCH_IRQ_2_ENA 0x8000
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int cfg;
+ unsigned int efs_cfg;
+ unsigned int frame_cfg;
+ unsigned int window_width_cfg;
+ unsigned int window_height_cfg;
+ unsigned int subsamp1_cfg;
+ unsigned int subsamp2_cfg;
+ unsigned int epoch_irq;
+} __attribute__((packed)) vfe_cmd_camif_cfg;
+
+
+
+/*
+ * Command to program the black level module
+ */
+
+#define VFE_CMD_BLACK_LVL_CFG 0x0005
+#define VFE_CMD_BLACK_LVL_CFG_LEN sizeof(vfe_cmd_black_lvl_cfg)
+
+#define VFE_CMD_BL_SEL_MANUAL 0x0000
+#define VFE_CMD_BL_SEL_AUTO 0x0001
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int black_lvl_sel;
+ unsigned int cfg_part[3];
+} __attribute__((packed)) vfe_cmd_black_lvl_cfg;
+
+
+/*
+ * Command to program the active region by cropping the region of interest
+ */
+
+#define VFE_CMD_ACTIVE_REGION_CFG 0x0006
+#define VFE_CMD_ACTIVE_REGION_CFG_LEN \
+ sizeof(vfe_cmd_active_region_cfg)
+
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int cfg_part1;
+ unsigned int cfg_part2;
+} __attribute__((packed)) vfe_cmd_active_region_cfg;
+
+
+
+/*
+ * Command to program the defective pixel correction(DPC) ,
+ * adaptive bayer filter (ABF) and demosaic modules
+ */
+
+#define VFE_CMD_DEMOSAIC_CFG 0x0007
+#define VFE_CMD_DEMOSAIC_CFG_LEN sizeof(vfe_cmd_demosaic_cfg)
+
+#define VFE_CMD_DEMOSAIC_PART1_ABF_EN_DIS 0x0000
+#define VFE_CMD_DEMOSAIC_PART1_ABF_EN_ENA 0x0001
+#define VFE_CMD_DEMOSAIC_PART1_DPC_EN_DIS 0x0000
+#define VFE_CMD_DEMOSAIC_PART1_DPC_EN_ENA 0x0002
+#define VFE_CMD_DEMOSAIC_PART1_FORCE_ABF_OFF 0x0000
+#define VFE_CMD_DEMOSAIC_PART1_FORCE_ABF_ON 0x0004
+#define VFE_CMD_DEMOSAIC_PART1_SLOPE_SHIFT_1 0x00000000
+#define VFE_CMD_DEMOSAIC_PART1_SLOPE_SHIFT_2 0x10000000
+#define VFE_CMD_DEMOSAIC_PART1_SLOPE_SHIFT_4 0x20000000
+#define VFE_CMD_DEMOSAIC_PART1_SLOPE_SHIFT_8 0x30000000
+#define VFE_CMD_DEMOSAIC_PART1_SLOPE_SHIFT_1_2 0x50000000
+#define VFE_CMD_DEMOSAIC_PART1_SLOPE_SHIFT_1_4 0x60000000
+#define VFE_CMD_DEMOSAIC_PART1_SLOPE_SHIFT_1_8 0x70000000
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int demosaic_part1;
+ unsigned int demosaic_part2;
+ unsigned int demosaic_part3;
+ unsigned int demosaic_part4;
+ unsigned int demosaic_part5;
+} __attribute__((packed)) vfe_cmd_demosaic_cfg;
+
+
+/*
+ * Command to program the ip format
+ */
+
+#define VFE_CMD_IP_FORMAT_CFG 0x0008
+#define VFE_CMD_IP_FORMAT_CFG_LEN \
+ sizeof(vfe_cmd_ip_format_cfg)
+
+#define VFE_CMD_IP_FORMAT_SEL_RGRG 0x0000
+#define VFE_CMD_IP_FORMAT_SEL_GRGR 0x0001
+#define VFE_CMD_IP_FORMAT_SEL_BGBG 0x0002
+#define VFE_CMD_IP_FORMAT_SEL_GBGB 0x0003
+#define VFE_CMD_IP_FORMAT_SEL_YCBYCR 0x0004
+#define VFE_CMD_IP_FORMAT_SEL_YCRYCB 0x0005
+#define VFE_CMD_IP_FORMAT_SEL_CBYCRY 0x0006
+#define VFE_CMD_IP_FORMAT_SEL_CRYCBY 0x0007
+#define VFE_CMD_IP_FORMAT_SEL_NO_CHROMA 0x0000
+#define VFE_CMD_IP_FORMAT_SEL_CHROMA 0x0008
+
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int ip_format_sel;
+ unsigned int balance_gains_part1;
+ unsigned int balance_gains_part2;
+} __attribute__((packed)) vfe_cmd_ip_format_cfg;
+
+
+
+/*
+ * Command to program max and min allowed op values
+ */
+
+#define VFE_CMD_OP_CLAMP_CFG 0x0009
+#define VFE_CMD_OP_CLAMP_CFG_LEN \
+ sizeof(vfe_cmd_op_clamp_cfg)
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int op_clamp_max;
+ unsigned int op_clamp_min;
+} __attribute__((packed)) vfe_cmd_op_clamp_cfg;
+
+
+/*
+ * Command to program chroma sub sample module
+ */
+
+#define VFE_CMD_CHROMA_SUBSAMPLE_CFG 0x000A
+#define VFE_CMD_CHROMA_SUBSAMPLE_CFG_LEN \
+ sizeof(vfe_cmd_chroma_subsample_cfg)
+
+#define VFE_CMD_CHROMA_SUBSAMP_SEL_H_INTERESTIAL_SAMPS 0x0000
+#define VFE_CMD_CHROMA_SUBSAMP_SEL_H_COSITED_SAMPS 0x0001
+#define VFE_CMD_CHROMA_SUBSAMP_SEL_V_INTERESTIAL_SAMPS 0x0000
+#define VFE_CMD_CHROMA_SUBSAMP_SEL_V_COSITED_SAMPS 0x0002
+#define VFE_CMD_CHROMA_SUBSAMP_SEL_H_SUBSAMP_DIS 0x0000
+#define VFE_CMD_CHROMA_SUBSAMP_SEL_H_SUBSAMP_ENA 0x0004
+#define VFE_CMD_CHROMA_SUBSAMP_SEL_V_SUBSAMP_DIS 0x0000
+#define VFE_CMD_CHROMA_SUBSAMP_SEL_V_SUBSAMP_ENA 0x0008
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int chroma_subsamp_sel;
+} __attribute__((packed)) vfe_cmd_chroma_subsample_cfg;
+
+
+/*
+ * Command to program the white balance module
+ */
+
+#define VFE_CMD_WHITE_BALANCE_CFG 0x000B
+#define VFE_CMD_WHITE_BALANCE_CFG_LEN \
+ sizeof(vfe_cmd_white_balance_cfg)
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int white_balance_gains;
+} __attribute__((packed)) vfe_cmd_white_balance_cfg;
+
+
+/*
+ * Command to program the color processing module
+ */
+
+#define VFE_CMD_COLOR_PROCESS_CFG 0x000C
+#define VFE_CMD_COLOR_PROCESS_CFG_LEN \
+ sizeof(vfe_cmd_color_process_cfg)
+
+#define VFE_CMD_COLOR_CORRE_PART7_Q7_FACTORS 0x0000
+#define VFE_CMD_COLOR_CORRE_PART7_Q8_FACTORS 0x0001
+#define VFE_CMD_COLOR_CORRE_PART7_Q9_FACTORS 0x0002
+#define VFE_CMD_COLOR_CORRE_PART7_Q10_FACTORS 0x0003
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int color_correction_part1;
+ unsigned int color_correction_part2;
+ unsigned int color_correction_part3;
+ unsigned int color_correction_part4;
+ unsigned int color_correction_part5;
+ unsigned int color_correction_part6;
+ unsigned int color_correction_part7;
+ unsigned int chroma_enhance_part1;
+ unsigned int chroma_enhance_part2;
+ unsigned int chroma_enhance_part3;
+ unsigned int chroma_enhance_part4;
+ unsigned int chroma_enhance_part5;
+ unsigned int luma_calc_part1;
+ unsigned int luma_calc_part2;
+} __attribute__((packed)) vfe_cmd_color_process_cfg;
+
+
+/*
+ * Command to program adaptive filter module
+ */
+
+#define VFE_CMD_ADP_FILTER_CFG 0x000D
+#define VFE_CMD_ADP_FILTER_CFG_LEN \
+ sizeof(vfe_cmd_adp_filter_cfg)
+
+#define VFE_CMD_ASF_CFG_PART_SMOOTH_FILTER_DIS 0x0000
+#define VFE_CMD_ASF_CFG_PART_SMOOTH_FILTER_ENA 0x0001
+#define VFE_CMD_ASF_CFG_PART_NO_SHARP_MODE 0x0000
+#define VFE_CMD_ASF_CFG_PART_SINGLE_FILTER 0x0002
+#define VFE_CMD_ASF_CFG_PART_DUAL_FILTER 0x0004
+#define VFE_CMD_ASF_CFG_PART_SHARP_MODE 0x0007
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int asf_cfg_part[7];
+} __attribute__((packed)) vfe_cmd_adp_filter_cfg;
+
+
+/*
+ * Command to program for frame skip pattern for op1 and op2
+ */
+
+#define VFE_CMD_FRAME_SKIP_CFG 0x000E
+#define VFE_CMD_FRAME_SKIP_CFG_LEN \
+ sizeof(vfe_cmd_frame_skip_cfg)
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int frame_skip_pattern_op1;
+ unsigned int frame_skip_pattern_op2;
+} __attribute__((packed)) vfe_cmd_frame_skip_cfg;
+
+
+/*
+ * Command to program field-of-view crop for digital zoom
+ */
+
+#define VFE_CMD_FOV_CROP 0x000F
+#define VFE_CMD_FOV_CROP_LEN sizeof(vfe_cmd_fov_crop)
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int fov_crop_part1;
+ unsigned int fov_crop_part2;
+} __attribute__((packed)) vfe_cmd_fov_crop;
+
+
+
+/*
+ * Command to program auto focus(AF) statistics module
+ */
+
+#define VFE_CMD_STATS_AUTOFOCUS_CFG 0x0010
+#define VFE_CMD_STATS_AUTOFOCUS_CFG_LEN \
+ sizeof(vfe_cmd_stats_autofocus_cfg)
+
+#define VFE_CMD_AF_STATS_SEL_STATS_DIS 0x0000
+#define VFE_CMD_AF_STATS_SEL_STATS_ENA 0x0001
+#define VFE_CMD_AF_STATS_SEL_PRI_FIXED 0x0000
+#define VFE_CMD_AF_STATS_SEL_PRI_VAR 0x0002
+#define VFE_CMD_AF_STATS_CFG_PART_METRIC_SUM 0x00000000
+#define VFE_CMD_AF_STATS_CFG_PART_METRIC_MAX 0x00200000
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int af_stats_sel;
+ unsigned int af_stats_cfg_part[8];
+ unsigned int af_stats_op_buf_hdr;
+ unsigned int af_stats_op_buf[3];
+} __attribute__((packed)) vfe_cmd_stats_autofocus_cfg;
+
+
+/*
+ * Command to program White balance(wb) and exposure (exp)
+ * statistics module
+ */
+
+#define VFE_CMD_STATS_WB_EXP_CFG 0x0011
+#define VFE_CMD_STATS_WB_EXP_CFG_LEN \
+ sizeof(vfe_cmd_stats_wb_exp_cfg)
+
+#define VFE_CMD_WB_EXP_STATS_SEL_STATS_DIS 0x0000
+#define VFE_CMD_WB_EXP_STATS_SEL_STATS_ENA 0x0001
+#define VFE_CMD_WB_EXP_STATS_SEL_PRI_FIXED 0x0000
+#define VFE_CMD_WB_EXP_STATS_SEL_PRI_VAR 0x0002
+
+#define VFE_CMD_WB_EXP_STATS_CFG_PART1_EXP_REG_8_8 0x0000
+#define VFE_CMD_WB_EXP_STATS_CFG_PART1_EXP_REG_16_16 0x0001
+#define VFE_CMD_WB_EXP_STATS_CFG_PART1_EXP_SREG_8_8 0x0000
+#define VFE_CMD_WB_EXP_STATS_CFG_PART1_EXP_SREG_4_4 0x0002
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int wb_exp_stats_sel;
+ unsigned int wb_exp_stats_cfg_part1;
+ unsigned int wb_exp_stats_cfg_part2;
+ unsigned int wb_exp_stats_cfg_part3;
+ unsigned int wb_exp_stats_cfg_part4;
+ unsigned int wb_exp_stats_op_buf_hdr;
+ unsigned int wb_exp_stats_op_buf[3];
+} __attribute__((packed)) vfe_cmd_stats_wb_exp_cfg;
+
+
+/*
+ * Command to program histogram(hg) stats module
+ */
+
+#define VFE_CMD_STATS_HG_CFG 0x0012
+#define VFE_CMD_STATS_HG_CFG_LEN \
+ sizeof(vfe_cmd_stats_hg_cfg)
+
+#define VFE_CMD_HG_STATS_SEL_PRI_FIXED 0x0000
+#define VFE_CMD_HG_STATS_SEL_PRI_VAR 0x0002
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int hg_stats_sel;
+ unsigned int hg_stats_cfg_part1;
+ unsigned int hg_stats_cfg_part2;
+ unsigned int hg_stats_op_buf_hdr;
+ unsigned int hg_stats_op_buf;
+} __attribute__((packed)) vfe_cmd_stats_hg_cfg;
+
+
+/*
+ * Command to acknowledge last MSG_VFE_OP1 message
+ */
+
+#define VFE_CMD_OP1_ACK 0x0013
+#define VFE_CMD_OP1_ACK_LEN sizeof(vfe_cmd_op1_ack)
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int op1_buf_y_addr;
+ unsigned int op1_buf_cbcr_addr;
+} __attribute__((packed)) vfe_cmd_op1_ack;
+
+
+
+/*
+ * Command to acknowledge last MSG_VFE_OP2 message
+ */
+
+#define VFE_CMD_OP2_ACK 0x0014
+#define VFE_CMD_OP2_ACK_LEN sizeof(vfe_cmd_op2_ack)
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int op2_buf_y_addr;
+ unsigned int op2_buf_cbcr_addr;
+} __attribute__((packed)) vfe_cmd_op2_ack;
+
+
+
+/*
+ * Command to acknowledge MSG_VFE_STATS_AUTOFOCUS msg
+ */
+
+#define VFE_CMD_STATS_AF_ACK 0x0015
+#define VFE_CMD_STATS_AF_ACK_LEN sizeof(vfe_cmd_stats_af_ack)
+
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int af_stats_op_buf;
+} __attribute__((packed)) vfe_cmd_stats_af_ack;
+
+
+/*
+ * Command to acknowledge MSG_VFE_STATS_WB_EXP msg
+ */
+
+#define VFE_CMD_STATS_WB_EXP_ACK 0x0016
+#define VFE_CMD_STATS_WB_EXP_ACK_LEN sizeof(vfe_cmd_stats_wb_exp_ack)
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int wb_exp_stats_op_buf;
+} __attribute__((packed)) vfe_cmd_stats_wb_exp_ack;
+
+
+/*
+ * Command to acknowledge MSG_VFE_EPOCH1 message
+ */
+
+#define VFE_CMD_EPOCH1_ACK 0x0017
+#define VFE_CMD_EPOCH1_ACK_LEN sizeof(vfe_cmd_epoch1_ack)
+
+typedef struct {
+ unsigned short cmd_id;
+} __attribute__((packed)) vfe_cmd_epoch1_ack;
+
+
+/*
+ * Command to acknowledge MSG_VFE_EPOCH2 message
+ */
+
+#define VFE_CMD_EPOCH2_ACK 0x0018
+#define VFE_CMD_EPOCH2_ACK_LEN sizeof(vfe_cmd_epoch2_ack)
+
+typedef struct {
+ unsigned short cmd_id;
+} __attribute__((packed)) vfe_cmd_epoch2_ack;
+
+
+
+/*
+ * Command to configure, enable or disable synchronous timer1
+ */
+
+#define VFE_CMD_SYNC_TIMER1_CFG 0x0019
+#define VFE_CMD_SYNC_TIMER1_CFG_LEN \
+ sizeof(vfe_cmd_sync_timer1_cfg)
+
+#define VFE_CMD_SYNC_T1_CFG_PART1_TIMER_DIS 0x0000
+#define VFE_CMD_SYNC_T1_CFG_PART1_TIMER_ENA 0x0001
+#define VFE_CMD_SYNC_T1_CFG_PART1_POL_HIGH 0x0000
+#define VFE_CMD_SYNC_T1_CFG_PART1_POL_LOW 0x0002
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int sync_t1_cfg_part1;
+ unsigned int sync_t1_h_sync_countdown;
+ unsigned int sync_t1_pclk_countdown;
+ unsigned int sync_t1_duration;
+} __attribute__((packed)) vfe_cmd_sync_timer1_cfg;
+
+
+/*
+ * Command to configure, enable or disable synchronous timer1
+ */
+
+#define VFE_CMD_SYNC_TIMER2_CFG 0x001A
+#define VFE_CMD_SYNC_TIMER2_CFG_LEN \
+ sizeof(vfe_cmd_sync_timer2_cfg)
+
+#define VFE_CMD_SYNC_T2_CFG_PART1_TIMER_DIS 0x0000
+#define VFE_CMD_SYNC_T2_CFG_PART1_TIMER_ENA 0x0001
+#define VFE_CMD_SYNC_T2_CFG_PART1_POL_HIGH 0x0000
+#define VFE_CMD_SYNC_T2_CFG_PART1_POL_LOW 0x0002
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int sync_t2_cfg_part1;
+ unsigned int sync_t2_h_sync_countdown;
+ unsigned int sync_t2_pclk_countdown;
+ unsigned int sync_t2_duration;
+} __attribute__((packed)) vfe_cmd_sync_timer2_cfg;
+
+
+/*
+ * Command to configure and start asynchronous timer1
+ */
+
+#define VFE_CMD_ASYNC_TIMER1_START 0x001B
+#define VFE_CMD_ASYNC_TIMER1_START_LEN \
+ sizeof(vfe_cmd_async_timer1_start)
+
+#define VFE_CMD_ASYNC_T1_POLARITY_A_HIGH 0x0000
+#define VFE_CMD_ASYNC_T1_POLARITY_A_LOW 0x0001
+#define VFE_CMD_ASYNC_T1_POLARITY_B_HIGH 0x0000
+#define VFE_CMD_ASYNC_T1_POLARITY_B_LOW 0x0002
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int async_t1a_cfg;
+ unsigned int async_t1b_cfg;
+ unsigned int async_t1_polarity;
+} __attribute__((packed)) vfe_cmd_async_timer1_start;
+
+
+/*
+ * Command to configure and start asynchronous timer2
+ */
+
+#define VFE_CMD_ASYNC_TIMER2_START 0x001C
+#define VFE_CMD_ASYNC_TIMER2_START_LEN \
+ sizeof(vfe_cmd_async_timer2_start)
+
+#define VFE_CMD_ASYNC_T2_POLARITY_A_HIGH 0x0000
+#define VFE_CMD_ASYNC_T2_POLARITY_A_LOW 0x0001
+#define VFE_CMD_ASYNC_T2_POLARITY_B_HIGH 0x0000
+#define VFE_CMD_ASYNC_T2_POLARITY_B_LOW 0x0002
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int async_t2a_cfg;
+ unsigned int async_t2b_cfg;
+ unsigned int async_t2_polarity;
+} __attribute__((packed)) vfe_cmd_async_timer2_start;
+
+
+/*
+ * Command to program partial configurations of auto focus(af)
+ */
+
+#define VFE_CMD_STATS_AF_UPDATE 0x001D
+#define VFE_CMD_STATS_AF_UPDATE_LEN \
+ sizeof(vfe_cmd_stats_af_update)
+
+#define VFE_CMD_AF_UPDATE_PART1_WINDOW_ONE 0x00000000
+#define VFE_CMD_AF_UPDATE_PART1_WINDOW_MULTI 0x80000000
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int af_update_part1;
+ unsigned int af_update_part2;
+} __attribute__((packed)) vfe_cmd_stats_af_update;
+
+
+/*
+ * Command to program partial cfg of wb and exp
+ */
+
+#define VFE_CMD_STATS_WB_EXP_UPDATE 0x001E
+#define VFE_CMD_STATS_WB_EXP_UPDATE_LEN \
+ sizeof(vfe_cmd_stats_wb_exp_update)
+
+#define VFE_CMD_WB_EXP_UPDATE_PART1_REGIONS_8_8 0x0000
+#define VFE_CMD_WB_EXP_UPDATE_PART1_REGIONS_16_16 0x0001
+#define VFE_CMD_WB_EXP_UPDATE_PART1_SREGIONS_8_8 0x0000
+#define VFE_CMD_WB_EXP_UPDATE_PART1_SREGIONS_4_4 0x0002
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int wb_exp_update_part1;
+ unsigned int wb_exp_update_part2;
+ unsigned int wb_exp_update_part3;
+ unsigned int wb_exp_update_part4;
+} __attribute__((packed)) vfe_cmd_stats_wb_exp_update;
+
+
+
+/*
+ * Command to re program the CAMIF FRAME CONFIG settings
+ */
+
+#define VFE_CMD_UPDATE_CAMIF_FRAME_CFG 0x001F
+#define VFE_CMD_UPDATE_CAMIF_FRAME_CFG_LEN \
+ sizeof(vfe_cmd_update_camif_frame_cfg)
+
+typedef struct {
+ unsigned int cmd_id;
+ unsigned int camif_frame_cfg;
+} __attribute__((packed)) vfe_cmd_update_camif_frame_cfg;
+
+
+#endif
diff --git a/drivers/staging/dream/include/mach/qdsp5/qdsp5vfemsg.h b/drivers/staging/dream/include/mach/qdsp5/qdsp5vfemsg.h
new file mode 100644
index 00000000000..0053cfb65ba
--- /dev/null
+++ b/drivers/staging/dream/include/mach/qdsp5/qdsp5vfemsg.h
@@ -0,0 +1,290 @@
+#ifndef QDSP5VFEMSGI_H
+#define QDSP5VFEMSGI_H
+
+/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
+
+ V F E I N T E R N A L M E S S A G E S
+
+GENERAL DESCRIPTION
+ This file contains defintions of format blocks of commands
+ that are sent by VFE Task
+
+REFERENCES
+ None
+
+EXTERNALIZED FUNCTIONS
+ None
+
+Copyright(c) 1992 - 2008 by QUALCOMM, Incorporated.
+
+This software is licensed under the terms of the GNU General Public
+License version 2, as published by the Free Software Foundation, and
+may be copied, distributed, and modified under those terms.
+
+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.
+
+*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
+/*===========================================================================
+
+ EDIT HISTORY FOR FILE
+
+This section contains comments describing changes made to this file.
+Notice that changes are listed in reverse chronological order.
+
+$Header: //source/qcom/qct/multimedia2/AdspSvc/7XXX/qdsp5cmd/video/qdsp5vfemsg.h#2 $ $DateTime: 2008/07/30 10:50:23 $ $Author: pavanr $
+Revision History:
+
+when who what, where, why
+-------- --- ----------------------------------------------------------
+06/12/08 sv initial version
+===========================================================================*/
+
+
+/*
+ * Message to acknowledge CMD_VFE_REST command
+ */
+
+#define VFE_MSG_RESET_ACK 0x0000
+#define VFE_MSG_RESET_ACK_LEN sizeof(vfe_msg_reset_ack)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_reset_ack;
+
+
+/*
+ * Message to acknowledge CMD_VFE_START command
+ */
+
+#define VFE_MSG_START_ACK 0x0001
+#define VFE_MSG_START_ACK_LEN sizeof(vfe_msg_start_ack)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_start_ack;
+
+/*
+ * Message to acknowledge CMD_VFE_STOP command
+ */
+
+#define VFE_MSG_STOP_ACK 0x0002
+#define VFE_MSG_STOP_ACK_LEN sizeof(vfe_msg_stop_ack)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_stop_ack;
+
+
+/*
+ * Message to acknowledge CMD_VFE_UPDATE command
+ */
+
+#define VFE_MSG_UPDATE_ACK 0x0003
+#define VFE_MSG_UPDATE_ACK_LEN sizeof(vfe_msg_update_ack)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_update_ack;
+
+
+/*
+ * Message to notify the ARM that snapshot processing is complete
+ * and that the VFE is now STATE_VFE_IDLE
+ */
+
+#define VFE_MSG_SNAPSHOT_DONE 0x0004
+#define VFE_MSG_SNAPSHOT_DONE_LEN \
+ sizeof(vfe_msg_snapshot_done)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_snapshot_done;
+
+
+
+/*
+ * Message to notify ARM that illegal cmd was received and
+ * system is in the IDLE state
+ */
+
+#define VFE_MSG_ILLEGAL_CMD 0x0005
+#define VFE_MSG_ILLEGAL_CMD_LEN \
+ sizeof(vfe_msg_illegal_cmd)
+
+typedef struct {
+ unsigned int status;
+} __attribute__((packed)) vfe_msg_illegal_cmd;
+
+
+/*
+ * Message to notify ARM that op1 buf is full and ready
+ */
+
+#define VFE_MSG_OP1 0x0006
+#define VFE_MSG_OP1_LEN sizeof(vfe_msg_op1)
+
+typedef struct {
+ unsigned int op1_buf_y_addr;
+ unsigned int op1_buf_cbcr_addr;
+ unsigned int black_level_even_col;
+ unsigned int black_level_odd_col;
+ unsigned int defect_pixels_detected;
+ unsigned int asf_max_edge;
+} __attribute__((packed)) vfe_msg_op1;
+
+
+/*
+ * Message to notify ARM that op2 buf is full and ready
+ */
+
+#define VFE_MSG_OP2 0x0007
+#define VFE_MSG_OP2_LEN sizeof(vfe_msg_op2)
+
+typedef struct {
+ unsigned int op2_buf_y_addr;
+ unsigned int op2_buf_cbcr_addr;
+ unsigned int black_level_even_col;
+ unsigned int black_level_odd_col;
+ unsigned int defect_pixels_detected;
+ unsigned int asf_max_edge;
+} __attribute__((packed)) vfe_msg_op2;
+
+
+/*
+ * Message to notify ARM that autofocus(af) stats are ready
+ */
+
+#define VFE_MSG_STATS_AF 0x0008
+#define VFE_MSG_STATS_AF_LEN sizeof(vfe_msg_stats_af)
+
+typedef struct {
+ unsigned int af_stats_op_buffer;
+} __attribute__((packed)) vfe_msg_stats_af;
+
+
+/*
+ * Message to notify ARM that white balance(wb) and exposure (exp)
+ * stats are ready
+ */
+
+#define VFE_MSG_STATS_WB_EXP 0x0009
+#define VFE_MSG_STATS_WB_EXP_LEN \
+ sizeof(vfe_msg_stats_wb_exp)
+
+typedef struct {
+ unsigned int wb_exp_stats_op_buf;
+} __attribute__((packed)) vfe_msg_stats_wb_exp;
+
+
+/*
+ * Message to notify the ARM that histogram(hg) stats are ready
+ */
+
+#define VFE_MSG_STATS_HG 0x000A
+#define VFE_MSG_STATS_HG_LEN sizeof(vfe_msg_stats_hg)
+
+typedef struct {
+ unsigned int hg_stats_op_buf;
+} __attribute__((packed)) vfe_msg_stats_hg;
+
+
+/*
+ * Message to notify the ARM that epoch1 event occurred in the CAMIF
+ */
+
+#define VFE_MSG_EPOCH1 0x000B
+#define VFE_MSG_EPOCH1_LEN sizeof(vfe_msg_epoch1)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_epoch1;
+
+
+/*
+ * Message to notify the ARM that epoch2 event occurred in the CAMIF
+ */
+
+#define VFE_MSG_EPOCH2 0x000C
+#define VFE_MSG_EPOCH2_LEN sizeof(vfe_msg_epoch2)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_epoch2;
+
+
+/*
+ * Message to notify the ARM that sync timer1 op is completed
+ */
+
+#define VFE_MSG_SYNC_T1_DONE 0x000D
+#define VFE_MSG_SYNC_T1_DONE_LEN sizeof(vfe_msg_sync_t1_done)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_sync_t1_done;
+
+
+/*
+ * Message to notify the ARM that sync timer2 op is completed
+ */
+
+#define VFE_MSG_SYNC_T2_DONE 0x000E
+#define VFE_MSG_SYNC_T2_DONE_LEN sizeof(vfe_msg_sync_t2_done)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_sync_t2_done;
+
+
+/*
+ * Message to notify the ARM that async t1 operation completed
+ */
+
+#define VFE_MSG_ASYNC_T1_DONE 0x000F
+#define VFE_MSG_ASYNC_T1_DONE_LEN sizeof(vfe_msg_async_t1_done)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_async_t1_done;
+
+
+
+/*
+ * Message to notify the ARM that async t2 operation completed
+ */
+
+#define VFE_MSG_ASYNC_T2_DONE 0x0010
+#define VFE_MSG_ASYNC_T2_DONE_LEN sizeof(vfe_msg_async_t2_done)
+
+typedef struct {
+} __attribute__((packed)) vfe_msg_async_t2_done;
+
+
+
+/*
+ * Message to notify the ARM that an error has occurred
+ */
+
+#define VFE_MSG_ERROR 0x0011
+#define VFE_MSG_ERROR_LEN sizeof(vfe_msg_error)
+
+#define VFE_MSG_ERR_COND_NO_CAMIF_ERR 0x0000
+#define VFE_MSG_ERR_COND_CAMIF_ERR 0x0001
+#define VFE_MSG_ERR_COND_OP1_Y_NO_BUS_OF 0x0000
+#define VFE_MSG_ERR_COND_OP1_Y_BUS_OF 0x0002
+#define VFE_MSG_ERR_COND_OP1_CBCR_NO_BUS_OF 0x0000
+#define VFE_MSG_ERR_COND_OP1_CBCR_BUS_OF 0x0004
+#define VFE_MSG_ERR_COND_OP2_Y_NO_BUS_OF 0x0000
+#define VFE_MSG_ERR_COND_OP2_Y_BUS_OF 0x0008
+#define VFE_MSG_ERR_COND_OP2_CBCR_NO_BUS_OF 0x0000
+#define VFE_MSG_ERR_COND_OP2_CBCR_BUS_OF 0x0010
+#define VFE_MSG_ERR_COND_AF_NO_BUS_OF 0x0000
+#define VFE_MSG_ERR_COND_AF_BUS_OF 0x0020
+#define VFE_MSG_ERR_COND_WB_EXP_NO_BUS_OF 0x0000
+#define VFE_MSG_ERR_COND_WB_EXP_BUS_OF 0x0040
+#define VFE_MSG_ERR_COND_NO_AXI_ERR 0x0000
+#define VFE_MSG_ERR_COND_AXI_ERR 0x0080
+
+#define VFE_MSG_CAMIF_STS_IDLE 0x0000
+#define VFE_MSG_CAMIF_STS_CAPTURE_DATA 0x0001
+
+typedef struct {
+ unsigned int err_cond;
+ unsigned int camif_sts;
+} __attribute__((packed)) vfe_msg_error;
+
+
+#endif
diff --git a/drivers/staging/dream/include/media/msm_camera.h b/drivers/staging/dream/include/media/msm_camera.h
new file mode 100644
index 00000000000..09812d62cc1
--- /dev/null
+++ b/drivers/staging/dream/include/media/msm_camera.h
@@ -0,0 +1,388 @@
+/*
+ * Copyright (C) 2008-2009 QUALCOMM Incorporated.
+ */
+#ifndef __LINUX_MSM_CAMERA_H
+#define __LINUX_MSM_CAMERA_H
+
+#include <linux/types.h>
+#include <asm/sizes.h>
+#include <linux/ioctl.h>
+
+#define MSM_CAM_IOCTL_MAGIC 'm'
+
+#define MSM_CAM_IOCTL_GET_SENSOR_INFO \
+ _IOR(MSM_CAM_IOCTL_MAGIC, 1, struct msm_camsensor_info *)
+
+#define MSM_CAM_IOCTL_REGISTER_PMEM \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 2, struct msm_pmem_info *)
+
+#define MSM_CAM_IOCTL_UNREGISTER_PMEM \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 3, unsigned)
+
+#define MSM_CAM_IOCTL_CTRL_COMMAND \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 4, struct msm_ctrl_cmd *)
+
+#define MSM_CAM_IOCTL_CONFIG_VFE \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 5, struct msm_camera_vfe_cfg_cmd *)
+
+#define MSM_CAM_IOCTL_GET_STATS \
+ _IOR(MSM_CAM_IOCTL_MAGIC, 6, struct msm_camera_stats_event_ctrl *)
+
+#define MSM_CAM_IOCTL_GETFRAME \
+ _IOR(MSM_CAM_IOCTL_MAGIC, 7, struct msm_camera_get_frame *)
+
+#define MSM_CAM_IOCTL_ENABLE_VFE \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 8, struct camera_enable_cmd *)
+
+#define MSM_CAM_IOCTL_CTRL_CMD_DONE \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 9, struct camera_cmd *)
+
+#define MSM_CAM_IOCTL_CONFIG_CMD \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 10, struct camera_cmd *)
+
+#define MSM_CAM_IOCTL_DISABLE_VFE \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 11, struct camera_enable_cmd *)
+
+#define MSM_CAM_IOCTL_PAD_REG_RESET2 \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 12, struct camera_enable_cmd *)
+
+#define MSM_CAM_IOCTL_VFE_APPS_RESET \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 13, struct camera_enable_cmd *)
+
+#define MSM_CAM_IOCTL_RELEASE_FRAME_BUFFER \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 14, struct camera_enable_cmd *)
+
+#define MSM_CAM_IOCTL_RELEASE_STATS_BUFFER \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 15, struct msm_stats_buf *)
+
+#define MSM_CAM_IOCTL_AXI_CONFIG \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 16, struct msm_camera_vfe_cfg_cmd *)
+
+#define MSM_CAM_IOCTL_GET_PICTURE \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 17, struct msm_camera_ctrl_cmd *)
+
+#define MSM_CAM_IOCTL_SET_CROP \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 18, struct crop_info *)
+
+#define MSM_CAM_IOCTL_PICT_PP \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 19, uint8_t *)
+
+#define MSM_CAM_IOCTL_PICT_PP_DONE \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 20, struct msm_snapshot_pp_status *)
+
+#define MSM_CAM_IOCTL_SENSOR_IO_CFG \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 21, struct sensor_cfg_data *)
+
+#define MSM_CAMERA_LED_OFF 0
+#define MSM_CAMERA_LED_LOW 1
+#define MSM_CAMERA_LED_HIGH 2
+
+#define MSM_CAM_IOCTL_FLASH_LED_CFG \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 22, unsigned *)
+
+#define MSM_CAM_IOCTL_UNBLOCK_POLL_FRAME \
+ _IO(MSM_CAM_IOCTL_MAGIC, 23)
+
+#define MSM_CAM_IOCTL_CTRL_COMMAND_2 \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 24, struct msm_ctrl_cmd *)
+
+#define MAX_SENSOR_NUM 3
+#define MAX_SENSOR_NAME 32
+
+#define MSM_CAM_CTRL_CMD_DONE 0
+#define MSM_CAM_SENSOR_VFE_CMD 1
+
+/*****************************************************
+ * structure
+ *****************************************************/
+
+/* define five type of structures for userspace <==> kernel
+ * space communication:
+ * command 1 - 2 are from userspace ==> kernel
+ * command 3 - 4 are from kernel ==> userspace
+ *
+ * 1. control command: control command(from control thread),
+ * control status (from config thread);
+ */
+struct msm_ctrl_cmd {
+ uint16_t type;
+ uint16_t length;
+ void *value;
+ uint16_t status;
+ uint32_t timeout_ms;
+ int resp_fd; /* FIXME: to be used by the kernel, pass-through for now */
+};
+
+struct msm_vfe_evt_msg {
+ unsigned short type; /* 1 == event (RPC), 0 == message (adsp) */
+ unsigned short msg_id;
+ unsigned int len; /* size in, number of bytes out */
+ void *data;
+};
+
+#define MSM_CAM_RESP_CTRL 0
+#define MSM_CAM_RESP_STAT_EVT_MSG 1
+#define MSM_CAM_RESP_V4L2 2
+#define MSM_CAM_RESP_MAX 3
+
+/* this one is used to send ctrl/status up to config thread */
+struct msm_stats_event_ctrl {
+ /* 0 - ctrl_cmd from control thread,
+ * 1 - stats/event kernel,
+ * 2 - V4L control or read request */
+ int resptype;
+ int timeout_ms;
+ struct msm_ctrl_cmd ctrl_cmd;
+ /* struct vfe_event_t stats_event; */
+ struct msm_vfe_evt_msg stats_event;
+};
+
+/* 2. config command: config command(from config thread); */
+struct msm_camera_cfg_cmd {
+ /* what to config:
+ * 1 - sensor config, 2 - vfe config */
+ uint16_t cfg_type;
+
+ /* sensor config type */
+ uint16_t cmd_type;
+ uint16_t queue;
+ uint16_t length;
+ void *value;
+};
+
+#define CMD_GENERAL 0
+#define CMD_AXI_CFG_OUT1 1
+#define CMD_AXI_CFG_SNAP_O1_AND_O2 2
+#define CMD_AXI_CFG_OUT2 3
+#define CMD_PICT_T_AXI_CFG 4
+#define CMD_PICT_M_AXI_CFG 5
+#define CMD_RAW_PICT_AXI_CFG 6
+#define CMD_STATS_AXI_CFG 7
+#define CMD_STATS_AF_AXI_CFG 8
+#define CMD_FRAME_BUF_RELEASE 9
+#define CMD_PREV_BUF_CFG 10
+#define CMD_SNAP_BUF_RELEASE 11
+#define CMD_SNAP_BUF_CFG 12
+#define CMD_STATS_DISABLE 13
+#define CMD_STATS_ENABLE 14
+#define CMD_STATS_AF_ENABLE 15
+#define CMD_STATS_BUF_RELEASE 16
+#define CMD_STATS_AF_BUF_RELEASE 17
+#define UPDATE_STATS_INVALID 18
+
+/* vfe config command: config command(from config thread)*/
+struct msm_vfe_cfg_cmd {
+ int cmd_type;
+ uint16_t length;
+ void *value;
+};
+
+#define MAX_CAMERA_ENABLE_NAME_LEN 32
+struct camera_enable_cmd {
+ char name[MAX_CAMERA_ENABLE_NAME_LEN];
+};
+
+#define MSM_PMEM_OUTPUT1 0
+#define MSM_PMEM_OUTPUT2 1
+#define MSM_PMEM_OUTPUT1_OUTPUT2 2
+#define MSM_PMEM_THUMBAIL 3
+#define MSM_PMEM_MAINIMG 4
+#define MSM_PMEM_RAW_MAINIMG 5
+#define MSM_PMEM_AEC_AWB 6
+#define MSM_PMEM_AF 7
+#define MSM_PMEM_MAX 8
+
+#define FRAME_PREVIEW_OUTPUT1 0
+#define FRAME_PREVIEW_OUTPUT2 1
+#define FRAME_SNAPSHOT 2
+#define FRAME_THUMBAIL 3
+#define FRAME_RAW_SNAPSHOT 4
+#define FRAME_MAX 5
+
+struct msm_pmem_info {
+ int type;
+ int fd;
+ void *vaddr;
+ uint32_t y_off;
+ uint32_t cbcr_off;
+ uint8_t active;
+};
+
+struct outputCfg {
+ uint32_t height;
+ uint32_t width;
+
+ uint32_t window_height_firstline;
+ uint32_t window_height_lastline;
+};
+
+#define OUTPUT_1 0
+#define OUTPUT_2 1
+#define OUTPUT_1_AND_2 2
+#define CAMIF_TO_AXI_VIA_OUTPUT_2 3
+#define OUTPUT_1_AND_CAMIF_TO_AXI_VIA_OUTPUT_2 4
+#define OUTPUT_2_AND_CAMIF_TO_AXI_VIA_OUTPUT_1 5
+#define LAST_AXI_OUTPUT_MODE_ENUM = OUTPUT_2_AND_CAMIF_TO_AXI_VIA_OUTPUT_1 6
+
+#define MSM_FRAME_PREV_1 0
+#define MSM_FRAME_PREV_2 1
+#define MSM_FRAME_ENC 2
+
+struct msm_frame {
+ int path;
+ unsigned long buffer;
+ uint32_t y_off;
+ uint32_t cbcr_off;
+ int fd;
+
+ void *cropinfo;
+ int croplen;
+};
+
+#define STAT_AEAW 0
+#define STAT_AF 1
+#define STAT_MAX 2
+
+struct msm_stats_buf {
+ int type;
+ unsigned long buffer;
+ int fd;
+};
+
+#define MSM_V4L2_VID_CAP_TYPE 0
+#define MSM_V4L2_STREAM_ON 1
+#define MSM_V4L2_STREAM_OFF 2
+#define MSM_V4L2_SNAPSHOT 3
+#define MSM_V4L2_QUERY_CTRL 4
+#define MSM_V4L2_GET_CTRL 5
+#define MSM_V4L2_SET_CTRL 6
+#define MSM_V4L2_QUERY 7
+#define MSM_V4L2_MAX 8
+
+struct crop_info {
+ void *info;
+ int len;
+};
+
+struct msm_postproc {
+ int ftnum;
+ struct msm_frame fthumnail;
+ int fmnum;
+ struct msm_frame fmain;
+};
+
+struct msm_snapshot_pp_status {
+ void *status;
+};
+
+#define CFG_SET_MODE 0
+#define CFG_SET_EFFECT 1
+#define CFG_START 2
+#define CFG_PWR_UP 3
+#define CFG_PWR_DOWN 4
+#define CFG_WRITE_EXPOSURE_GAIN 5
+#define CFG_SET_DEFAULT_FOCUS 6
+#define CFG_MOVE_FOCUS 7
+#define CFG_REGISTER_TO_REAL_GAIN 8
+#define CFG_REAL_TO_REGISTER_GAIN 9
+#define CFG_SET_FPS 10
+#define CFG_SET_PICT_FPS 11
+#define CFG_SET_BRIGHTNESS 12
+#define CFG_SET_CONTRAST 13
+#define CFG_SET_ZOOM 14
+#define CFG_SET_EXPOSURE_MODE 15
+#define CFG_SET_WB 16
+#define CFG_SET_ANTIBANDING 17
+#define CFG_SET_EXP_GAIN 18
+#define CFG_SET_PICT_EXP_GAIN 19
+#define CFG_SET_LENS_SHADING 20
+#define CFG_GET_PICT_FPS 21
+#define CFG_GET_PREV_L_PF 22
+#define CFG_GET_PREV_P_PL 23
+#define CFG_GET_PICT_L_PF 24
+#define CFG_GET_PICT_P_PL 25
+#define CFG_GET_AF_MAX_STEPS 26
+#define CFG_GET_PICT_MAX_EXP_LC 27
+#define CFG_MAX 28
+
+#define MOVE_NEAR 0
+#define MOVE_FAR 1
+
+#define SENSOR_PREVIEW_MODE 0
+#define SENSOR_SNAPSHOT_MODE 1
+#define SENSOR_RAW_SNAPSHOT_MODE 2
+
+#define SENSOR_QTR_SIZE 0
+#define SENSOR_FULL_SIZE 1
+#define SENSOR_INVALID_SIZE 2
+
+#define CAMERA_EFFECT_OFF 0
+#define CAMERA_EFFECT_MONO 1
+#define CAMERA_EFFECT_NEGATIVE 2
+#define CAMERA_EFFECT_SOLARIZE 3
+#define CAMERA_EFFECT_PASTEL 4
+#define CAMERA_EFFECT_MOSAIC 5
+#define CAMERA_EFFECT_RESIZE 6
+#define CAMERA_EFFECT_SEPIA 7
+#define CAMERA_EFFECT_POSTERIZE 8
+#define CAMERA_EFFECT_WHITEBOARD 9
+#define CAMERA_EFFECT_BLACKBOARD 10
+#define CAMERA_EFFECT_AQUA 11
+#define CAMERA_EFFECT_MAX 12
+
+struct sensor_pict_fps {
+ uint16_t prevfps;
+ uint16_t pictfps;
+};
+
+struct exp_gain_cfg {
+ uint16_t gain;
+ uint32_t line;
+};
+
+struct focus_cfg {
+ int32_t steps;
+ int dir;
+};
+
+struct fps_cfg {
+ uint16_t f_mult;
+ uint16_t fps_div;
+ uint32_t pict_fps_div;
+};
+
+struct sensor_cfg_data {
+ int cfgtype;
+ int mode;
+ int rs;
+ uint8_t max_steps;
+
+ union {
+ int8_t effect;
+ uint8_t lens_shading;
+ uint16_t prevl_pf;
+ uint16_t prevp_pl;
+ uint16_t pictl_pf;
+ uint16_t pictp_pl;
+ uint32_t pict_max_exp_lc;
+ uint16_t p_fps;
+ struct sensor_pict_fps gfps;
+ struct exp_gain_cfg exp_gain;
+ struct focus_cfg focus;
+ struct fps_cfg fps;
+ } cfg;
+};
+
+#define GET_NAME 0
+#define GET_PREVIEW_LINE_PER_FRAME 1
+#define GET_PREVIEW_PIXELS_PER_LINE 2
+#define GET_SNAPSHOT_LINE_PER_FRAME 3
+#define GET_SNAPSHOT_PIXELS_PER_LINE 4
+#define GET_SNAPSHOT_FPS 5
+#define GET_SNAPSHOT_MAX_EP_LINE_CNT 6
+
+struct msm_camsensor_info {
+ char name[MAX_SENSOR_NAME];
+ uint8_t flash_enabled;
+};
+#endif /* __LINUX_MSM_CAMERA_H */
diff --git a/drivers/staging/dream/pmem.c b/drivers/staging/dream/pmem.c
index def64681234..503ba212dc9 100644
--- a/drivers/staging/dream/pmem.c
+++ b/drivers/staging/dream/pmem.c
@@ -37,17 +37,17 @@
* the file should not be released until put_pmem_file is called */
#define PMEM_FLAGS_BUSY 0x1
/* indicates that this is a suballocation of a larger master range */
-#define PMEM_FLAGS_CONNECTED 0x1 << 1
+#define PMEM_FLAGS_CONNECTED ( 0x1 << 1 )
/* indicates this is a master and not a sub allocation and that it is mmaped */
-#define PMEM_FLAGS_MASTERMAP 0x1 << 2
+#define PMEM_FLAGS_MASTERMAP ( 0x1 << 2 )
/* submap and unsubmap flags indicate:
* 00: subregion has never been mmaped
* 10: subregion has been mmaped, reference to the mm was taken
* 11: subretion has ben released, refernece to the mm still held
* 01: subretion has been released, reference to the mm has been released
*/
-#define PMEM_FLAGS_SUBMAP 0x1 << 3
-#define PMEM_FLAGS_UNSUBMAP 0x1 << 4
+#define PMEM_FLAGS_SUBMAP ( 0x1 << 3 )
+#define PMEM_FLAGS_UNSUBMAP ( 0x1 << 4 )
struct pmem_data {
@@ -91,7 +91,7 @@ struct pmem_region_node {
#define PMEM_DEBUG_MSGS 0
#if PMEM_DEBUG_MSGS
-#define DLOG(fmt,args...) \
+#define DLOG(fmt, args...) \
do { printk(KERN_INFO "[%s:%s:%d] "fmt, __FILE__, __func__, __LINE__, \
##args); } \
while (0)
@@ -152,7 +152,7 @@ struct pmem_info {
static struct pmem_info pmem[PMEM_MAX_DEVICES];
static int id_count;
-#define PMEM_IS_FREE(id, index) !(pmem[id].bitmap[index].allocated)
+#define PMEM_IS_FREE(id, index) ( !(pmem[id].bitmap[index].allocated) )
#define PMEM_ORDER(id, index) pmem[id].bitmap[index].order
#define PMEM_BUDDY_INDEX(id, index) (index ^ (1 << PMEM_ORDER(id, index)))
#define PMEM_NEXT_INDEX(id, index) (index + (1 << PMEM_ORDER(id, index)))
@@ -708,9 +708,8 @@ int get_pmem_addr(struct file *file, unsigned long *start,
struct pmem_data *data;
int id;
- if (!is_pmem_file(file) || !has_allocation(file)) {
+ if (!is_pmem_file(file) || !has_allocation(file))
return -1;
- }
data = (struct pmem_data *)file->private_data;
if (data->index == -1) {
@@ -789,9 +788,8 @@ void flush_pmem_file(struct file *file, unsigned long offset, unsigned long len)
struct list_head *elt;
void *flush_start, *flush_end;
- if (!is_pmem_file(file) || !has_allocation(file)) {
+ if (!is_pmem_file(file) || !has_allocation(file))
return;
- }
id = get_id(file);
data = (struct pmem_data *)file->private_data;
@@ -833,7 +831,7 @@ static int pmem_connect(unsigned long connect, struct file *file)
src_file = fget_light(connect, &put_needed);
DLOG("connect %p to %p\n", file, src_file);
if (!src_file) {
- printk("pmem: src file not found!\n");
+ printk(KERN_INFO "pmem: src file not found!\n");
ret = -EINVAL;
goto err_no_file;
}
@@ -846,7 +844,7 @@ static int pmem_connect(unsigned long connect, struct file *file)
src_data = (struct pmem_data *)src_file->private_data;
if (has_allocation(file) && (data->index != src_data->index)) {
- printk("pmem: file is already mapped but doesn't match this"
+ printk(KERN_INFO "pmem: file is already mapped but doesn't match this"
" src_file!\n");
ret = -EINVAL;
goto err_bad_file;
@@ -885,7 +883,7 @@ lock_mm:
mm = get_task_mm(data->task);
if (!mm) {
#if PMEM_DEBUG
- printk("pmem: can't remap task is gone!\n");
+ printk(KERN_DEBUG "pmem: can't remap task is gone!\n");
#endif
up_read(&data->sem);
return -1;
@@ -936,7 +934,7 @@ int pmem_remap(struct pmem_region *region, struct file *file,
if (unlikely(!PMEM_IS_PAGE_ALIGNED(region->offset) ||
!PMEM_IS_PAGE_ALIGNED(region->len))) {
#if PMEM_DEBUG
- printk("pmem: request for unaligned pmem suballocation "
+ printk(KERN_DEBUG "pmem: request for unaligned pmem suballocation "
"%lx %lx\n", region->offset, region->len);
#endif
return -EINVAL;
diff --git a/drivers/staging/dream/qdsp5/Makefile b/drivers/staging/dream/qdsp5/Makefile
index 991d4a7e157..beedaaff5cc 100644
--- a/drivers/staging/dream/qdsp5/Makefile
+++ b/drivers/staging/dream/qdsp5/Makefile
@@ -1,3 +1,4 @@
+EXTRA_CFLAGS=-Idrivers/staging/dream/include
obj-y += adsp.o
ifeq ($(CONFIG_MSM_AMSS_VERSION_6350),y)
obj-y += adsp_info.o
diff --git a/drivers/staging/dream/qdsp5/audio_mp3.c b/drivers/staging/dream/qdsp5/audio_mp3.c
index b95574f699f..7ed6e261d6c 100644
--- a/drivers/staging/dream/qdsp5/audio_mp3.c
+++ b/drivers/staging/dream/qdsp5/audio_mp3.c
@@ -650,8 +650,7 @@ static long audio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
&audio->read_phys,
GFP_KERNEL);
if (!audio->read_data) {
- pr_err("audio_mp3: malloc pcm \
- buf failed\n");
+ pr_err("audio_mp3: malloc pcm buf failed\n");
rc = -1;
} else {
uint8_t index;
diff --git a/drivers/staging/dream/smd/Makefile b/drivers/staging/dream/smd/Makefile
index 892c7414bbe..1c87618366a 100644
--- a/drivers/staging/dream/smd/Makefile
+++ b/drivers/staging/dream/smd/Makefile
@@ -1,3 +1,4 @@
+EXTRA_CFLAGS=-Idrivers/staging/dream/include
obj-$(CONFIG_MSM_SMD) += smd.o smd_tty.o smd_qmi.o
obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter.o
obj-$(CONFIG_MSM_ONCRPCROUTER) += smd_rpcrouter_device.o
diff --git a/drivers/staging/dream/smd/smd_rpcrouter.c b/drivers/staging/dream/smd/smd_rpcrouter.c
index 5ac2cd4a597..69911a7bc87 100644
--- a/drivers/staging/dream/smd/smd_rpcrouter.c
+++ b/drivers/staging/dream/smd/smd_rpcrouter.c
@@ -38,8 +38,6 @@
#include <linux/platform_device.h>
#include <linux/uaccess.h>
-#include <asm/byteorder.h>
-
#include <mach/msm_smd.h>
#include "smd_rpcrouter.h"
diff --git a/drivers/staging/dt3155/Kconfig b/drivers/staging/dt3155/Kconfig
new file mode 100644
index 00000000000..4a3293c721b
--- /dev/null
+++ b/drivers/staging/dt3155/Kconfig
@@ -0,0 +1,4 @@
+config DT3155
+ tristate "DT3155 Digitizer support"
+ depends on PCI
+
diff --git a/drivers/staging/dt3155/Makefile b/drivers/staging/dt3155/Makefile
new file mode 100644
index 00000000000..136f21fdbbe
--- /dev/null
+++ b/drivers/staging/dt3155/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_DT3155) += dt3155.o
+dt3155-objs := \
+ dt3155_drv.o \
+ dt3155_isr.o \
+ dt3155_io.o \
+ allocator.o
diff --git a/drivers/staging/dt3155/TODO b/drivers/staging/dt3155/TODO
new file mode 100644
index 00000000000..3baa3b6294c
--- /dev/null
+++ b/drivers/staging/dt3155/TODO
@@ -0,0 +1,10 @@
+TODO:
+ - fix checkpatch.pl issues
+ - remove old kernel support, it is not needed
+ - convert to proper PCI device API
+ - fix sparse warnings
+ - audit for correct subsystem interaction
+ - review review review!
+
+Please send patches to Greg Kroah-Hartman <greg@kroah.com>
+and Scott Smedley <ss@aao.gov.au>
diff --git a/drivers/staging/dt3155/allocator.README b/drivers/staging/dt3155/allocator.README
new file mode 100644
index 00000000000..05700b6c926
--- /dev/null
+++ b/drivers/staging/dt3155/allocator.README
@@ -0,0 +1,98 @@
+
+The allocator shown here exploits high memory. This document explains
+how a user can deal with drivers uses this allocator and how a
+programmer can link in the module.
+
+The module is being used by my pxc and pxdrv device drivers (as well as
+other ones), available from ftp.systemy.it/pub/develop and
+ftp.linux.it/pub/People/Rubini
+
+ User's manual
+ =============
+
+
+One of the most compelling problems with any DMA-capable device is the
+allocation of a suitable memory buffer. The "allocator" module tries
+to deal with the problem in a clean way. The module is able to use
+high memory (above the one used in normal operation) for DMA
+allocation.
+
+To prevent the kernel for using high memory, so that it remains
+available for DMA, you should pass a command line argument to the
+kernel. Command line arguments can be passed to Lilo, to Loadlin or
+to whichever loader you are using (unless it's very poor in design).
+For Lilo, either use "append=" in /etc/lilo.conf or add commandline
+arguments to the interactive prompt. For example, I have a 32MB box
+and reserve two megs for DMA:
+
+In lilo.conf:
+ image = /zImage
+ label = linux
+ append = "mem=30M"
+
+Or, interactively:
+ LILO: linux mem=30M
+
+Once the kernel is booted with the right command-line argument, any
+driver linked with the allocator module will be able to get
+DMA-capable memory without much trouble (unless the various drivers
+need more memory than available).
+
+The module implements an alloc/free mechanism, so that it can serve
+multiple drivers at the same time. Note however that the allocator
+uses all of high memory and assumes to be the only piece of software
+using such memory.
+
+
+ Programmer's manual
+ ===================
+
+The allocator, as released, is designed to be linked to a device
+driver. In this case, the driver must call allocator_init() before
+using the allocator and must call allocator_cleanup() before
+unloading. This is usually done from within init_module() and
+cleanup_module(). If the allocator is linked to a driver, it won't be
+possible for several drivers to allocate high DMA memory, as explained
+above.
+
+It is possible, on the other hand, to compile the module as a standalone
+module, so that several modules can rely on the allocator for they DMA
+buffers. To compile the allocator as a standalone module, do the
+following in this directory (or provide a suitable Makefile, or edit
+the source code):
+
+ make allocator.o CC="gcc -Dallocator_init=init_module -Dallocator_cleanup=cleanup_module -include /usr/include/linux/module.h"
+
+The previous commandline tells to include <linux/module.h> in the
+first place, and to rename the init and cleanup function to the ones
+needed for module loading and unloading. Drivers using a standalone
+allocator won't need to call allocator_init() nor allocator_cleanup().
+
+The allocator exports the following functions (declared in allocator.h):
+
+ unsigned long allocator_allocate_dma (unsigned long kilobytes,
+ int priority);
+
+ This function returns a physical address, over high_memory,
+ which corresponds to an area of at least "kilobytes" kilobytes.
+ The area will be owned by the module calling the function.
+ The returned address can be passed to device boards, to instruct
+ their DMA controllers, via phys_to_bus(). The address can be used
+ by C code after vremap()/ioremap(). The "priority" argument should
+ be GFP_KERNEL or GFP_ATOMIC, according to the context of the
+ caller; it is used to call kmalloc(), as the allocator must keep
+ track of any region it gives away. In case of error the function
+ returns 0, and the caller is expected to issue a -ENOMEM error.
+
+
+ void allocator_free_dma (unsigned long address);
+
+ This function is the reverse of the previous one. If a driver
+ doesn't free the DMA memory it allocated, the allocator will
+ consider such memory as busy. Note, however, that
+ allocator_cleanup() calls kfree() on every region it reclaimed,
+ so that a driver with the allocator linked in can avoid calling
+ allocator_free_dma() at unload time.
+
+
+
diff --git a/drivers/staging/dt3155/allocator.c b/drivers/staging/dt3155/allocator.c
new file mode 100644
index 00000000000..c74234c6689
--- /dev/null
+++ b/drivers/staging/dt3155/allocator.c
@@ -0,0 +1,295 @@
+/*
+ * allocator.c -- allocate after high_memory, if available
+ *
+ * NOTE: this is different from my previous allocator, the one that
+ * assembles pages, which revealed itself both slow and unreliable.
+ *
+ * Copyright (C) 1998 rubini@linux.it (Alessandro Rubini)
+ *
+ * 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.
+ *
+
+-- Changes --
+
+ Date Programmer Description of changes made
+ -------------------------------------------------------------------
+ 02-Aug-2002 NJC allocator now steps in 1MB increments, rather
+ than doubling its size each time.
+ Also, allocator_init(u32 *) now returns
+ (in the first arg) the size of the free
+ space. This is no longer consistent with
+ using the allocator as a module, and some changes
+ may be necessary for that purpose. This was
+ designed to work with the DT3155 driver, in
+ stand alone mode only!!!
+ 26-Oct-2009 SS Port to 2.6.30 kernel.
+ */
+
+
+#ifndef __KERNEL__
+# define __KERNEL__
+#endif
+#ifndef MODULE
+# define MODULE
+#endif
+
+#include <linux/version.h>
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/mm.h> /* PAGE_ALIGN() */
+#include <linux/io.h>
+
+#include <asm/page.h>
+
+/*#define ALL_DEBUG*/
+#define ALL_MSG "allocator: "
+
+#undef PDEBUG /* undef it, just in case */
+#ifdef ALL_DEBUG
+# define __static
+# define DUMP_LIST() dump_list()
+# ifdef __KERNEL__
+ /* This one if debugging is on, and kernel space */
+# define PDEBUG(fmt, args...) printk(KERN_DEBUG ALL_MSG fmt, ## args)
+# else
+ /* This one for user space */
+# define PDEBUG(fmt, args...) fprintf(stderr, fmt, ## args)
+# endif
+#else
+# define PDEBUG(fmt, args...) /* not debugging: nothing */
+# define DUMP_LIST()
+# define __static static
+#endif
+
+#undef PDEBUGG
+#define PDEBUGG(fmt, args...)
+/*#define PDEBUGG(fmt, args...) printk( KERN_DEBUG ALL_MSG fmt, ## args)*/
+
+
+int allocator_himem = 1; /* 0 = probe, pos. = megs, neg. = disable */
+int allocator_step = 1; /* This is the step size in MB */
+int allocator_probe = 1; /* This is a flag -- 1=probe, 0=don't probe */
+
+static unsigned long allocator_buffer; /* physical address */
+static unsigned long allocator_buffer_size; /* kilobytes */
+
+/*
+ * The allocator keeps a list of DMA areas, so multiple devices
+ * can coexist. The list is kept sorted by address
+ */
+
+struct allocator_struct {
+ unsigned long address;
+ unsigned long size;
+ struct allocator_struct *next;
+};
+
+struct allocator_struct *allocator_list;
+
+
+#ifdef ALL_DEBUG
+static int dump_list(void)
+{
+ struct allocator_struct *ptr;
+
+ PDEBUG("Current list:\n");
+ for (ptr = allocator_list; ptr; ptr = ptr->next)
+ PDEBUG("0x%08lx (size %likB)\n", ptr->address, ptr->size>>10);
+ return 0;
+}
+#endif
+
+/* ========================================================================
+ * This function is the actual allocator.
+ *
+ * If space is available in high memory (as detected at load time), that
+ * one is returned. The return value is a physical address (i.e., it can
+ * be used straight ahead for DMA, but needs remapping for program use).
+ */
+
+unsigned long allocator_allocate_dma(unsigned long kilobytes, int prio)
+{
+ struct allocator_struct *ptr = allocator_list, *newptr;
+ unsigned long bytes = kilobytes << 10;
+
+ /* check if high memory is available */
+ if (!allocator_buffer)
+ return 0;
+
+ /* Round it to a multiple of the pagesize */
+ bytes = PAGE_ALIGN(bytes);
+ PDEBUG("request for %li bytes\n", bytes);
+
+ while (ptr && ptr->next) {
+ if (ptr->next->address - (ptr->address + ptr->size) >= bytes)
+ break; /* enough space */
+ ptr = ptr->next;
+ }
+ if (!ptr->next) {
+ DUMP_LIST();
+ PDEBUG("alloc failed\n");
+ return 0; /* end of list */
+ }
+ newptr = kmalloc(sizeof(struct allocator_struct), prio);
+ if (!newptr)
+ return 0;
+
+ /* ok, now stick it after ptr */
+ newptr->address = ptr->address + ptr->size;
+ newptr->size = bytes;
+ newptr->next = ptr->next;
+ ptr->next = newptr;
+
+ DUMP_LIST();
+ PDEBUG("returning 0x%08lx\n", newptr->address);
+ return newptr->address;
+}
+
+int allocator_free_dma(unsigned long address)
+{
+ struct allocator_struct *ptr = allocator_list, *prev;
+
+ while (ptr && ptr->next) {
+ if (ptr->next->address == address)
+ break;
+ ptr = ptr->next;
+ }
+ /* the one being freed is ptr->next */
+ prev = ptr; ptr = ptr->next;
+
+ if (!ptr) {
+ printk(KERN_ERR ALL_MSG
+ "free_dma(0x%08lx) but add. not allocated\n",
+ ptr->address);
+ return -EINVAL;
+ }
+ PDEBUGG("freeing: %08lx (%li) next %08lx\n", ptr->address, ptr->size,
+ ptr->next->address);
+ prev->next = ptr->next;
+ kfree(ptr);
+
+ /* dump_list(); */
+ return 0;
+}
+
+/* ========================================================================
+ * Init and cleanup
+ *
+ * On cleanup everything is released. If the list is not empty, that a
+ * problem of our clients
+ */
+int allocator_init(u32 *allocator_max)
+{
+ /* check how much free memory is there */
+ void *remapped;
+ unsigned long max;
+ unsigned long trial_size = allocator_himem<<20;
+ unsigned long last_trial = 0;
+ unsigned long step = allocator_step<<20;
+ unsigned long i = 0;
+ struct allocator_struct *head, *tail;
+ char test_string[] = "0123456789abcde"; /* 16 bytes */
+
+ PDEBUGG("himem = %i\n", allocator_himem);
+ if (allocator_himem < 0) /* don't even try */
+ return -EINVAL;
+
+ if (!trial_size)
+ trial_size = 1<<20; /* not specified: try one meg */
+
+ while (1) {
+ remapped = ioremap(__pa(high_memory), trial_size);
+ if (!remapped) {
+ PDEBUGG("%li megs failed!\n", trial_size>>20);
+ break;
+ }
+ PDEBUGG("Trying %li megs (at %p, %p)\n", trial_size>>20,
+ (void *)__pa(high_memory), remapped);
+ for (i = last_trial; i < trial_size; i += 16) {
+ strcpy((char *)(remapped)+i, test_string);
+ if (strcmp((char *)(remapped)+i, test_string))
+ break;
+ }
+ iounmap((void *)remapped);
+ schedule();
+ last_trial = trial_size;
+ if (i == trial_size)
+ trial_size += step; /* increment, if all went well */
+ else {
+ PDEBUGG("%li megs copy test failed!\n", trial_size>>20);
+ break;
+ }
+ if (!allocator_probe)
+ break;
+ }
+ PDEBUG("%li megs (%li k, %li b)\n", i>>20, i>>10, i);
+ allocator_buffer_size = i>>10; /* kilobytes */
+ allocator_buffer = __pa(high_memory);
+ if (!allocator_buffer_size) {
+ printk(KERN_WARNING ALL_MSG "no free high memory to use\n");
+ return -ENOMEM;
+ }
+
+ /*
+ * to simplify things, always have two cells in the list:
+ * the first and the last. This avoids some conditionals and
+ * extra code when allocating and deallocating: we only play
+ * in the middle of the list
+ */
+ head = kmalloc(sizeof(struct allocator_struct), GFP_KERNEL);
+ if (!head)
+ return -ENOMEM;
+ tail = kmalloc(sizeof(struct allocator_struct), GFP_KERNEL);
+ if (!tail) {
+ kfree(head);
+ return -ENOMEM;
+ }
+
+ max = allocator_buffer_size<<10;
+
+ head->size = tail->size = 0;
+ head->address = allocator_buffer;
+ tail->address = allocator_buffer + max;
+ head->next = tail;
+ tail->next = NULL;
+ allocator_list = head;
+
+ /* Back to the user code, in KB */
+ *allocator_max = allocator_buffer_size;
+
+ return 0; /* ok, ready */
+}
+
+void allocator_cleanup(void)
+{
+ struct allocator_struct *ptr, *next;
+
+ for (ptr = allocator_list; ptr; ptr = next) {
+ next = ptr->next;
+ PDEBUG("freeing list: 0x%08lx\n", ptr->address);
+ kfree(ptr);
+ }
+
+ allocator_buffer = 0;
+ allocator_buffer_size = 0;
+ allocator_list = NULL;
+}
+
+
diff --git a/drivers/staging/dt3155/allocator.h b/drivers/staging/dt3155/allocator.h
new file mode 100644
index 00000000000..bdf3268ca52
--- /dev/null
+++ b/drivers/staging/dt3155/allocator.h
@@ -0,0 +1,28 @@
+/*
+ * allocator.h -- prototypes for allocating high memory
+ *
+ * NOTE: this is different from my previous allocator, the one that
+ * assembles pages, which revealed itself both slow and unreliable.
+ *
+ * Copyright (C) 1998 rubini@linux.it (Alessandro Rubini)
+ *
+ * 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.
+ *
+ */
+
+void allocator_free_dma(unsigned long address);
+unsigned long allocator_allocate_dma(unsigned long kilobytes, int priority);
+int allocator_init(u32 *);
+void allocator_cleanup(void);
diff --git a/drivers/staging/dt3155/dt3155.h b/drivers/staging/dt3155/dt3155.h
new file mode 100644
index 00000000000..1bf786364ee
--- /dev/null
+++ b/drivers/staging/dt3155/dt3155.h
@@ -0,0 +1,171 @@
+/*
+
+Copyright 1996,2002,2005 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
+ Jason Lapenta, Scott Smedley
+
+This file is part of the DT3155 Device Driver.
+
+The DT3155 Device 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.
+
+The DT3155 Device 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 the DT3155 Device Driver; if not, write to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+MA 02111-1307 USA
+
+-- Changes --
+
+ Date Programmer Description of changes made
+ -------------------------------------------------------------------
+ 03-Jul-2000 JML n/a
+ 10-Oct-2001 SS port to 2.4 kernel.
+ 24-Jul-2002 SS remove unused code & added GPL licence.
+ 05-Aug-2005 SS port to 2.6 kernel; make CCIR mode default.
+
+*/
+
+#ifndef _DT3155_INC
+#define _DT3155_INC
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/time.h> /* struct timeval */
+#else
+#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
+
+#define TRUE 1
+#define FALSE 0
+
+/* Uncomment this for 50Hz CCIR */
+#define CCIR 1
+
+/* Can be 1 or 2 */
+#define MAXBOARDS 1
+
+#define BOARD_MAX_BUFFS 3
+#define MAXBUFFERS (BOARD_MAX_BUFFS*MAXBOARDS)
+
+#define PCI_PAGE_SIZE (1 << 12)
+
+#ifdef CCIR
+#define DT3155_MAX_ROWS 576
+#define DT3155_MAX_COLS 768
+#define FORMAT50HZ TRUE
+#else
+#define DT3155_MAX_ROWS 480
+#define DT3155_MAX_COLS 640
+#define FORMAT50HZ FALSE
+#endif
+
+/* Configuration structure */
+struct dt3155_config_s {
+ u32 acq_mode;
+ u32 cols, rows;
+ u32 continuous;
+};
+
+
+/* hold data for each frame */
+typedef struct {
+ u32 addr; /* address of the buffer with the frame */
+ u32 tag; /* unique number for the frame */
+ struct timeval time; /* time that capture took place */
+} frame_info_t;
+
+/*
+ * Structure for interrupt and buffer handling.
+ * This is the setup for 1 card
+ */
+struct dt3155_fbuffer_s {
+ int nbuffers;
+
+ frame_info_t frame_info[BOARD_MAX_BUFFS];
+
+ int empty_buffers[BOARD_MAX_BUFFS]; /* indexes empty frames */
+ int empty_len; /* Number of empty buffers */
+ /* Zero means empty */
+
+ int active_buf; /* Where data is currently dma'ing */
+ int locked_buf; /* Buffers used by user */
+
+ int ready_que[BOARD_MAX_BUFFS];
+ u32 ready_head; /* The most recent buffer located here */
+ u32 ready_len; /* The number of ready buffers */
+
+ int even_happened;
+ int even_stopped;
+
+ int stop_acquire; /* Flag to stop interrupts */
+ u32 frame_count; /* Counter for frames acquired by this card */
+};
+
+
+
+#define DT3155_MODE_FRAME 1
+#define DT3155_MODE_FIELD 2
+
+#define DT3155_SNAP 1
+#define DT3155_ACQ 2
+
+/* There is one status structure for each card. */
+typedef struct dt3155_status_s {
+ int fixed_mode; /* if 1, we are in fixed frame mode */
+ u32 reg_addr; /* Register address for a single card */
+ u32 mem_addr; /* Buffer start addr for this card */
+ u32 mem_size; /* This is the amount of mem available */
+ u32 irq; /* this card's irq */
+ struct dt3155_config_s config; /* configuration struct */
+ struct dt3155_fbuffer_s fbuffer; /* frame buffer state struct */
+ u32 state; /* this card's state */
+ u32 device_installed; /* Flag if installed. 1=installed */
+} dt3155_status_t;
+
+/* Reference to global status structure */
+extern struct dt3155_status_s dt3155_status[MAXBOARDS];
+
+#define DT3155_STATE_IDLE 0x00
+#define DT3155_STATE_FRAME 0x01
+#define DT3155_STATE_FLD 0x02
+#define DT3155_STATE_STOP 0x100
+#define DT3155_STATE_ERROR 0x200
+#define DT3155_STATE_MODE 0x0ff
+
+#define DT3155_IOC_MAGIC '!'
+
+#define DT3155_SET_CONFIG _IOW(DT3155_IOC_MAGIC, 1, struct dt3155_config_s)
+#define DT3155_GET_CONFIG _IOR(DT3155_IOC_MAGIC, 2, struct dt3155_status_s)
+#define DT3155_STOP _IO(DT3155_IOC_MAGIC, 3)
+#define DT3155_START _IO(DT3155_IOC_MAGIC, 4)
+#define DT3155_FLUSH _IO(DT3155_IOC_MAGIC, 5)
+#define DT3155_IOC_MAXNR 5
+
+/* Error codes */
+
+#define DT_ERR_NO_BUFFERS 0x10000 /* not used but it might be one day */
+#define DT_ERR_CORRUPT 0x20000
+#define DT_ERR_OVERRUN 0x30000
+#define DT_ERR_I2C_TIMEOUT 0x40000
+#define DT_ERR_MASK 0xff0000/* not used but it might be one day */
+
+/* User code will probably want to declare one of these for each card */
+typedef struct dt3155_read_s {
+ u32 offset;
+ u32 frame_seq;
+ u32 state;
+
+ frame_info_t frame_info;
+} dt3155_read_t;
+
+#endif /* _DT3155_inc */
diff --git a/drivers/staging/dt3155/dt3155.sysvinit b/drivers/staging/dt3155/dt3155.sysvinit
new file mode 100644
index 00000000000..92ec0939cb7
--- /dev/null
+++ b/drivers/staging/dt3155/dt3155.sysvinit
@@ -0,0 +1,60 @@
+#! /bin/sh
+#
+# Module load/unload script for use with SysV-style /etc/init.d/ systems.
+# On a Debian system, copy this to /etc/init.d/dt3155 and then run
+# /usr/sbin/update-rc.d dt3155 defaults 55
+# to create the appropriate /etc/rc?.d/[SK]55dt3155 start/stop links.
+# (The "55" is arbitrary but is what I use to load this rather late.)
+#
+# Andy Dougherty Feb 22 2000 doughera@lafayette.edu
+# Dept. of Physics
+# Lafayette College, Easton PA 18042
+#
+
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+
+# Edit to point to your local copy.
+FILE=/usr/local/lib/modules/dt3155/dt3155.o
+NAME="dt3155"
+DESC="dt3155 Frame Grabber module"
+DEV="dt3155"
+
+if test ! -f $FILE; then
+ echo "Unable to locate $FILE"
+ exit 0
+fi
+
+set -e
+
+case "$1" in
+ start)
+ echo -n "Loading $DESC "
+ if /sbin/insmod -v -f $FILE; then
+ major=`grep $DEV /proc/devices | awk "{print \\$1}"`
+ rm -f /dev/dt3155?
+ mknod /dev/dt3155a c $major 0
+ mknod /dev/dt3155b c $major 1
+ chmod go+rw /dev/dt3155?
+ echo
+ else
+ echo "$FILE not loaded."
+ fi
+ ;;
+ stop)
+ echo -n "Unloading $DESC: "
+ if /sbin/rmmod $NAME ; then
+ echo
+ else
+ echo "$DEV not removed"
+ exit 0
+ fi
+ rm -f /dev/dt3155?
+ ;;
+ *)
+ echo "Usage: /etc/init.d/$NAME {start|stop}"
+ exit 1
+ ;;
+esac
+
+exit 0
+
diff --git a/drivers/staging/dt3155/dt3155_drv.c b/drivers/staging/dt3155/dt3155_drv.c
new file mode 100644
index 00000000000..a67c622869d
--- /dev/null
+++ b/drivers/staging/dt3155/dt3155_drv.c
@@ -0,0 +1,1095 @@
+/*
+
+Copyright 1996,2002,2005 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
+ Jason Lapenta, Scott Smedley, Greg Sharp
+
+This file is part of the DT3155 Device Driver.
+
+The DT3155 Device 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.
+
+The DT3155 Device 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 the DT3155 Device Driver; if not, write to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+MA 02111-1307 USA
+
+-- Changes --
+
+ Date Programmer Description of changes made
+ -------------------------------------------------------------------
+ 03-Jul-2000 JML n/a
+ 10-Oct-2001 SS port to 2.4 kernel
+ 02-Apr-2002 SS Mods to use allocator as a standalone module;
+ Merged John Roll's changes (john@cfa.harvard.edu)
+ to make work with multiple boards.
+ 02-Jul-2002 SS Merged James Rose's chages (rosejr@purdue.edu) to:
+ * fix successive interrupt-driven captures
+ * add select/poll support.
+ 10-Jul-2002 GCS Add error check when ndevices > MAXBOARDS.
+ 02-Aug-2002 GCS Fix field mode so that odd (lower) field is stored
+ in lower half of buffer.
+ 05-Aug-2005 SS port to 2.6 kernel.
+ 26-Oct-2009 SS port to 2.6.30 kernel.
+
+-- Notes --
+
+** appended "mem=124" in lilo.conf to allow for 4megs free on my 128meg system.
+ * using allocator.c and allocator.h from o'reilly book (alessandro rubini)
+ ftp://ftp.systemy.it/pub/develop (see README.allocator)
+
+ + might want to get rid of MAXboards for allocating initial buffer.
+ confusing and not necessary
+
+ + in cleanup_module the MOD_IN_USE looks like it is check after it should
+
+ * GFP_DMA should not be set with a PCI system (pg 291)
+
+ - NJC why are only two buffers allowed? (see isr, approx line 358)
+
+*/
+
+extern void printques(int);
+
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/interrupt.h>
+
+
+MODULE_LICENSE("GPL");
+
+#endif
+
+#ifndef CONFIG_PCI
+#error "DT3155 : Kernel PCI support not enabled (DT3155 drive requires PCI)"
+#endif
+
+#include <linux/pci.h>
+#include <linux/types.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include "dt3155.h"
+#include "dt3155_drv.h"
+#include "dt3155_isr.h"
+#include "dt3155_io.h"
+#include "allocator.h"
+
+/* Error variable. Zero means no error. */
+int dt3155_errno = 0;
+
+#ifndef PCI_DEVICE_ID_INTEL_7116
+#define PCI_DEVICE_ID_INTEL_7116 0x1223
+#endif
+
+#define DT3155_VENDORID PCI_VENDOR_ID_INTEL
+#define DT3155_DEVICEID PCI_DEVICE_ID_INTEL_7116
+#define MAXPCI 16
+
+#ifdef DT_DEBUG
+#define DT_3155_DEBUG_MSG(x,y) printk(x,y)
+#else
+#define DT_3155_DEBUG_MSG(x,y)
+#endif
+
+/* wait queue for interrupts */
+wait_queue_head_t dt3155_read_wait_queue[ MAXBOARDS ];
+
+#define DT_3155_SUCCESS 0
+#define DT_3155_FAILURE -EIO
+
+/* set to dynamicaly allocate, but it is tunable: */
+/* insmod DT_3155 dt3155 dt3155_major=XX */
+int dt3155_major = 0;
+
+/* The minor numbers are 0 and 1 ... they are not tunable.
+ * They are used as the indices for the structure vectors,
+ * and register address vectors
+ */
+
+/* Global structures and variables */
+
+/* Status of each device */
+struct dt3155_status_s dt3155_status[ MAXBOARDS ];
+
+/* kernel logical address of the board */
+u8 *dt3155_lbase[ MAXBOARDS ] = { NULL
+#if MAXBOARDS == 2
+ , NULL
+#endif
+};
+/* DT3155 registers */
+u8 *dt3155_bbase = NULL; /* kernel logical address of the *
+ * buffer region */
+u32 dt3155_dev_open[ MAXBOARDS ] = {0
+#if MAXBOARDS == 2
+ , 0
+#endif
+};
+
+u32 ndevices = 0;
+u32 unique_tag = 0;;
+
+
+/*
+ * Stops interrupt generation right away and resets the status
+ * to idle. I don't know why this works and the other way doesn't.
+ * (James Rose)
+ */
+static void quick_stop (int minor)
+{
+ // TODO: scott was here
+#if 1
+ ReadMReg((dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg);
+ /* disable interrupts */
+ int_csr_r.fld.FLD_END_EVE_EN = 0;
+ int_csr_r.fld.FLD_END_ODD_EN = 0;
+ WriteMReg((dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg );
+
+ dt3155_status[ minor ].state &= ~(DT3155_STATE_STOP|0xff);
+ /* mark the system stopped: */
+ dt3155_status[ minor ].state |= DT3155_STATE_IDLE;
+ dt3155_fbuffer[ minor ]->stop_acquire = 0;
+ dt3155_fbuffer[ minor ]->even_stopped = 0;
+#else
+ dt3155_status[minor].state |= DT3155_STATE_STOP;
+ dt3155_status[minor].fbuffer.stop_acquire = 1;
+#endif
+
+}
+
+
+/*****************************************************
+ * dt3155_isr() Interrupt service routien
+ *
+ * - looks like this isr supports IRQ sharing (or could) JML
+ * - Assumes irq's are disabled, via SA_INTERRUPT flag
+ * being set in request_irq() call from init_module()
+ *****************************************************/
+static inline void dt3155_isr( int irq, void *dev_id, struct pt_regs *regs )
+{
+ int minor = -1;
+ int index;
+ unsigned long flags;
+ u32 buffer_addr;
+
+ /* find out who issued the interrupt */
+ for ( index = 0; index < ndevices; index++ ) {
+ if( dev_id == (void*) &dt3155_status[ index ])
+ {
+ minor = index;
+ break;
+ }
+ }
+
+ /* hopefully we should not get here */
+ if ( minor < 0 || minor >= MAXBOARDS ) {
+ printk(KERN_ERR "dt3155_isr called with invalid dev_id\n");
+ return;
+ }
+
+ /* Check for corruption and set a flag if so */
+ ReadMReg( (dt3155_lbase[ minor ] + CSR1), csr1_r.reg );
+
+ if ( (csr1_r.fld.FLD_CRPT_EVE) || (csr1_r.fld.FLD_CRPT_ODD) )
+ {
+ /* TODO: this should probably stop acquisition */
+ /* and set some flags so that dt3155_read */
+ /* returns an error next time it is called */
+ dt3155_errno = DT_ERR_CORRUPT;
+ printk("dt3155: corrupt field\n");
+ return;
+ }
+
+ ReadMReg((dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg);
+
+ /* Handle the even field ... */
+ if (int_csr_r.fld.FLD_END_EVE)
+ {
+ if ( (dt3155_status[ minor ].state & DT3155_STATE_MODE) ==
+ DT3155_STATE_FLD )
+ {
+ dt3155_fbuffer[ minor ]->frame_count++;
+ }
+
+ ReadI2C(dt3155_lbase[ minor ], EVEN_CSR, &i2c_even_csr.reg);
+
+ /* Clear the interrupt? */
+ int_csr_r.fld.FLD_END_EVE = 1;
+
+ /* disable the interrupt if last field */
+ if (dt3155_fbuffer[ minor ]->stop_acquire)
+ {
+ printk("dt3155: even stopped.\n");
+ dt3155_fbuffer[ minor ]->even_stopped = 1;
+ if (i2c_even_csr.fld.SNGL_EVE)
+ {
+ int_csr_r.fld.FLD_END_EVE_EN = 0;
+ }
+ else
+ {
+ i2c_even_csr.fld.SNGL_EVE = 1;
+ }
+ }
+
+ WriteMReg( (dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg );
+
+ /* Set up next DMA if we are doing FIELDS */
+ if ( (dt3155_status[ minor ].state & DT3155_STATE_MODE ) ==
+ DT3155_STATE_FLD)
+ {
+ /* GCS (Aug 2, 2002) -- In field mode, dma the odd field
+ into the lower half of the buffer */
+ const u32 stride = dt3155_status[ minor ].config.cols;
+ buffer_addr = dt3155_fbuffer[ minor ]->
+ frame_info[ dt3155_fbuffer[ minor ]->active_buf ].addr
+ + (DT3155_MAX_ROWS / 2) * stride;
+ local_save_flags(flags);
+ local_irq_disable();
+ wake_up_interruptible( &dt3155_read_wait_queue[ minor ] );
+
+ /* Set up the DMA address for the next field */
+ local_irq_restore(flags);
+ WriteMReg((dt3155_lbase[ minor ] + ODD_DMA_START), buffer_addr);
+ }
+
+ /* Check for errors. */
+ i2c_even_csr.fld.DONE_EVE = 1;
+ if ( i2c_even_csr.fld.ERROR_EVE )
+ dt3155_errno = DT_ERR_OVERRUN;
+
+ WriteI2C( dt3155_lbase[ minor ], EVEN_CSR, i2c_even_csr.reg );
+
+ /* Note that we actually saw an even field meaning */
+ /* that subsequent odd field complete the frame */
+ dt3155_fbuffer[ minor ]->even_happened = 1;
+
+ /* recording the time that the even field finished, this should be */
+ /* about time in the middle of the frame */
+ do_gettimeofday( &(dt3155_fbuffer[ minor ]->
+ frame_info[ dt3155_fbuffer[ minor ]->
+ active_buf ].time) );
+ return;
+ }
+
+ /* ... now handle the odd field */
+ if ( int_csr_r.fld.FLD_END_ODD )
+ {
+ ReadI2C( dt3155_lbase[ minor ], ODD_CSR, &i2c_odd_csr.reg );
+
+ /* Clear the interrupt? */
+ int_csr_r.fld.FLD_END_ODD = 1;
+
+ if (dt3155_fbuffer[ minor ]->even_happened ||
+ (dt3155_status[ minor ].state & DT3155_STATE_MODE) ==
+ DT3155_STATE_FLD)
+ {
+ dt3155_fbuffer[ minor ]->frame_count++;
+ }
+
+ if ( dt3155_fbuffer[ minor ]->stop_acquire &&
+ dt3155_fbuffer[ minor ]->even_stopped )
+ {
+ printk(KERN_DEBUG "dt3155: stopping odd..\n");
+ if ( i2c_odd_csr.fld.SNGL_ODD )
+ {
+ /* disable interrupts */
+ int_csr_r.fld.FLD_END_ODD_EN = 0;
+ dt3155_status[ minor ].state &= ~(DT3155_STATE_STOP|0xff);
+
+ /* mark the system stopped: */
+ dt3155_status[ minor ].state |= DT3155_STATE_IDLE;
+ dt3155_fbuffer[ minor ]->stop_acquire = 0;
+ dt3155_fbuffer[ minor ]->even_stopped = 0;
+
+ printk(KERN_DEBUG "dt3155: state is now %x\n",
+ dt3155_status[minor].state);
+ }
+ else
+ {
+ i2c_odd_csr.fld.SNGL_ODD = 1;
+ }
+ }
+
+ WriteMReg( (dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg );
+
+ /* if the odd field has been acquired, then */
+ /* change the next dma location for both fields */
+ /* and wake up the process if sleeping */
+ if ( dt3155_fbuffer[ minor ]->even_happened ||
+ (dt3155_status[ minor ].state & DT3155_STATE_MODE) ==
+ DT3155_STATE_FLD )
+ {
+
+ local_save_flags(flags);
+ local_irq_disable();
+
+#ifdef DEBUG_QUES_B
+ printques( minor );
+#endif
+ if ( dt3155_fbuffer[ minor ]->nbuffers > 2 )
+ {
+ if ( !are_empty_buffers( minor ) )
+ {
+ /* The number of active + locked buffers is
+ * at most 2, and since there are none empty, there
+ * must be at least nbuffers-2 ready buffers.
+ * This is where we 'drop frames', oldest first. */
+ push_empty( pop_ready( minor ), minor );
+ }
+
+ /* The ready_que can't be full, since we know
+ * there is one active buffer right now, so it's safe
+ * to push the active buf on the ready_que. */
+ push_ready( minor, dt3155_fbuffer[ minor ]->active_buf );
+ /* There's at least 1 empty -- make it active */
+ dt3155_fbuffer[ minor ]->active_buf = pop_empty( minor );
+ dt3155_fbuffer[ minor ]->
+ frame_info[ dt3155_fbuffer[ minor ]->
+ active_buf ].tag = ++unique_tag;
+ }
+ else /* nbuffers == 2, special case */
+ { /* There is 1 active buffer.
+ * If there is a locked buffer, keep the active buffer
+ * the same -- that means we drop a frame.
+ */
+ if ( dt3155_fbuffer[ minor ]->locked_buf < 0 )
+ {
+ push_ready( minor,
+ dt3155_fbuffer[ minor ]->active_buf );
+ if (are_empty_buffers( minor ) )
+ {
+ dt3155_fbuffer[ minor ]->active_buf =
+ pop_empty( minor );
+ }
+ else
+ { /* no empty or locked buffers, so use a readybuf */
+ dt3155_fbuffer[ minor ]->active_buf =
+ pop_ready( minor );
+ }
+ }
+ }
+
+#ifdef DEBUG_QUES_B
+ printques( minor );
+#endif
+
+ dt3155_fbuffer[ minor ]->even_happened = 0;
+
+ wake_up_interruptible( &dt3155_read_wait_queue[ minor ] );
+
+ local_irq_restore(flags);
+ }
+
+
+ /* Set up the DMA address for the next frame/field */
+ buffer_addr = dt3155_fbuffer[ minor ]->
+ frame_info[ dt3155_fbuffer[ minor ]->active_buf ].addr;
+ if ( (dt3155_status[ minor ].state & DT3155_STATE_MODE) ==
+ DT3155_STATE_FLD )
+ {
+ WriteMReg((dt3155_lbase[ minor ] + EVEN_DMA_START), buffer_addr);
+ }
+ else
+ {
+ WriteMReg((dt3155_lbase[ minor ] + EVEN_DMA_START), buffer_addr);
+
+ WriteMReg((dt3155_lbase[ minor ] + ODD_DMA_START), buffer_addr
+ + dt3155_status[ minor ].config.cols);
+ }
+
+ /* Do error checking */
+ i2c_odd_csr.fld.DONE_ODD = 1;
+ if ( i2c_odd_csr.fld.ERROR_ODD )
+ dt3155_errno = DT_ERR_OVERRUN;
+
+ WriteI2C(dt3155_lbase[ minor ], ODD_CSR, i2c_odd_csr.reg );
+
+ return;
+ }
+ /* If we get here, the Odd Field wasn't it either... */
+ printk( "neither even nor odd. shared perhaps?\n");
+}
+
+/*****************************************************
+ * init_isr(int minor)
+ * turns on interupt generation for the card
+ * designated by "minor".
+ * It is called *only* from inside ioctl().
+ *****************************************************/
+static void dt3155_init_isr(int minor)
+{
+ const u32 stride = dt3155_status[ minor ].config.cols;
+
+ switch (dt3155_status[ minor ].state & DT3155_STATE_MODE)
+ {
+ case DT3155_STATE_FLD:
+ {
+ even_dma_start_r = dt3155_status[ minor ].
+ fbuffer.frame_info[ dt3155_status[ minor ].fbuffer.active_buf ].addr;
+ even_dma_stride_r = 0;
+ odd_dma_stride_r = 0;
+
+ WriteMReg((dt3155_lbase[ minor ] + EVEN_DMA_START),
+ even_dma_start_r);
+ WriteMReg((dt3155_lbase[ minor ] + EVEN_DMA_STRIDE),
+ even_dma_stride_r);
+ WriteMReg((dt3155_lbase[ minor ] + ODD_DMA_STRIDE),
+ odd_dma_stride_r);
+ break;
+ }
+
+ case DT3155_STATE_FRAME:
+ default:
+ {
+ even_dma_start_r = dt3155_status[ minor ].
+ fbuffer.frame_info[ dt3155_status[ minor ].fbuffer.active_buf ].addr;
+ odd_dma_start_r = even_dma_start_r + stride;
+ even_dma_stride_r = stride;
+ odd_dma_stride_r = stride;
+
+ WriteMReg((dt3155_lbase[ minor ] + EVEN_DMA_START),
+ even_dma_start_r);
+ WriteMReg((dt3155_lbase[ minor ] + ODD_DMA_START),
+ odd_dma_start_r);
+ WriteMReg((dt3155_lbase[ minor ] + EVEN_DMA_STRIDE),
+ even_dma_stride_r);
+ WriteMReg((dt3155_lbase[ minor ] + ODD_DMA_STRIDE),
+ odd_dma_stride_r);
+ break;
+ }
+ }
+
+ /* 50/60 Hz should be set before this point but let's make sure it is */
+ /* right anyway */
+
+ ReadI2C(dt3155_lbase[ minor ], CONFIG, &i2c_csr2.reg);
+ i2c_csr2.fld.HZ50 = FORMAT50HZ;
+ WriteI2C(dt3155_lbase[ minor ], CONFIG, i2c_config.reg);
+
+ /* enable busmaster chip, clear flags */
+
+ /*
+ * TODO:
+ * shouldn't we be concered with continuous values of
+ * DT3155_SNAP & DT3155_ACQ here? (SS)
+ */
+
+ csr1_r.reg = 0;
+ csr1_r.fld.CAP_CONT_EVE = 1; /* use continuous capture bits to */
+ csr1_r.fld.CAP_CONT_ODD = 1; /* enable */
+ csr1_r.fld.FLD_DN_EVE = 1; /* writing a 1 clears flags */
+ csr1_r.fld.FLD_DN_ODD = 1;
+ csr1_r.fld.SRST = 1; /* reset - must be 1 */
+ csr1_r.fld.FIFO_EN = 1; /* fifo control - must be 1 */
+ csr1_r.fld.FLD_CRPT_EVE = 1; /* writing a 1 clears flags */
+ csr1_r.fld.FLD_CRPT_ODD = 1;
+
+ WriteMReg((dt3155_lbase[ minor ] + CSR1),csr1_r.reg);
+
+ /* Enable interrupts at the end of each field */
+
+ int_csr_r.reg = 0;
+ int_csr_r.fld.FLD_END_EVE_EN = 1;
+ int_csr_r.fld.FLD_END_ODD_EN = 1;
+ int_csr_r.fld.FLD_START_EN = 0;
+
+ WriteMReg((dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg);
+
+ /* start internal BUSY bits */
+
+ ReadI2C(dt3155_lbase[ minor ], CSR2, &i2c_csr2.reg);
+ i2c_csr2.fld.BUSY_ODD = 1;
+ i2c_csr2.fld.BUSY_EVE = 1;
+ WriteI2C(dt3155_lbase[ minor ], CSR2, i2c_csr2.reg);
+
+ /* Now its up to the interrupt routine!! */
+
+ return;
+}
+
+
+/*****************************************************
+ * ioctl()
+ *
+ *****************************************************/
+static int dt3155_ioctl(struct inode *inode,
+ struct file *file,
+ unsigned int cmd,
+ unsigned long arg)
+{
+ int minor = MINOR(inode->i_rdev); /* What device are we ioctl()'ing? */
+
+ if ( minor >= MAXBOARDS || minor < 0 )
+ return -ENODEV;
+
+ /* make sure it is valid command */
+ if (_IOC_NR(cmd) > DT3155_IOC_MAXNR)
+ {
+ printk("DT3155: invalid IOCTL(0x%x)\n",cmd);
+ printk("DT3155: Valid commands (0x%x), (0x%x), (0x%x), (0x%x), (0x%x)\n",
+ (unsigned int)DT3155_GET_CONFIG,
+ (unsigned int)DT3155_SET_CONFIG,
+ (unsigned int)DT3155_START,
+ (unsigned int)DT3155_STOP,
+ (unsigned int)DT3155_FLUSH);
+ return -EINVAL;
+ }
+
+ switch (cmd)
+ {
+ case DT3155_SET_CONFIG:
+ {
+ if (dt3155_status[minor].state != DT3155_STATE_IDLE)
+ return -EBUSY;
+
+ {
+ struct dt3155_config_s tmp;
+ if (copy_from_user((void *)&tmp, (void *) arg, sizeof(tmp)))
+ return -EFAULT;
+ /* check for valid settings */
+ if (tmp.rows > DT3155_MAX_ROWS ||
+ tmp.cols > DT3155_MAX_COLS ||
+ (tmp.acq_mode != DT3155_MODE_FRAME &&
+ tmp.acq_mode != DT3155_MODE_FIELD) ||
+ (tmp.continuous != DT3155_SNAP &&
+ tmp.continuous != DT3155_ACQ))
+ {
+ return -EINVAL;
+ }
+ dt3155_status[minor].config = tmp;
+ }
+ return 0;
+ }
+ case DT3155_GET_CONFIG:
+ {
+ if (copy_to_user((void *) arg, (void *) &dt3155_status[minor],
+ sizeof(dt3155_status_t) ))
+ return -EFAULT;
+ return 0;
+ }
+ case DT3155_FLUSH: /* Flushes the buffers -- ensures fresh data */
+ {
+ if (dt3155_status[minor].state != DT3155_STATE_IDLE)
+ return -EBUSY;
+ return dt3155_flush(minor);
+ }
+ case DT3155_STOP:
+ {
+ if (dt3155_status[minor].state & DT3155_STATE_STOP ||
+ dt3155_status[minor].fbuffer.stop_acquire)
+ return -EBUSY;
+
+ if (dt3155_status[minor].state == DT3155_STATE_IDLE)
+ return 0;
+
+ quick_stop(minor);
+ if (copy_to_user((void *) arg, (void *) &dt3155_status[minor],
+ sizeof(dt3155_status_t)))
+ return -EFAULT;
+ return 0;
+ }
+ case DT3155_START:
+ {
+ if (dt3155_status[minor].state != DT3155_STATE_IDLE)
+ return -EBUSY;
+
+ dt3155_status[minor].fbuffer.stop_acquire = 0;
+ dt3155_status[minor].fbuffer.frame_count = 0;
+
+ /* Set the MODE in the status -- we default to FRAME */
+ if (dt3155_status[minor].config.acq_mode == DT3155_MODE_FIELD)
+ {
+ dt3155_status[minor].state = DT3155_STATE_FLD;
+ }
+ else
+ {
+ dt3155_status[minor].state = DT3155_STATE_FRAME;
+ }
+
+ dt3155_init_isr(minor);
+ if (copy_to_user( (void *) arg, (void *) &dt3155_status[minor],
+ sizeof(dt3155_status_t)))
+ return -EFAULT;
+ return 0;
+ }
+ default:
+ {
+ printk("DT3155: invalid IOCTL(0x%x)\n",cmd);
+ printk("DT3155: Valid commands (0x%x), (0x%x), (0x%x), (0x%x), (0x%x)\n",
+ (unsigned int)DT3155_GET_CONFIG,
+ (unsigned int)DT3155_SET_CONFIG,
+ DT3155_START, DT3155_STOP, DT3155_FLUSH);
+ return -ENOSYS;
+ }
+ }
+ return -ENOSYS;
+}
+
+/*****************************************************
+ * mmap()
+ *
+ * only allow the user to mmap the registers and buffer
+ * It is quite possible that this is broken, since the
+ * addition of of the capacity for two cards!!!!!!!!
+ * It *looks* like it should work but since I'm not
+ * sure how to use it, I'm not actually sure. (NJC? ditto by SS)
+ *****************************************************/
+static int dt3155_mmap (struct file * file, struct vm_area_struct * vma)
+{
+ /* which device are we mmapping? */
+ int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ unsigned long offset;
+ offset = vma->vm_pgoff << PAGE_SHIFT;
+
+ if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC))
+ vma->vm_flags |= VM_IO;
+
+ /* Don't try to swap out physical pages.. */
+ vma->vm_flags |= VM_RESERVED;
+
+ /* they are mapping the registers or the buffer */
+ if ((offset == dt3155_status[minor].reg_addr &&
+ vma->vm_end - vma->vm_start == PCI_PAGE_SIZE) ||
+ (offset == dt3155_status[minor].mem_addr &&
+ vma->vm_end - vma->vm_start == dt3155_status[minor].mem_size))
+ {
+ if (remap_pfn_range(vma,
+ vma->vm_start,
+ offset >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot)) {
+ printk("DT3155: remap_page_range() failed.\n");
+ return -EAGAIN;
+ }
+ }
+ else
+ {
+ printk("DT3155: dt3155_mmap() bad call.\n");
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+
+/*****************************************************
+ * open()
+ *
+ * Our special open code.
+ * MOD_INC_USE_COUNT make sure that the driver memory is not freed
+ * while the device is in use.
+ *****************************************************/
+static int dt3155_open( struct inode* inode, struct file* filep)
+{
+ int minor = MINOR(inode->i_rdev); /* what device are we opening? */
+ if (dt3155_dev_open[ minor ]) {
+ printk ("DT3155: Already opened by another process.\n");
+ return -EBUSY;
+ }
+
+ if (dt3155_status[ minor ].device_installed==0)
+ {
+ printk("DT3155 Open Error: No such device dt3155 minor number %d\n",
+ minor);
+ return -EIO;
+ }
+
+ if (dt3155_status[ minor ].state != DT3155_STATE_IDLE) {
+ printk ("DT3155: Not in idle state (state = %x)\n",
+ dt3155_status[ minor ].state);
+ return -EBUSY;
+ }
+
+ printk("DT3155: Device opened.\n");
+
+ dt3155_dev_open[ minor ] = 1 ;
+
+ dt3155_flush( minor );
+
+ /* Disable ALL interrupts */
+ int_csr_r.reg = 0;
+ WriteMReg( (dt3155_lbase[ minor ] + INT_CSR), int_csr_r.reg );
+
+ init_waitqueue_head(&(dt3155_read_wait_queue[minor]));
+
+ return 0;
+}
+
+
+/*****************************************************
+ * close()
+ *
+ * Now decrement the use count.
+ *
+ *****************************************************/
+static int dt3155_close( struct inode *inode, struct file *filep)
+{
+ int minor;
+
+ minor = MINOR(inode->i_rdev); /* which device are we closing */
+ if (!dt3155_dev_open[ minor ])
+ {
+ printk("DT3155: attempt to CLOSE a not OPEN device\n");
+ }
+ else
+ {
+ dt3155_dev_open[ minor ] = 0;
+
+ if (dt3155_status[ minor ].state != DT3155_STATE_IDLE)
+ {
+ quick_stop(minor);
+ }
+ }
+ return 0;
+}
+
+/*****************************************************
+ * read()
+ *
+ *****************************************************/
+static ssize_t dt3155_read(struct file *filep, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ /* which device are we reading from? */
+ int minor = MINOR(filep->f_dentry->d_inode->i_rdev);
+ u32 offset;
+ int frame_index;
+ frame_info_t *frame_info_p;
+
+ /* TODO: this should check the error flag and */
+ /* return an error on hardware failures */
+ if (count != sizeof(dt3155_read_t))
+ {
+ printk("DT3155 ERROR (NJC): count is not right\n");
+ return -EINVAL;
+ }
+
+
+ /* Hack here -- I'm going to allow reading even when idle.
+ * this is so that the frames can be read after STOP has
+ * been called. Leaving it here, commented out, as a reminder
+ * for a short while to make sure there are no problems.
+ * Note that if the driver is not opened in non_blocking mode,
+ * and the device is idle, then it could sit here forever! */
+
+ /* if (dt3155_status[minor].state == DT3155_STATE_IDLE)*/
+ /* return -EBUSY;*/
+
+ /* non-blocking reads should return if no data */
+ if (filep->f_flags & O_NDELAY)
+ {
+ if ((frame_index = dt3155_get_ready_buffer(minor)) < 0) {
+ /*printk( "dt3155: no buffers available (?)\n");*/
+ /* printques(minor); */
+ return -EAGAIN;
+ }
+ }
+ else
+ {
+ /*
+ * sleep till data arrives , or we get interrupted.
+ * Note that wait_event_interruptible() does not actually
+ * sleep/wait if it's condition evaluates to true upon entry.
+ */
+ wait_event_interruptible(dt3155_read_wait_queue[minor],
+ (frame_index = dt3155_get_ready_buffer(minor))
+ >= 0);
+
+ if (frame_index < 0)
+ {
+ printk ("DT3155: read: interrupted\n");
+ quick_stop (minor);
+ printques(minor);
+ return -EINTR;
+ }
+ }
+
+ frame_info_p = &dt3155_status[minor].fbuffer.frame_info[frame_index];
+
+ /* make this an offset */
+ offset = frame_info_p->addr - dt3155_status[minor].mem_addr;
+
+ put_user(offset, (unsigned int *) buf);
+ buf += sizeof(u32);
+ put_user( dt3155_status[minor].fbuffer.frame_count, (unsigned int *) buf);
+ buf += sizeof(u32);
+ put_user(dt3155_status[minor].state, (unsigned int *) buf);
+ buf += sizeof(u32);
+ if (copy_to_user(buf, frame_info_p, sizeof(frame_info_t)))
+ return -EFAULT;
+
+ return sizeof(dt3155_read_t);
+}
+
+static unsigned int dt3155_poll (struct file * filp, poll_table *wait)
+{
+ int minor = MINOR(filp->f_dentry->d_inode->i_rdev);
+
+ if (!is_ready_buf_empty(minor))
+ return POLLIN | POLLRDNORM;
+
+ poll_wait (filp, &dt3155_read_wait_queue[minor], wait);
+
+ return 0;
+}
+
+
+/*****************************************************
+ * file operations supported by DT3155 driver
+ * needed by init_module
+ * register_chrdev
+ *****************************************************/
+static struct file_operations dt3155_fops = {
+ read: dt3155_read,
+ ioctl: dt3155_ioctl,
+ mmap: dt3155_mmap,
+ poll: dt3155_poll,
+ open: dt3155_open,
+ release: dt3155_close
+};
+
+
+/*****************************************************
+ * find_PCI();
+ *
+ * PCI has been totally reworked in 2.1..
+ *****************************************************/
+static int find_PCI (void)
+{
+ struct pci_dev *pci_dev = NULL;
+ int error, pci_index = 0;
+ unsigned short rev_device;
+ unsigned long base;
+ unsigned char irq;
+
+ while ((pci_dev = pci_get_device
+ (DT3155_VENDORID, DT3155_DEVICEID, pci_dev)) != NULL)
+ {
+ pci_index ++;
+
+ /* Is it really there? */
+ if ((error =
+ pci_read_config_word(pci_dev, PCI_CLASS_DEVICE, &rev_device)))
+ continue;
+
+ /* Found a board */
+ DT_3155_DEBUG_MSG("DT3155: Device number %d \n", pci_index);
+
+ /* Make sure the driver was compiled with enough buffers to handle
+ this many boards */
+ if (pci_index > MAXBOARDS) {
+ printk("DT3155: ERROR - found %d devices, but driver only configured "
+ "for %d devices\n"
+ "DT3155: Please change MAXBOARDS in dt3155.h\n",
+ pci_index, MAXBOARDS);
+ goto err;
+ }
+
+ /* Now, just go out and make sure that this/these device(s) is/are
+ actually mapped into the kernel address space */
+ if ((error = pci_read_config_dword( pci_dev, PCI_BASE_ADDRESS_0,
+ (u32 *) &base)))
+ {
+ printk("DT3155: Was not able to find device \n");
+ goto err;
+ }
+
+ DT_3155_DEBUG_MSG("DT3155: Base address 0 for device is %lx \n", base);
+ dt3155_status[pci_index-1].reg_addr = base;
+
+ /* Remap the base address to a logical address through which we
+ * can access it. */
+ dt3155_lbase[ pci_index - 1 ] = ioremap(base,PCI_PAGE_SIZE);
+ dt3155_status[ pci_index - 1 ].reg_addr = base;
+ DT_3155_DEBUG_MSG("DT3155: New logical address is %p \n",
+ dt3155_lbase[pci_index-1]);
+ if ( !dt3155_lbase[pci_index-1] )
+ {
+ printk("DT3155: Unable to remap control registers\n");
+ goto err;
+ }
+
+ if ( (error = pci_read_config_byte( pci_dev, PCI_INTERRUPT_LINE, &irq)) )
+ {
+ printk("DT3155: Was not able to find device \n");
+ goto err;
+ }
+
+ DT_3155_DEBUG_MSG("DT3155: IRQ is %d \n",irq);
+ dt3155_status[ pci_index-1 ].irq = irq;
+ /* Set flag: kth device found! */
+ dt3155_status[ pci_index-1 ].device_installed = 1;
+ printk("DT3155: Installing device %d w/irq %d and address %p\n",
+ pci_index,
+ dt3155_status[pci_index-1].irq,
+ dt3155_lbase[pci_index-1]);
+
+ }
+ ndevices = pci_index;
+
+ return DT_3155_SUCCESS;
+
+err:
+ pci_dev_put(pci_dev);
+ return DT_3155_FAILURE;
+}
+
+u32 allocatorAddr = 0;
+
+/*****************************************************
+ * init_module()
+ *****************************************************/
+int init_module(void)
+{
+ int index;
+ int rcode = 0;
+ char *devname[ MAXBOARDS ];
+
+ devname[ 0 ] = "dt3155a";
+#if MAXBOARDS == 2
+ devname[ 1 ] = "dt3155b";
+#endif
+
+ printk("DT3155: Loading module...\n");
+
+ /* Register the device driver */
+ rcode = register_chrdev( dt3155_major, "dt3155", &dt3155_fops );
+ if( rcode < 0 )
+ {
+ printk( KERN_INFO "DT3155: register_chrdev failed \n");
+ return rcode;
+ }
+
+ if( dt3155_major == 0 )
+ dt3155_major = rcode; /* dynamic */
+
+
+ /* init the status variables. */
+ /* DMA memory is taken care of in setup_buffers() */
+ for ( index = 0; index < MAXBOARDS; index++ )
+ {
+ dt3155_status[ index ].config.acq_mode = DT3155_MODE_FRAME;
+ dt3155_status[ index ].config.continuous = DT3155_ACQ;
+ dt3155_status[ index ].config.cols = DT3155_MAX_COLS;
+ dt3155_status[ index ].config.rows = DT3155_MAX_ROWS;
+ dt3155_status[ index ].state = DT3155_STATE_IDLE;
+
+ /* find_PCI() will check if devices are installed; */
+ /* first assume they're not: */
+ dt3155_status[ index ].mem_addr = 0;
+ dt3155_status[ index ].mem_size = 0;
+ dt3155_status[ index ].state = DT3155_STATE_IDLE;
+ dt3155_status[ index ].device_installed = 0;
+ }
+
+ /* Now let's find the hardware. find_PCI() will set ndevices to the
+ * number of cards found in this machine. */
+ {
+ if ( (rcode = find_PCI()) != DT_3155_SUCCESS )
+ {
+ printk("DT3155 error: find_PCI() failed to find dt3155 board(s)\n");
+ unregister_chrdev( dt3155_major, "dt3155" );
+ return rcode;
+ }
+ }
+
+ /* Ok, time to setup the frame buffers */
+ if( (rcode = dt3155_setup_buffers(&allocatorAddr)) < 0 )
+ {
+ printk("DT3155: Error: setting up buffer not large enough.");
+ unregister_chrdev( dt3155_major, "dt3155" );
+ return rcode;
+ }
+
+ /* If we are this far, then there is enough RAM */
+ /* for the buffers: Print the configuration. */
+ for( index = 0; index < ndevices; index++ )
+ {
+ printk("DT3155: Device = %d; acq_mode = %d; "
+ "continuous = %d; cols = %d; rows = %d;\n",
+ index ,
+ dt3155_status[ index ].config.acq_mode,
+ dt3155_status[ index ].config.continuous,
+ dt3155_status[ index ].config.cols,
+ dt3155_status[ index ].config.rows);
+ printk("DT3155: m_addr = 0x%x; m_size = %ld; "
+ "state = %d; device_installed = %d\n",
+ dt3155_status[ index ].mem_addr,
+ (long int)dt3155_status[ index ].mem_size,
+ dt3155_status[ index ].state,
+ dt3155_status[ index ].device_installed);
+ }
+
+ /* Disable ALL interrupts */
+ int_csr_r.reg = 0;
+ for( index = 0; index < ndevices; index++ )
+ {
+ WriteMReg( (dt3155_lbase[ index ] + INT_CSR), int_csr_r.reg );
+ if( dt3155_status[ index ].device_installed )
+ {
+ /*
+ * This driver *looks* like it can handle sharing interrupts,
+ * but I can't actually test myself. I've had reports that it
+ * DOES work so I'll enable it for now. This comment will remain
+ * as a reminder in case any problems arise. (SS)
+ */
+ /* in older kernels flags are: SA_SHIRQ | SA_INTERRUPT */
+ rcode = request_irq( dt3155_status[ index ].irq, (void *)dt3155_isr,
+ IRQF_SHARED | IRQF_DISABLED, devname[ index ],
+ (void*) &dt3155_status[index]);
+ if( rcode < 0 )
+ {
+ printk("DT3155: minor %d request_irq failed for IRQ %d\n",
+ index, dt3155_status[index].irq);
+ unregister_chrdev( dt3155_major, "dt3155" );
+ return rcode;
+ }
+ }
+ }
+
+ printk("DT3155: finished loading\n");
+
+ return 0;
+}
+
+/*****************************************************
+ * cleanup_module(void)
+ *
+ *****************************************************/
+void cleanup_module(void)
+{
+ int index;
+
+ printk("DT3155: cleanup_module called\n");
+
+ /* removed DMA allocated with the allocator */
+#ifdef STANDALONE_ALLOCATOR
+ if (allocatorAddr != 0)
+ allocator_free_dma(allocatorAddr);
+#else
+ allocator_cleanup();
+#endif
+
+ unregister_chrdev( dt3155_major, "dt3155" );
+
+ for( index = 0; index < ndevices; index++ )
+ {
+ if( dt3155_status[ index ].device_installed == 1 )
+ {
+ printk( "DT3155: Freeing irq %d for device %d\n",
+ dt3155_status[ index ].irq, index );
+ free_irq( dt3155_status[ index ].irq, (void*)&dt3155_status[index] );
+ }
+ }
+}
+
diff --git a/drivers/staging/dt3155/dt3155_drv.h b/drivers/staging/dt3155/dt3155_drv.h
new file mode 100644
index 00000000000..95e68c3388a
--- /dev/null
+++ b/drivers/staging/dt3155/dt3155_drv.h
@@ -0,0 +1,45 @@
+/*
+
+Copyright 1996,2002 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
+ Scott Smedley
+
+This file is part of the DT3155 Device Driver.
+
+The DT3155 Device 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.
+
+The DT3155 Device 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 the DT3155 Device Driver; if not, write to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+MA 02111-1307 USA
+*/
+
+#ifndef DT3155_DRV_INC
+#define DT3155_DRV_INC
+
+/* kernel logical address of the frame grabbers */
+extern u8 *dt3155_lbase[MAXBOARDS];
+
+/* kernel logical address of ram buffer */
+extern u8 *dt3155_bbase;
+
+#ifdef __KERNEL__
+#include <linux/wait.h>
+
+/* wait queue for reads */
+extern wait_queue_head_t dt3155_read_wait_queue[MAXBOARDS];
+#endif
+
+/* number of devices */
+extern u32 ndevices;
+
+extern int dt3155_errno;
+
+#endif
diff --git a/drivers/staging/dt3155/dt3155_io.c b/drivers/staging/dt3155/dt3155_io.c
new file mode 100644
index 00000000000..6b9c68501a6
--- /dev/null
+++ b/drivers/staging/dt3155/dt3155_io.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright 1996,2002,2005 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
+ * Jason Lapenta, Scott Smedley
+ *
+ * This file is part of the DT3155 Device Driver.
+ *
+ * The DT3155 Device 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.
+ *
+ * The DT3155 Device 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.
+ */
+
+/*
+ * This file provides some basic register io routines. It is modified from
+ * demo code provided by Data Translations.
+ */
+
+#include <linux/delay.h>
+#include "dt3155.h"
+#include "dt3155_io.h"
+#include "dt3155_drv.h"
+
+
+/****** local copies of board's 32 bit registers ******/
+u32 even_dma_start_r; /* bit 0 should always be 0 */
+u32 odd_dma_start_r; /* .. */
+u32 even_dma_stride_r; /* bits 0&1 should always be 0 */
+u32 odd_dma_stride_r; /* .. */
+u32 even_pixel_fmt_r;
+u32 odd_pixel_fmt_r;
+
+FIFO_TRIGGER_R fifo_trigger_r;
+XFER_MODE_R xfer_mode_r;
+CSR1_R csr1_r;
+RETRY_WAIT_CNT_R retry_wait_cnt_r;
+INT_CSR_R int_csr_r;
+
+u32 even_fld_mask_r;
+u32 odd_fld_mask_r;
+
+MASK_LENGTH_R mask_length_r;
+FIFO_FLAG_CNT_R fifo_flag_cnt_r;
+IIC_CLK_DUR_R iic_clk_dur_r;
+IIC_CSR1_R iic_csr1_r;
+IIC_CSR2_R iic_csr2_r;
+DMA_UPPER_LMT_R even_dma_upper_lmt_r;
+DMA_UPPER_LMT_R odd_dma_upper_lmt_r;
+
+
+
+/******** local copies of board's 8 bit I2C registers ******/
+I2C_CSR2 i2c_csr2;
+I2C_EVEN_CSR i2c_even_csr;
+I2C_ODD_CSR i2c_odd_csr;
+I2C_CONFIG i2c_config;
+u8 i2c_dt_id;
+u8 i2c_x_clip_start;
+u8 i2c_y_clip_start;
+u8 i2c_x_clip_end;
+u8 i2c_y_clip_end;
+u8 i2c_ad_addr;
+u8 i2c_ad_lut;
+I2C_AD_CMD i2c_ad_cmd;
+u8 i2c_dig_out;
+u8 i2c_pm_lut_addr;
+u8 i2c_pm_lut_data;
+
+/*
+ * wait_ibsyclr()
+ *
+ * This function handles read/write timing and r/w timeout error
+ *
+ * Returns TRUE if NEW_CYCLE clears
+ * Returns FALSE if NEW_CYCLE doesn't clear in roughly 3 msecs, otherwise
+ * returns 0
+ */
+static int wait_ibsyclr(u8 *lpReg)
+{
+ /* wait 100 microseconds */
+ udelay(100L);
+ /* __delay(loops_per_sec/10000); */
+ if (iic_csr2_r.fld.NEW_CYCLE) {
+ /* if NEW_CYCLE didn't clear */
+ /* TIMEOUT ERROR */
+ dt3155_errno = DT_ERR_I2C_TIMEOUT;
+ return FALSE;
+ } else
+ return TRUE; /* no error */
+}
+
+/*
+ * WriteI2C()
+ *
+ * This function handles writing to 8-bit DT3155 registers
+ *
+ * 1st parameter is pointer to 32-bit register base address
+ * 2nd parameter is reg. index;
+ * 3rd is value to be written
+ *
+ * Returns TRUE - Successful completion
+ * FALSE - Timeout error - cycle did not complete!
+ */
+int WriteI2C(u8 *lpReg, u_short wIregIndex, u8 byVal)
+{
+ int writestat; /* status for return */
+
+ /* read 32 bit IIC_CSR2 register data into union */
+
+ ReadMReg((lpReg + IIC_CSR2), iic_csr2_r.reg);
+
+ /* for write operation */
+ iic_csr2_r.fld.DIR_RD = 0;
+ /* I2C address of I2C register: */
+ iic_csr2_r.fld.DIR_ADDR = wIregIndex;
+ /* 8 bit data to be written to I2C reg */
+ iic_csr2_r.fld.DIR_WR_DATA = byVal;
+ /* will start a direct I2C cycle: */
+ iic_csr2_r.fld.NEW_CYCLE = 1;
+
+ /* xfer union data into 32 bit IIC_CSR2 register */
+ WriteMReg((lpReg + IIC_CSR2), iic_csr2_r.reg);
+
+ /* wait for IIC cycle to finish */
+ writestat = wait_ibsyclr(lpReg);
+ return writestat;
+}
+
+/*
+ * ReadI2C()
+ *
+ * This function handles reading from 8-bit DT3155 registers
+ *
+ * 1st parameter is pointer to 32-bit register base address
+ * 2nd parameter is reg. index;
+ * 3rd is adrs of value to be read
+ *
+ * Returns TRUE - Successful completion
+ * FALSE - Timeout error - cycle did not complete!
+ */
+int ReadI2C(u8 *lpReg, u_short wIregIndex, u8 *byVal)
+{
+ int writestat; /* status for return */
+
+ /* read 32 bit IIC_CSR2 register data into union */
+ ReadMReg((lpReg + IIC_CSR2), iic_csr2_r.reg);
+
+ /* for read operation */
+ iic_csr2_r.fld.DIR_RD = 1;
+
+ /* I2C address of I2C register: */
+ iic_csr2_r.fld.DIR_ADDR = wIregIndex;
+
+ /* will start a direct I2C cycle: */
+ iic_csr2_r.fld.NEW_CYCLE = 1;
+
+ /* xfer union's data into 32 bit IIC_CSR2 register */
+ WriteMReg((lpReg + IIC_CSR2), iic_csr2_r.reg);
+
+ /* wait for IIC cycle to finish */
+ writestat = wait_ibsyclr(lpReg);
+
+ /* Next 2 commands read 32 bit IIC_CSR1 register's data into union */
+ /* first read data is in IIC_CSR1 */
+ ReadMReg((lpReg + IIC_CSR1), iic_csr1_r.reg);
+
+ /* now get data u8 out of register */
+ *byVal = (u8) iic_csr1_r.fld.RD_DATA;
+
+ return writestat;
+}
diff --git a/drivers/staging/dt3155/dt3155_io.h b/drivers/staging/dt3155/dt3155_io.h
new file mode 100644
index 00000000000..d1a25100169
--- /dev/null
+++ b/drivers/staging/dt3155/dt3155_io.h
@@ -0,0 +1,358 @@
+/*
+
+Copyright 1996,2002 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
+ Jason Lapenta, Scott Smedley
+
+This file is part of the DT3155 Device Driver.
+
+The DT3155 Device 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.
+
+The DT3155 Device 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 the DT3155 Device Driver; if not, write to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+MA 02111-1307 USA
+
+
+-- Changes --
+
+ Date Programmer Description of changes made
+ -------------------------------------------------------------------
+ 24-Jul-2002 SS GPL licence.
+
+*/
+
+/* This code is a modified version of examples provided by Data Translations.*/
+
+#ifndef DT3155_IO_INC
+#define DT3155_IO_INC
+
+/* macros to access registers */
+
+#define WriteMReg(Address, Data) (*((u32 *)(Address)) = Data)
+#define ReadMReg(Address, Data) (Data = *((u32 *)(Address)))
+
+/***************** 32 bit register globals **************/
+
+/* offsets for 32-bit memory mapped registers */
+
+#define EVEN_DMA_START 0x000
+#define ODD_DMA_START 0x00C
+#define EVEN_DMA_STRIDE 0x018
+#define ODD_DMA_STRIDE 0x024
+#define EVEN_PIXEL_FMT 0x030
+#define ODD_PIXEL_FMT 0x034
+#define FIFO_TRIGGER 0x038
+#define XFER_MODE 0x03C
+#define CSR1 0x040
+#define RETRY_WAIT_CNT 0x044
+#define INT_CSR 0x048
+#define EVEN_FLD_MASK 0x04C
+#define ODD_FLD_MASK 0x050
+#define MASK_LENGTH 0x054
+#define FIFO_FLAG_CNT 0x058
+#define IIC_CLK_DUR 0x05C
+#define IIC_CSR1 0x060
+#define IIC_CSR2 0x064
+#define EVEN_DMA_UPPR_LMT 0x08C
+#define ODD_DMA_UPPR_LMT 0x090
+
+#define CLK_DUR_VAL 0x01010101
+
+
+
+/******** Assignments and Typedefs for 32 bit Memory Mapped Registers ********/
+
+typedef union fifo_trigger_tag {
+ u32 reg;
+ struct {
+ u32 PACKED:6;
+ u32 :9;
+ u32 PLANER:7;
+ u32 :9;
+ } fld;
+} FIFO_TRIGGER_R;
+
+typedef union xfer_mode_tag {
+ u32 reg;
+ struct {
+ u32 :2;
+ u32 FIELD_TOGGLE:1;
+ u32 :5;
+ u32 :2;
+ u32 :22;
+ } fld;
+} XFER_MODE_R;
+
+typedef union csr1_tag {
+ u32 reg;
+ struct {
+ u32 CAP_CONT_EVE:1;
+ u32 CAP_CONT_ODD:1;
+ u32 CAP_SNGL_EVE:1;
+ u32 CAP_SNGL_ODD:1;
+ u32 FLD_DN_EVE :1;
+ u32 FLD_DN_ODD :1;
+ u32 SRST :1;
+ u32 FIFO_EN :1;
+ u32 FLD_CRPT_EVE:1;
+ u32 FLD_CRPT_ODD:1;
+ u32 ADDR_ERR_EVE:1;
+ u32 ADDR_ERR_ODD:1;
+ u32 CRPT_DIS :1;
+ u32 RANGE_EN :1;
+ u32 :16;
+ } fld;
+} CSR1_R;
+
+typedef union retry_wait_cnt_tag {
+ u32 reg;
+ struct {
+ u32 RTRY_WAIT_CNT:8;
+ u32 :24;
+ } fld;
+} RETRY_WAIT_CNT_R;
+
+typedef union int_csr_tag {
+ u32 reg;
+ struct {
+ u32 FLD_END_EVE :1;
+ u32 FLD_END_ODD :1;
+ u32 FLD_START :1;
+ u32 :5;
+ u32 FLD_END_EVE_EN:1;
+ u32 FLD_END_ODD_EN:1;
+ u32 FLD_START_EN :1;
+ u32 :21;
+ } fld;
+} INT_CSR_R;
+
+typedef union mask_length_tag {
+ u32 reg;
+ struct {
+ u32 MASK_LEN_EVE:5;
+ u32 :11;
+ u32 MASK_LEN_ODD:5;
+ u32 :11;
+ } fld;
+} MASK_LENGTH_R;
+
+typedef union fifo_flag_cnt_tag {
+ u32 reg;
+ struct {
+ u32 AF_COUNT:7;
+ u32 :9;
+ u32 AE_COUNT:7;
+ u32 :9;
+ } fld;
+} FIFO_FLAG_CNT_R;
+
+typedef union iic_clk_dur {
+ u32 reg;
+ struct {
+ u32 PHASE_1:8;
+ u32 PHASE_2:8;
+ u32 PHASE_3:8;
+ u32 PHASE_4:8;
+ } fld;
+} IIC_CLK_DUR_R;
+
+typedef union iic_csr1_tag {
+ u32 reg;
+ struct {
+ u32 AUTO_EN :1;
+ u32 BYPASS :1;
+ u32 SDA_OUT :1;
+ u32 SCL_OUT :1;
+ u32 :4;
+ u32 AUTO_ABORT :1;
+ u32 DIRECT_ABORT:1;
+ u32 SDA_IN :1;
+ u32 SCL_IN :1;
+ u32 :4;
+ u32 AUTO_ADDR :8;
+ u32 RD_DATA :8;
+ } fld;
+} IIC_CSR1_R;
+
+/**********************************
+ * iic_csr2_tag
+ */
+typedef union iic_csr2_tag {
+ u32 reg;
+ struct {
+ u32 DIR_WR_DATA :8;
+ u32 DIR_SUB_ADDR:8;
+ u32 DIR_RD :1;
+ u32 DIR_ADDR :7;
+ u32 NEW_CYCLE :1;
+ u32 :7;
+ } fld;
+} IIC_CSR2_R;
+
+/* use for both EVEN and ODD DMA UPPER LIMITS */
+
+/*
+ * dma_upper_lmt_tag
+ */
+typedef union dma_upper_lmt_tag {
+ u32 reg;
+ struct {
+ u32 DMA_UPPER_LMT_VAL:24;
+ u32 :8;
+ } fld;
+} DMA_UPPER_LMT_R;
+
+
+/*
+ * Global declarations of local copies of boards' 32 bit registers
+ */
+extern u32 even_dma_start_r; /* bit 0 should always be 0 */
+extern u32 odd_dma_start_r; /* .. */
+extern u32 even_dma_stride_r; /* bits 0&1 should always be 0 */
+extern u32 odd_dma_stride_r; /* .. */
+extern u32 even_pixel_fmt_r;
+extern u32 odd_pixel_fmt_r;
+
+extern FIFO_TRIGGER_R fifo_trigger_r;
+extern XFER_MODE_R xfer_mode_r;
+extern CSR1_R csr1_r;
+extern RETRY_WAIT_CNT_R retry_wait_cnt_r;
+extern INT_CSR_R int_csr_r;
+
+extern u32 even_fld_mask_r;
+extern u32 odd_fld_mask_r;
+
+extern MASK_LENGTH_R mask_length_r;
+extern FIFO_FLAG_CNT_R fifo_flag_cnt_r;
+extern IIC_CLK_DUR_R iic_clk_dur_r;
+extern IIC_CSR1_R iic_csr1_r;
+extern IIC_CSR2_R iic_csr2_r;
+extern DMA_UPPER_LMT_R even_dma_upper_lmt_r;
+extern DMA_UPPER_LMT_R odd_dma_upper_lmt_r;
+
+
+
+/***************** 8 bit I2C register globals ***********/
+#define CSR2 0x010 /* indices of 8-bit I2C mapped reg's*/
+#define EVEN_CSR 0x011
+#define ODD_CSR 0x012
+#define CONFIG 0x013
+#define DT_ID 0x01F
+#define X_CLIP_START 0x020
+#define Y_CLIP_START 0x022
+#define X_CLIP_END 0x024
+#define Y_CLIP_END 0x026
+#define AD_ADDR 0x030
+#define AD_LUT 0x031
+#define AD_CMD 0x032
+#define DIG_OUT 0x040
+#define PM_LUT_ADDR 0x050
+#define PM_LUT_DATA 0x051
+
+
+/******** Assignments and Typedefs for 8 bit I2C Registers********************/
+
+typedef union i2c_csr2_tag {
+ u8 reg;
+ struct {
+ u8 CHROM_FIL:1;
+ u8 SYNC_SNTL:1;
+ u8 HZ50:1;
+ u8 SYNC_PRESENT:1;
+ u8 BUSY_EVE:1;
+ u8 BUSY_ODD:1;
+ u8 DISP_PASS:1;
+ } fld;
+} I2C_CSR2;
+
+typedef union i2c_even_csr_tag {
+ u8 reg;
+ struct {
+ u8 DONE_EVE :1;
+ u8 SNGL_EVE :1;
+ u8 ERROR_EVE:1;
+ u8 :5;
+ } fld;
+} I2C_EVEN_CSR;
+
+typedef union i2c_odd_csr_tag {
+ u8 reg;
+ struct {
+ u8 DONE_ODD:1;
+ u8 SNGL_ODD:1;
+ u8 ERROR_ODD:1;
+ u8 :5;
+ } fld;
+} I2C_ODD_CSR;
+
+typedef union i2c_config_tag {
+ u8 reg;
+ struct {
+ u8 ACQ_MODE:2;
+ u8 EXT_TRIG_EN:1;
+ u8 EXT_TRIG_POL:1;
+ u8 H_SCALE:1;
+ u8 CLIP:1;
+ u8 PM_LUT_SEL:1;
+ u8 PM_LUT_PGM:1;
+ } fld;
+} I2C_CONFIG;
+
+
+typedef union i2c_ad_cmd_tag {
+ /* bits can have 3 different meanings depending on value of AD_ADDR */
+ u8 reg;
+ /* Bt252 Command Register if AD_ADDR = 00h */
+ struct {
+ u8 :2;
+ u8 SYNC_LVL_SEL:2;
+ u8 SYNC_CNL_SEL:2;
+ u8 DIGITIZE_CNL_SEL1:2;
+ } bt252_command;
+
+ /* Bt252 IOUT0 register if AD_ADDR = 01h */
+ struct {
+ u8 IOUT_DATA:8;
+ } bt252_iout0;
+
+ /* BT252 IOUT1 register if AD_ADDR = 02h */
+ struct {
+ u8 IOUT_DATA:8;
+ } bt252_iout1;
+} I2C_AD_CMD;
+
+
+/***** Global declarations of local copies of boards' 8 bit I2C registers ***/
+
+extern I2C_CSR2 i2c_csr2;
+extern I2C_EVEN_CSR i2c_even_csr;
+extern I2C_ODD_CSR i2c_odd_csr;
+extern I2C_CONFIG i2c_config;
+extern u8 i2c_dt_id;
+extern u8 i2c_x_clip_start;
+extern u8 i2c_y_clip_start;
+extern u8 i2c_x_clip_end;
+extern u8 i2c_y_clip_end;
+extern u8 i2c_ad_addr;
+extern u8 i2c_ad_lut;
+extern I2C_AD_CMD i2c_ad_cmd;
+extern u8 i2c_dig_out;
+extern u8 i2c_pm_lut_addr;
+extern u8 i2c_pm_lut_data;
+
+/* Functions for Global use */
+
+/* access 8-bit IIC registers */
+
+extern int ReadI2C(u8 *lpReg, u_short wIregIndex, u8 *byVal);
+extern int WriteI2C(u8 *lpReg, u_short wIregIndex, u8 byVal);
+
+#endif
diff --git a/drivers/staging/dt3155/dt3155_isr.c b/drivers/staging/dt3155/dt3155_isr.c
new file mode 100644
index 00000000000..fd7f93d6c33
--- /dev/null
+++ b/drivers/staging/dt3155/dt3155_isr.c
@@ -0,0 +1,516 @@
+/*
+
+Copyright 1996,2002,2005 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
+ Jason Lapenta, Scott Smedley, Greg Sharp
+
+This file is part of the DT3155 Device Driver.
+
+The DT3155 Device 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.
+
+The DT3155 Device 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 the DT3155 Device Driver; if not, write to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+MA 02111-1307 USA
+
+ File: dt3155_isr.c
+Purpose: Buffer management routines, and other routines for the ISR
+ (the actual isr is in dt3155_drv.c)
+
+-- Changes --
+
+ Date Programmer Description of changes made
+ -------------------------------------------------------------------
+ 03-Jul-2000 JML n/a
+ 02-Apr-2002 SS Mods to make work with separate allocator
+ module; Merged John Roll's mods to make work with
+ multiple boards.
+ 10-Jul-2002 GCS Complete rewrite of setup_buffers to disallow
+ buffers which span a 4MB boundary.
+ 24-Jul-2002 SS GPL licence.
+ 30-Jul-2002 NJC Added support for buffer loop.
+ 31-Jul-2002 NJC Complete rewrite of buffer management
+ 02-Aug-2002 NJC Including slab.h instead of malloc.h (no warning).
+ Also, allocator_init() now returns allocator_max
+ so cleaned up allocate_buffers() accordingly.
+ 08-Aug-2005 SS port to 2.6 kernel.
+
+*/
+
+#include <asm/system.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+
+#include "dt3155.h"
+#include "dt3155_drv.h"
+#include "dt3155_io.h"
+#include "dt3155_isr.h"
+#include "allocator.h"
+
+#define FOUR_MB (0x0400000) /* Can't DMA accross a 4MB boundary!*/
+#define UPPER_10_BITS (0x3FF<<22) /* Can't DMA accross a 4MB boundary!*/
+
+
+/* Pointer into global structure for handling buffers */
+struct dt3155_fbuffer_s *dt3155_fbuffer[MAXBOARDS] = {NULL
+#if MAXBOARDS == 2
+ , NULL
+#endif
+};
+
+/******************************************************************************
+ * Simple array based que struct
+ *
+ * Some handy functions using the buffering structure.
+ *****************************************************************************/
+
+
+/***************************
+ * are_empty_buffers
+ * m is minor # of device
+ ***************************/
+inline bool are_empty_buffers( int m )
+{
+ return ( dt3155_fbuffer[ m ]->empty_len );
+}
+
+/**************************
+ * push_empty
+ * m is minor # of device
+ *
+ * This is slightly confusing. The number empty_len is the literal #
+ * of empty buffers. After calling, empty_len-1 is the index into the
+ * empty buffer stack. So, if empty_len == 1, there is one empty buffer,
+ * given by dt3155_fbuffer[m]->empty_buffers[0].
+ * empty_buffers should never fill up, though this is not checked.
+ **************************/
+inline void push_empty( int index, int m )
+{
+ dt3155_fbuffer[m]->empty_buffers[ dt3155_fbuffer[m]->empty_len ] = index;
+ dt3155_fbuffer[m]->empty_len++;
+}
+
+/**************************
+ * pop_empty( m )
+ * m is minor # of device
+ **************************/
+inline int pop_empty( int m )
+{
+ dt3155_fbuffer[m]->empty_len--;
+ return dt3155_fbuffer[m]->empty_buffers[ dt3155_fbuffer[m]->empty_len ];
+}
+
+/*************************
+ * is_ready_buf_empty( m )
+ * m is minor # of device
+ *************************/
+inline bool is_ready_buf_empty( int m )
+{
+ return ((dt3155_fbuffer[ m ]->ready_len) == 0);
+}
+
+/*************************
+ * is_ready_buf_full( m )
+ * m is minor # of device
+ * this should *never* be true if there are any active, locked or empty
+ * buffers, since it corresponds to nbuffers ready buffers!!
+ * 7/31/02: total rewrite. --NJC
+ *************************/
+inline bool is_ready_buf_full( int m )
+{
+ return ( dt3155_fbuffer[ m ]->ready_len == dt3155_fbuffer[ m ]->nbuffers );
+}
+
+/*****************************************************
+ * push_ready( m, buffer )
+ * m is minor # of device
+ *
+ *****************************************************/
+inline void push_ready( int m, int index )
+{
+ int head = dt3155_fbuffer[m]->ready_head;
+
+ dt3155_fbuffer[ m ]->ready_que[ head ] = index;
+ dt3155_fbuffer[ m ]->ready_head = ( (head + 1) %
+ (dt3155_fbuffer[ m ]->nbuffers) );
+ dt3155_fbuffer[ m ]->ready_len++;
+
+}
+
+/*****************************************************
+ * get_tail()
+ * m is minor # of device
+ *
+ * Simply comptutes the tail given the head and the length.
+ *****************************************************/
+static inline int get_tail( int m )
+{
+ return ((dt3155_fbuffer[ m ]->ready_head -
+ dt3155_fbuffer[ m ]->ready_len +
+ dt3155_fbuffer[ m ]->nbuffers)%
+ (dt3155_fbuffer[ m ]->nbuffers));
+}
+
+
+
+/*****************************************************
+ * pop_ready()
+ * m is minor # of device
+ *
+ * This assumes that there is a ready buffer ready... should
+ * be checked (e.g. with is_ready_buf_empty() prior to call.
+ *****************************************************/
+inline int pop_ready( int m )
+{
+ int tail;
+ tail = get_tail(m);
+ dt3155_fbuffer[ m ]->ready_len--;
+ return dt3155_fbuffer[ m ]->ready_que[ tail ];
+}
+
+
+/*****************************************************
+ * printques
+ * m is minor # of device
+ *****************************************************/
+inline void printques( int m )
+{
+ int head = dt3155_fbuffer[ m ]->ready_head;
+ int tail;
+ int num = dt3155_fbuffer[ m ]->nbuffers;
+ int frame_index;
+ int index;
+
+ tail = get_tail(m);
+
+ printk("\n R:");
+ for ( index = tail; index != head; index++, index = index % (num) )
+ {
+ frame_index = dt3155_fbuffer[ m ]->ready_que[ index ];
+ printk(" %d ", frame_index );
+ }
+
+ printk("\n E:");
+ for ( index = 0; index < dt3155_fbuffer[ m ]->empty_len; index++ )
+ {
+ frame_index = dt3155_fbuffer[ m ]->empty_buffers[ index ];
+ printk(" %d ", frame_index );
+ }
+
+ frame_index = dt3155_fbuffer[ m ]->active_buf;
+ printk("\n A: %d", frame_index);
+
+ frame_index = dt3155_fbuffer[ m ]->locked_buf;
+ printk("\n L: %d \n", frame_index );
+
+}
+
+/*****************************************************
+ * adjust_4MB
+ *
+ * If a buffer intersects the 4MB boundary, push
+ * the start address up to the beginning of the
+ * next 4MB chunk (assuming bufsize < 4MB).
+ *****************************************************/
+u32 adjust_4MB (u32 buf_addr, u32 bufsize) {
+ if (((buf_addr+bufsize) & UPPER_10_BITS) != (buf_addr & UPPER_10_BITS))
+ return (buf_addr+bufsize) & UPPER_10_BITS;
+ else
+ return buf_addr;
+}
+
+
+/*****************************************************
+ * allocate_buffers
+ *
+ * Try to allocate enough memory for all requested
+ * buffers. If there is not enough free space
+ * try for less memory.
+ *****************************************************/
+void allocate_buffers (u32 *buf_addr, u32* total_size_kbs,
+ u32 bufsize)
+{
+ /* Compute the minimum amount of memory guaranteed to hold all
+ MAXBUFFERS such that no buffer crosses the 4MB boundary.
+ Store this value in the variable "full_size" */
+
+ u32 allocator_max;
+ u32 bufs_per_chunk = (FOUR_MB / bufsize);
+ u32 filled_chunks = (MAXBUFFERS-1) / bufs_per_chunk;
+ u32 leftover_bufs = MAXBUFFERS - filled_chunks * bufs_per_chunk;
+
+ u32 full_size = bufsize /* possibly unusable part of 1st chunk */
+ + filled_chunks * FOUR_MB /* max # of completely filled 4mb chunks */
+ + leftover_bufs * bufsize; /* these buffs will be in a partly filled
+ chunk at beginning or end */
+
+ u32 full_size_kbs = 1 + (full_size-1) / 1024;
+ u32 min_size_kbs = 2*ndevices*bufsize / 1024;
+ u32 size_kbs;
+
+ /* Now, try to allocate full_size. If this fails, keep trying for
+ less & less memory until it succeeds. */
+#ifndef STANDALONE_ALLOCATOR
+ /* initialize the allocator */
+ allocator_init(&allocator_max);
+#endif
+ size_kbs = full_size_kbs;
+ *buf_addr = 0;
+ printk("DT3155: We would like to get: %d KB\n", full_size_kbs);
+ printk("DT3155: ...but need at least: %d KB\n", min_size_kbs);
+ printk("DT3155: ...the allocator has: %d KB\n", allocator_max);
+ size_kbs = (full_size_kbs <= allocator_max ? full_size_kbs : allocator_max);
+ if (size_kbs > min_size_kbs) {
+ if ((*buf_addr = allocator_allocate_dma (size_kbs, GFP_KERNEL)) != 0) {
+ printk("DT3155: Managed to allocate: %d KB\n", size_kbs);
+ *total_size_kbs = size_kbs;
+ return;
+ }
+ }
+ /* If we got here, the allocation failed */
+ printk ("DT3155: Allocator failed!\n");
+ *buf_addr = 0;
+ *total_size_kbs = 0;
+ return;
+
+}
+
+
+/*****************************************************
+ * dt3155_setup_buffers
+ *
+ * setup_buffers just puts the buffering system into
+ * a consistent state before the start of interrupts
+ *
+ * JML : it looks like all the buffers need to be
+ * continuous. So I'm going to try and allocate one
+ * continuous buffer.
+ *
+ * GCS : Fix DMA problems when buffer spans
+ * 4MB boundary. Also, add error checking. This
+ * function will return -ENOMEM when not enough memory.
+ *****************************************************/
+u32 dt3155_setup_buffers(u32 *allocatorAddr)
+
+{
+ u32 index;
+ u32 rambuff_addr; /* start of allocation */
+ u32 rambuff_size; /* total size allocated to driver */
+ u32 rambuff_acm; /* accumlator, keep track of how much
+ is left after being split up*/
+ u32 rambuff_end; /* end of rambuff */
+ u32 numbufs; /* number of useful buffers allocated (per device) */
+ u32 bufsize = DT3155_MAX_ROWS * DT3155_MAX_COLS;
+ int m; /* minor # of device, looped for all devs */
+
+ /* zero the fbuffer status and address structure */
+ for ( m = 0; m < ndevices; m++)
+ {
+ dt3155_fbuffer[ m ] = &(dt3155_status[ m ].fbuffer);
+
+ /* Make sure the buffering variables are consistent */
+ {
+ u8 *ptr = (u8 *) dt3155_fbuffer[ m ];
+ for( index = 0; index < sizeof(struct dt3155_fbuffer_s); index++)
+ *(ptr++)=0;
+ }
+ }
+
+ /* allocate a large contiguous chunk of RAM */
+ allocate_buffers (&rambuff_addr, &rambuff_size, bufsize);
+ printk("DT3155: mem info\n");
+ printk(" - rambuf_addr = 0x%x \n", rambuff_addr);
+ printk(" - length (kb) = %u \n", rambuff_size);
+ if( rambuff_addr == 0 )
+ {
+ printk( KERN_INFO
+ "DT3155: Error setup_buffers() allocator dma failed \n" );
+ return -ENOMEM;
+ }
+ *allocatorAddr = rambuff_addr;
+ rambuff_end = rambuff_addr + 1024 * rambuff_size;
+
+ /* after allocation, we need to count how many useful buffers there
+ are so we can give an equal number to each device */
+ rambuff_acm = rambuff_addr;
+ for ( index = 0; index < MAXBUFFERS; index++) {
+ rambuff_acm = adjust_4MB (rambuff_acm, bufsize);/*avoid spanning 4MB bdry*/
+ if (rambuff_acm + bufsize > rambuff_end)
+ break;
+ rambuff_acm += bufsize;
+ }
+ /* Following line is OK, will waste buffers if index
+ * not evenly divisible by ndevices -NJC*/
+ numbufs = index / ndevices;
+ printk(" - numbufs = %u\n", numbufs);
+ if (numbufs < 2) {
+ printk( KERN_INFO
+ "DT3155: Error setup_buffers() couldn't allocate 2 bufs/board\n" );
+ return -ENOMEM;
+ }
+
+ /* now that we have board memory we spit it up */
+ /* between the boards and the buffers */
+ rambuff_acm = rambuff_addr;
+ for ( m = 0; m < ndevices; m ++)
+ {
+ rambuff_acm = adjust_4MB (rambuff_acm, bufsize);
+
+ /* Save the start of this boards buffer space (for mmap). */
+ dt3155_status[ m ].mem_addr = rambuff_acm;
+
+ for (index = 0; index < numbufs; index++)
+ {
+ rambuff_acm = adjust_4MB (rambuff_acm, bufsize);
+ if (rambuff_acm + bufsize > rambuff_end) {
+ /* Should never happen */
+ printk ("DT3155 PROGRAM ERROR (GCS)\n"
+ "Error distributing allocated buffers\n");
+ return -ENOMEM;
+ }
+
+ dt3155_fbuffer[ m ]->frame_info[ index ].addr = rambuff_acm;
+ push_empty( index, m );
+ /* printk(" - Buffer : %lx\n",
+ * dt3155_fbuffer[ m ]->frame_info[ index ].addr );
+ */
+ dt3155_fbuffer[ m ]->nbuffers += 1;
+ rambuff_acm += bufsize;
+ }
+
+ /* Make sure there is an active buffer there. */
+ dt3155_fbuffer[ m ]->active_buf = pop_empty( m );
+ dt3155_fbuffer[ m ]->even_happened = 0;
+ dt3155_fbuffer[ m ]->even_stopped = 0;
+
+ /* make sure there is no locked_buf JML 2/28/00 */
+ dt3155_fbuffer[ m ]->locked_buf = -1;
+
+ dt3155_status[ m ].mem_size =
+ rambuff_acm - dt3155_status[ m ].mem_addr;
+
+ /* setup the ready queue */
+ dt3155_fbuffer[ m ]->ready_head = 0;
+ dt3155_fbuffer[ m ]->ready_len = 0;
+ printk("Available buffers for device %d: %d\n",
+ m, dt3155_fbuffer[ m ]->nbuffers);
+ }
+
+ return 1;
+}
+
+/*****************************************************
+ * internal_release_locked_buffer
+ *
+ * The internal function for releasing a locked buffer.
+ * It assumes interrupts are turned off.
+ *
+ * m is minor number of device
+ *****************************************************/
+static inline void internal_release_locked_buffer( int m )
+{
+ /* Pointer into global structure for handling buffers */
+ if ( dt3155_fbuffer[ m ]->locked_buf >= 0 )
+ {
+ push_empty( dt3155_fbuffer[ m ]->locked_buf, m );
+ dt3155_fbuffer[ m ]->locked_buf = -1;
+ }
+}
+
+
+/*****************************************************
+ * dt3155_release_locked_buffer()
+ * m is minor # of device
+ *
+ * The user function of the above.
+ *
+ *****************************************************/
+inline void dt3155_release_locked_buffer( int m )
+{
+ unsigned long int flags;
+ local_save_flags(flags);
+ local_irq_disable();
+ internal_release_locked_buffer(m);
+ local_irq_restore(flags);
+}
+
+
+/*****************************************************
+ * dt3155_flush()
+ * m is minor # of device
+ *
+ *****************************************************/
+inline int dt3155_flush( int m )
+{
+ int index;
+ unsigned long int flags;
+ local_save_flags(flags);
+ local_irq_disable();
+
+ internal_release_locked_buffer( m );
+ dt3155_fbuffer[ m ]->empty_len = 0;
+
+ for ( index = 0; index < dt3155_fbuffer[ m ]->nbuffers; index++ )
+ push_empty( index, m );
+
+ /* Make sure there is an active buffer there. */
+ dt3155_fbuffer[ m ]->active_buf = pop_empty( m );
+
+ dt3155_fbuffer[ m ]->even_happened = 0;
+ dt3155_fbuffer[ m ]->even_stopped = 0;
+
+ /* setup the ready queue */
+ dt3155_fbuffer[ m ]->ready_head = 0;
+ dt3155_fbuffer[ m ]->ready_len = 0;
+
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+/*****************************************************
+ * dt3155_get_ready_buffer()
+ * m is minor # of device
+ *
+ * get_ready_buffer will grab the next chunk of data
+ * if it is already there, otherwise it returns 0.
+ * If the user has a buffer locked it will unlock
+ * that buffer before returning the new one.
+ *****************************************************/
+inline int dt3155_get_ready_buffer( int m )
+{
+ int frame_index;
+ unsigned long int flags;
+ local_save_flags(flags);
+ local_irq_disable();
+
+#ifdef DEBUG_QUES_A
+ printques( m );
+#endif
+
+ internal_release_locked_buffer( m );
+
+ if (is_ready_buf_empty( m ))
+ frame_index = -1;
+ else
+ {
+ frame_index = pop_ready( m );
+ dt3155_fbuffer[ m ]->locked_buf = frame_index;
+ }
+
+#ifdef DEBUG_QUES_B
+ printques( m );
+#endif
+
+ local_irq_restore(flags);
+
+ return frame_index;
+}
diff --git a/drivers/staging/dt3155/dt3155_isr.h b/drivers/staging/dt3155/dt3155_isr.h
new file mode 100644
index 00000000000..7595cb16c98
--- /dev/null
+++ b/drivers/staging/dt3155/dt3155_isr.h
@@ -0,0 +1,77 @@
+/*
+
+Copyright 1996,2002 Gregory D. Hager, Alfred A. Rizzi, Noah J. Cowan,
+ Jason Lapenta, Scott Smedley
+
+This file is part of the DT3155 Device Driver.
+
+The DT3155 Device 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.
+
+The DT3155 Device 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 the DT3155 Device Driver; if not, write to the Free
+Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+MA 02111-1307 USA
+
+
+-- Changes --
+
+ Date Programmer Description of changes made
+ -------------------------------------------------------------------
+ 03-Jul-2000 JML n/a
+ 24-Jul-2002 SS GPL licence.
+ 26-Oct-2009 SS Porting to 2.6.30 kernel.
+
+-- notes --
+
+*/
+
+#ifndef DT3155_ISR_H
+#define DT3155_ISR_H
+
+extern struct dt3155_fbuffer_s *dt3155_fbuffer[MAXBOARDS];
+
+/* User functions for buffering */
+/* Initialize the buffering system. This should */
+/* be called prior to enabling interrupts */
+
+u32 dt3155_setup_buffers(u32 *allocatorAddr);
+
+/* Get the next frame of data if it is ready. Returns */
+/* zero if no data is ready. If there is data but */
+/* the user has a locked buffer, it will unlock that */
+/* buffer and return it to the free list. */
+
+int dt3155_get_ready_buffer(int minor);
+
+/* Return a locked buffer to the free list */
+
+void dt3155_release_locked_buffer(int minor);
+
+/* Flush the buffer system */
+int dt3155_flush(int minor);
+
+/**********************************
+ * Simple array based que struct
+ **********************************/
+
+bool are_empty_buffers(int minor);
+void push_empty(int index, int minor);
+
+int pop_empty(int minor);
+
+bool is_ready_buf_empty(int minor);
+bool is_ready_buf_full(int minor);
+
+void push_ready(int minor, int index);
+int pop_ready(int minor);
+
+
+#endif
diff --git a/drivers/staging/et131x/et1310_address_map.h b/drivers/staging/et131x/et1310_address_map.h
index e715e4dcb52..ea746ba41fa 100644
--- a/drivers/staging/et131x/et1310_address_map.h
+++ b/drivers/staging/et131x/et1310_address_map.h
@@ -149,7 +149,7 @@
* GLOBAL Module of JAGCore Address Mapping
* Located at address 0x0000
*/
-typedef struct _GLOBAL_t { /* Location: */
+struct global_regs { /* Location: */
u32 txq_start_addr; /* 0x0000 */
u32 txq_end_addr; /* 0x0004 */
u32 rxq_start_addr; /* 0x0008 */
@@ -165,9 +165,7 @@ typedef struct _GLOBAL_t { /* Location: */
u32 msi_config; /* 0x0030 */
u32 loopback; /* 0x0034 */
u32 watchdog_timer; /* 0x0038 */
-} GLOBAL_t, *PGLOBAL_t;
-
-/* END OF GLOBAL REGISTER ADDRESS MAP */
+};
/* START OF TXDMA REGISTER ADDRESS MAP */
@@ -255,7 +253,7 @@ extern inline void add_12bit(u32 *v, int n)
* Tx DMA Module of JAGCore Address Mapping
* Located at address 0x1000
*/
-typedef struct _TXDMA_t { /* Location: */
+struct txdma_regs { /* Location: */
u32 csr; /* 0x1000 */
u32 pr_base_hi; /* 0x1004 */
u32 pr_base_lo; /* 0x1008 */
@@ -282,7 +280,7 @@ typedef struct _TXDMA_t { /* Location: */
u32 DroppedTLPCount; /* 0x105c */
u32 NewServiceComplete; /* 0x1060 */
u32 EthernetPacketCount; /* 0x1064 */
-} TXDMA_t, *PTXDMA_t;
+};
/* END OF TXDMA REGISTER ADDRESS MAP */
@@ -292,45 +290,25 @@ typedef struct _TXDMA_t { /* Location: */
/*
* structure for control status reg in rxdma address map
* Located at address 0x2000
+ *
+ * CSR
+ * 0: halt
+ * 1-3: tc
+ * 4: fbr_big_endian
+ * 5: psr_big_endian
+ * 6: pkt_big_endian
+ * 7: dma_big_endian
+ * 8-9: fbr0_size
+ * 10: fbr0_enable
+ * 11-12: fbr1_size
+ * 13: fbr1_enable
+ * 14: unused
+ * 15: pkt_drop_disable
+ * 16: pkt_done_flush
+ * 17: halt_status
+ * 18-31: unused
*/
-typedef union _RXDMA_CSR_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 unused2:14; /* bits 18-31 */
- u32 halt_status:1; /* bit 17 */
- u32 pkt_done_flush:1; /* bit 16 */
- u32 pkt_drop_disable:1; /* bit 15 */
- u32 unused1:1; /* bit 14 */
- u32 fbr1_enable:1; /* bit 13 */
- u32 fbr1_size:2; /* bits 11-12 */
- u32 fbr0_enable:1; /* bit 10 */
- u32 fbr0_size:2; /* bits 8-9 */
- u32 dma_big_endian:1; /* bit 7 */
- u32 pkt_big_endian:1; /* bit 6 */
- u32 psr_big_endian:1; /* bit 5 */
- u32 fbr_big_endian:1; /* bit 4 */
- u32 tc:3; /* bits 1-3 */
- u32 halt:1; /* bit 0 */
-#else
- u32 halt:1; /* bit 0 */
- u32 tc:3; /* bits 1-3 */
- u32 fbr_big_endian:1; /* bit 4 */
- u32 psr_big_endian:1; /* bit 5 */
- u32 pkt_big_endian:1; /* bit 6 */
- u32 dma_big_endian:1; /* bit 7 */
- u32 fbr0_size:2; /* bits 8-9 */
- u32 fbr0_enable:1; /* bit 10 */
- u32 fbr1_size:2; /* bits 11-12 */
- u32 fbr1_enable:1; /* bit 13 */
- u32 unused1:1; /* bit 14 */
- u32 pkt_drop_disable:1; /* bit 15 */
- u32 pkt_done_flush:1; /* bit 16 */
- u32 halt_status:1; /* bit 17 */
- u32 unused2:14; /* bits 18-31 */
-#endif
- } bits;
-} RXDMA_CSR_t, *PRXDMA_CSR_t;
+
/*
* structure for dma writeback lo reg in rxdma address map
@@ -451,18 +429,6 @@ typedef union _RXDMA_CSR_t {
* 31-10: unused
* 9-0: fbr ndesc
*/
-typedef union _RXDMA_FBR_NUM_DES_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 unused:22; /* bits 10-31 */
- u32 fbr_ndesc:10; /* bits 0-9 */
-#else
- u32 fbr_ndesc:10; /* bits 0-9 */
- u32 unused:22; /* bits 10-31 */
-#endif
- } bits;
-} RXDMA_FBR_NUM_DES_t, *PRXDMA_FBR_NUM_DES_t;
/*
* structure for free buffer ring 0 available offset reg in rxdma address map
@@ -532,8 +498,8 @@ typedef union _RXDMA_FBR_NUM_DES_t {
* Rx DMA Module of JAGCore Address Mapping
* Located at address 0x2000
*/
-typedef struct _RXDMA_t { /* Location: */
- RXDMA_CSR_t csr; /* 0x2000 */
+struct rxdma_regs { /* Location: */
+ u32 csr; /* 0x2000 */
u32 dma_wb_base_lo; /* 0x2004 */
u32 dma_wb_base_hi; /* 0x2008 */
u32 num_pkt_done; /* 0x200C */
@@ -562,7 +528,7 @@ typedef struct _RXDMA_t { /* Location: */
u32 fbr1_full_offset; /* 0x2068 */
u32 fbr1_rd_index; /* 0x206C */
u32 fbr1_min_des; /* 0x2070 */
-} RXDMA_t, *PRXDMA_t;
+};
/* END OF RXDMA REGISTER ADDRESS MAP */
@@ -572,33 +538,18 @@ typedef struct _RXDMA_t { /* Location: */
/*
* structure for control reg in txmac address map
* located at address 0x3000
+ *
+ * bits
+ * 31-8: unused
+ * 7: cklseg_disable
+ * 6: ckbcnt_disable
+ * 5: cksegnum
+ * 4: async_disable
+ * 3: fc_disable
+ * 2: mcif_disable
+ * 1: mif_disable
+ * 0: txmac_en
*/
-typedef union _TXMAC_CTL_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 unused:24; /* bits 8-31 */
- u32 cklseg_diable:1; /* bit 7 */
- u32 ckbcnt_disable:1; /* bit 6 */
- u32 cksegnum:1; /* bit 5 */
- u32 async_disable:1; /* bit 4 */
- u32 fc_disable:1; /* bit 3 */
- u32 mcif_disable:1; /* bit 2 */
- u32 mif_disable:1; /* bit 1 */
- u32 txmac_en:1; /* bit 0 */
-#else
- u32 txmac_en:1; /* bit 0 */
- u32 mif_disable:1; /* bit 1 mac interface */
- u32 mcif_disable:1; /* bit 2 mem. contr. interface */
- u32 fc_disable:1; /* bit 3 */
- u32 async_disable:1; /* bit 4 */
- u32 cksegnum:1; /* bit 5 */
- u32 ckbcnt_disable:1; /* bit 6 */
- u32 cklseg_diable:1; /* bit 7 */
- u32 unused:24; /* bits 8-31 */
-#endif
- } bits;
-} TXMAC_CTL_t, *PTXMAC_CTL_t;
/*
* structure for shadow pointer reg in txmac address map
@@ -612,23 +563,12 @@ typedef union _TXMAC_CTL_t {
/*
* structure for error count reg in txmac address map
* located at address 0x3008
+ *
+ * 31-12: unused
+ * 11-8: reserved
+ * 7-4: txq_underrun
+ * 3-0: fifo_underrun
*/
-typedef union _TXMAC_ERR_CNT_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 unused:20; /* bits 12-31 */
- u32 reserved:4; /* bits 8-11 */
- u32 txq_underrun:4; /* bits 4-7 */
- u32 fifo_underrun:4; /* bits 0-3 */
-#else
- u32 fifo_underrun:4; /* bits 0-3 */
- u32 txq_underrun:4; /* bits 4-7 */
- u32 reserved:4; /* bits 8-11 */
- u32 unused:20; /* bits 12-31 */
-#endif
- } bits;
-} TXMAC_ERR_CNT_t, *PTXMAC_ERR_CNT_t;
/*
* structure for max fill reg in txmac address map
@@ -657,64 +597,32 @@ typedef union _TXMAC_ERR_CNT_t {
/*
* structure for error reg in txmac address map
* located at address 0x3018
+ *
+ * 31-9: unused
+ * 8: fifo_underrun
+ * 7-6: unused
+ * 5: ctrl2_err
+ * 4: txq_underrun
+ * 3: bcnt_err
+ * 2: lseg_err
+ * 1: segnum_err
+ * 0: seg0_err
*/
-typedef union _TXMAC_ERR_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 unused2:23; /* bits 9-31 */
- u32 fifo_underrun:1; /* bit 8 */
- u32 unused1:2; /* bits 6-7 */
- u32 ctrl2_err:1; /* bit 5 */
- u32 txq_underrun:1; /* bit 4 */
- u32 bcnt_err:1; /* bit 3 */
- u32 lseg_err:1; /* bit 2 */
- u32 segnum_err:1; /* bit 1 */
- u32 seg0_err:1; /* bit 0 */
-#else
- u32 seg0_err:1; /* bit 0 */
- u32 segnum_err:1; /* bit 1 */
- u32 lseg_err:1; /* bit 2 */
- u32 bcnt_err:1; /* bit 3 */
- u32 txq_underrun:1; /* bit 4 */
- u32 ctrl2_err:1; /* bit 5 */
- u32 unused1:2; /* bits 6-7 */
- u32 fifo_underrun:1; /* bit 8 */
- u32 unused2:23; /* bits 9-31 */
-#endif
- } bits;
-} TXMAC_ERR_t, *PTXMAC_ERR_t;
/*
* structure for error interrupt reg in txmac address map
* located at address 0x301C
+ *
+ * 31-9: unused
+ * 8: fifo_underrun
+ * 7-6: unused
+ * 5: ctrl2_err
+ * 4: txq_underrun
+ * 3: bcnt_err
+ * 2: lseg_err
+ * 1: segnum_err
+ * 0: seg0_err
*/
-typedef union _TXMAC_ERR_INT_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 unused2:23; /* bits 9-31 */
- u32 fifo_underrun:1; /* bit 8 */
- u32 unused1:2; /* bits 6-7 */
- u32 ctrl2_err:1; /* bit 5 */
- u32 txq_underrun:1; /* bit 4 */
- u32 bcnt_err:1; /* bit 3 */
- u32 lseg_err:1; /* bit 2 */
- u32 segnum_err:1; /* bit 1 */
- u32 seg0_err:1; /* bit 0 */
-#else
- u32 seg0_err:1; /* bit 0 */
- u32 segnum_err:1; /* bit 1 */
- u32 lseg_err:1; /* bit 2 */
- u32 bcnt_err:1; /* bit 3 */
- u32 txq_underrun:1; /* bit 4 */
- u32 ctrl2_err:1; /* bit 5 */
- u32 unused1:2; /* bits 6-7 */
- u32 fifo_underrun:1; /* bit 8 */
- u32 unused2:23; /* bits 9-31 */
-#endif
- } bits;
-} TXMAC_ERR_INT_t, *PTXMAC_ERR_INT_t;
/*
* structure for error interrupt reg in txmac address map
@@ -728,17 +636,17 @@ typedef union _TXMAC_ERR_INT_t {
/*
* Tx MAC Module of JAGCore Address Mapping
*/
-typedef struct _TXMAC_t { /* Location: */
- TXMAC_CTL_t ctl; /* 0x3000 */
+struct txmac_regs { /* Location: */
+ u32 ctl; /* 0x3000 */
u32 shadow_ptr; /* 0x3004 */
- TXMAC_ERR_CNT_t err_cnt; /* 0x3008 */
+ u32 err_cnt; /* 0x3008 */
u32 max_fill; /* 0x300C */
u32 cf_param; /* 0x3010 */
u32 tx_test; /* 0x3014 */
- TXMAC_ERR_t err; /* 0x3018 */
- TXMAC_ERR_INT_t err_int; /* 0x301C */
+ u32 err; /* 0x3018 */
+ u32 err_int; /* 0x301C */
u32 bp_ctrl; /* 0x3020 */
-} TXMAC_t, *PTXMAC_t;
+};
/* END OF TXMAC REGISTER ADDRESS MAP */
@@ -747,106 +655,47 @@ typedef struct _TXMAC_t { /* Location: */
/*
* structure for rxmac control reg in rxmac address map
* located at address 0x4000
+ *
+ * 31-7: reserved
+ * 6: rxmac_int_disable
+ * 5: async_disable
+ * 4: mif_disable
+ * 3: wol_disable
+ * 2: pkt_filter_disable
+ * 1: mcif_disable
+ * 0: rxmac_en
*/
-typedef union _RXMAC_CTRL_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 reserved:25; /* bits 7-31 */
- u32 rxmac_int_disable:1; /* bit 6 */
- u32 async_disable:1; /* bit 5 */
- u32 mif_disable:1; /* bit 4 */
- u32 wol_disable:1; /* bit 3 */
- u32 pkt_filter_disable:1; /* bit 2 */
- u32 mcif_disable:1; /* bit 1 */
- u32 rxmac_en:1; /* bit 0 */
-#else
- u32 rxmac_en:1; /* bit 0 */
- u32 mcif_disable:1; /* bit 1 */
- u32 pkt_filter_disable:1; /* bit 2 */
- u32 wol_disable:1; /* bit 3 */
- u32 mif_disable:1; /* bit 4 */
- u32 async_disable:1; /* bit 5 */
- u32 rxmac_int_disable:1; /* bit 6 */
- u32 reserved:25; /* bits 7-31 */
-#endif
- } bits;
-} RXMAC_CTRL_t, *PRXMAC_CTRL_t;
/*
* structure for Wake On Lan Control and CRC 0 reg in rxmac address map
* located at address 0x4004
+ * 31-16: crc
+ * 15-12: reserved
+ * 11: ignore_pp
+ * 10: ignore_mp
+ * 9: clr_intr
+ * 8: ignore_link_chg
+ * 7: ignore_uni
+ * 6: ignore_multi
+ * 5: ignore_broad
+ * 4-0: valid_crc 4-0
*/
-typedef union _RXMAC_WOL_CTL_CRC0_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 crc0:16; /* bits 16-31 */
- u32 reserve:4; /* bits 12-15 */
- u32 ignore_pp:1; /* bit 11 */
- u32 ignore_mp:1; /* bit 10 */
- u32 clr_intr:1; /* bit 9 */
- u32 ignore_link_chg:1; /* bit 8 */
- u32 ignore_uni:1; /* bit 7 */
- u32 ignore_multi:1; /* bit 6 */
- u32 ignore_broad:1; /* bit 5 */
- u32 valid_crc4:1; /* bit 4 */
- u32 valid_crc3:1; /* bit 3 */
- u32 valid_crc2:1; /* bit 2 */
- u32 valid_crc1:1; /* bit 1 */
- u32 valid_crc0:1; /* bit 0 */
-#else
- u32 valid_crc0:1; /* bit 0 */
- u32 valid_crc1:1; /* bit 1 */
- u32 valid_crc2:1; /* bit 2 */
- u32 valid_crc3:1; /* bit 3 */
- u32 valid_crc4:1; /* bit 4 */
- u32 ignore_broad:1; /* bit 5 */
- u32 ignore_multi:1; /* bit 6 */
- u32 ignore_uni:1; /* bit 7 */
- u32 ignore_link_chg:1; /* bit 8 */
- u32 clr_intr:1; /* bit 9 */
- u32 ignore_mp:1; /* bit 10 */
- u32 ignore_pp:1; /* bit 11 */
- u32 reserve:4; /* bits 12-15 */
- u32 crc0:16; /* bits 16-31 */
-#endif
- } bits;
-} RXMAC_WOL_CTL_CRC0_t, *PRXMAC_WOL_CTL_CRC0_t;
/*
* structure for CRC 1 and CRC 2 reg in rxmac address map
* located at address 0x4008
+ *
+ * 31-16: crc2
+ * 15-0: crc1
*/
-typedef union _RXMAC_WOL_CRC12_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 crc2:16; /* bits 16-31 */
- u32 crc1:16; /* bits 0-15 */
-#else
- u32 crc1:16; /* bits 0-15 */
- u32 crc2:16; /* bits 16-31 */
-#endif
- } bits;
-} RXMAC_WOL_CRC12_t, *PRXMAC_WOL_CRC12_t;
/*
* structure for CRC 3 and CRC 4 reg in rxmac address map
* located at address 0x400C
+ *
+ * 31-16: crc4
+ * 15-0: crc3
*/
-typedef union _RXMAC_WOL_CRC34_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 crc4:16; /* bits 16-31 */
- u32 crc3:16; /* bits 0-15 */
-#else
- u32 crc3:16; /* bits 0-15 */
- u32 crc4:16; /* bits 16-31 */
-#endif
- } bits;
-} RXMAC_WOL_CRC34_t, *PRXMAC_WOL_CRC34_t;
/*
* structure for Wake On Lan Source Address Lo reg in rxmac address map
@@ -966,164 +815,84 @@ typedef union _RXMAC_UNI_PF_ADDR3_t {
/*
* structure for Packet Filter Control reg in rxmac address map
* located at address 0x4084
+ *
+ * 31-23: unused
+ * 22-16: min_pkt_size
+ * 15-4: unused
+ * 3: filter_frag_en
+ * 2: filter_uni_en
+ * 1: filter_multi_en
+ * 0: filter_broad_en
*/
-typedef union _RXMAC_PF_CTRL_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 unused2:9; /* bits 23-31 */
- u32 min_pkt_size:7; /* bits 16-22 */
- u32 unused1:12; /* bits 4-15 */
- u32 filter_frag_en:1; /* bit 3 */
- u32 filter_uni_en:1; /* bit 2 */
- u32 filter_multi_en:1; /* bit 1 */
- u32 filter_broad_en:1; /* bit 0 */
-#else
- u32 filter_broad_en:1; /* bit 0 */
- u32 filter_multi_en:1; /* bit 1 */
- u32 filter_uni_en:1; /* bit 2 */
- u32 filter_frag_en:1; /* bit 3 */
- u32 unused1:12; /* bits 4-15 */
- u32 min_pkt_size:7; /* bits 16-22 */
- u32 unused2:9; /* bits 23-31 */
-#endif
- } bits;
-} RXMAC_PF_CTRL_t, *PRXMAC_PF_CTRL_t;
/*
* structure for Memory Controller Interface Control Max Segment reg in rxmac
* address map. Located at address 0x4088
+ *
+ * 31-10: reserved
+ * 9-2: max_size
+ * 1: fc_en
+ * 0: seg_en
*/
-typedef union _RXMAC_MCIF_CTRL_MAX_SEG_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 reserved:22; /* bits 10-31 */
- u32 max_size:8; /* bits 2-9 */
- u32 fc_en:1; /* bit 1 */
- u32 seg_en:1; /* bit 0 */
-#else
- u32 seg_en:1; /* bit 0 */
- u32 fc_en:1; /* bit 1 */
- u32 max_size:8; /* bits 2-9 */
- u32 reserved:22; /* bits 10-31 */
-#endif
- } bits;
-} RXMAC_MCIF_CTRL_MAX_SEG_t, *PRXMAC_MCIF_CTRL_MAX_SEG_t;
/*
* structure for Memory Controller Interface Water Mark reg in rxmac address
* map. Located at address 0x408C
+ *
+ * 31-26: unused
+ * 25-16: mark_hi
+ * 15-10: unused
+ * 9-0: mark_lo
*/
-typedef union _RXMAC_MCIF_WATER_MARK_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 reserved2:6; /* bits 26-31 */
- u32 mark_hi:10; /* bits 16-25 */
- u32 reserved1:6; /* bits 10-15 */
- u32 mark_lo:10; /* bits 0-9 */
-#else
- u32 mark_lo:10; /* bits 0-9 */
- u32 reserved1:6; /* bits 10-15 */
- u32 mark_hi:10; /* bits 16-25 */
- u32 reserved2:6; /* bits 26-31 */
-#endif
- } bits;
-} RXMAC_MCIF_WATER_MARK_t, *PRXMAC_MCIF_WATER_MARK_t;
/*
* structure for Rx Queue Dialog reg in rxmac address map.
* located at address 0x4090
+ *
+ * 31-26: reserved
+ * 25-16: rd_ptr
+ * 15-10: reserved
+ * 9-0: wr_ptr
*/
-typedef union _RXMAC_RXQ_DIAG_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 reserved2:6; /* bits 26-31 */
- u32 rd_ptr:10; /* bits 16-25 */
- u32 reserved1:6; /* bits 10-15 */
- u32 wr_ptr:10; /* bits 0-9 */
-#else
- u32 wr_ptr:10; /* bits 0-9 */
- u32 reserved1:6; /* bits 10-15 */
- u32 rd_ptr:10; /* bits 16-25 */
- u32 reserved2:6; /* bits 26-31 */
-#endif
- } bits;
-} RXMAC_RXQ_DIAG_t, *PRXMAC_RXQ_DIAG_t;
/*
* structure for space availiable reg in rxmac address map.
* located at address 0x4094
+ *
+ * 31-17: reserved
+ * 16: space_avail_en
+ * 15-10: reserved
+ * 9-0: space_avail
*/
-typedef union _RXMAC_SPACE_AVAIL_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 reserved2:15; /* bits 17-31 */
- u32 space_avail_en:1; /* bit 16 */
- u32 reserved1:6; /* bits 10-15 */
- u32 space_avail:10; /* bits 0-9 */
-#else
- u32 space_avail:10; /* bits 0-9 */
- u32 reserved1:6; /* bits 10-15 */
- u32 space_avail_en:1; /* bit 16 */
- u32 reserved2:15; /* bits 17-31 */
-#endif
- } bits;
-} RXMAC_SPACE_AVAIL_t, *PRXMAC_SPACE_AVAIL_t;
/*
* structure for management interface reg in rxmac address map.
* located at address 0x4098
+ *
+ * 31-18: reserved
+ * 17: drop_pkt_en
+ * 16-0: drop_pkt_mask
*/
-typedef union _RXMAC_MIF_CTL_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 reserve:14; /* bits 18-31 */
- u32 drop_pkt_en:1; /* bit 17 */
- u32 drop_pkt_mask:17; /* bits 0-16 */
-#else
- u32 drop_pkt_mask:17; /* bits 0-16 */
- u32 drop_pkt_en:1; /* bit 17 */
- u32 reserve:14; /* bits 18-31 */
-#endif
- } bits;
-} RXMAC_MIF_CTL_t, *PRXMAC_MIF_CTL_t;
/*
* structure for Error reg in rxmac address map.
* located at address 0x409C
+ *
+ * 31-4: unused
+ * 3: mif
+ * 2: async
+ * 1: pkt_filter
+ * 0: mcif
*/
-typedef union _RXMAC_ERROR_REG_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 reserve:28; /* bits 4-31 */
- u32 mif:1; /* bit 3 */
- u32 async:1; /* bit 2 */
- u32 pkt_filter:1; /* bit 1 */
- u32 mcif:1; /* bit 0 */
-#else
- u32 mcif:1; /* bit 0 */
- u32 pkt_filter:1; /* bit 1 */
- u32 async:1; /* bit 2 */
- u32 mif:1; /* bit 3 */
- u32 reserve:28; /* bits 4-31 */
-#endif
- } bits;
-} RXMAC_ERROR_REG_t, *PRXMAC_ERROR_REG_t;
/*
* Rx MAC Module of JAGCore Address Mapping
*/
typedef struct _RXMAC_t { /* Location: */
- RXMAC_CTRL_t ctrl; /* 0x4000 */
- RXMAC_WOL_CTL_CRC0_t crc0; /* 0x4004 */
- RXMAC_WOL_CRC12_t crc12; /* 0x4008 */
- RXMAC_WOL_CRC34_t crc34; /* 0x400C */
+ u32 ctrl; /* 0x4000 */
+ u32 crc0; /* 0x4004 */
+ u32 crc12; /* 0x4008 */
+ u32 crc34; /* 0x400C */
RXMAC_WOL_SA_LO_t sa_lo; /* 0x4010 */
RXMAC_WOL_SA_HI_t sa_hi; /* 0x4014 */
u32 mask0_word0; /* 0x4018 */
@@ -1153,17 +922,17 @@ typedef struct _RXMAC_t { /* Location: */
u32 multi_hash2; /* 0x4078 */
u32 multi_hash3; /* 0x407C */
u32 multi_hash4; /* 0x4080 */
- RXMAC_PF_CTRL_t pf_ctrl; /* 0x4084 */
- RXMAC_MCIF_CTRL_MAX_SEG_t mcif_ctrl_max_seg; /* 0x4088 */
- RXMAC_MCIF_WATER_MARK_t mcif_water_mark; /* 0x408C */
- RXMAC_RXQ_DIAG_t rxq_diag; /* 0x4090 */
- RXMAC_SPACE_AVAIL_t space_avail; /* 0x4094 */
-
- RXMAC_MIF_CTL_t mif_ctrl; /* 0x4098 */
- RXMAC_ERROR_REG_t err_reg; /* 0x409C */
+ u32 pf_ctrl; /* 0x4084 */
+ u32 mcif_ctrl_max_seg; /* 0x4088 */
+ u32 mcif_water_mark; /* 0x408C */
+ u32 rxq_diag; /* 0x4090 */
+ u32 space_avail; /* 0x4094 */
+
+ u32 mif_ctrl; /* 0x4098 */
+ u32 err_reg; /* 0x409C */
} RXMAC_t, *PRXMAC_t;
-/* END OF TXMAC REGISTER ADDRESS MAP */
+/* END OF RXMAC REGISTER ADDRESS MAP */
/* START OF MAC REGISTER ADDRESS MAP */
@@ -1337,37 +1106,19 @@ typedef struct _RXMAC_t { /* Location: */
/*
* structure for Interface Status reg in mac address map.
* located at address 0x503C
+ *
+ * 31-10: reserved
+ * 9: excess_defer
+ * 8: clash
+ * 7: phy_jabber
+ * 6: phy_link_ok
+ * 5: phy_full_duplex
+ * 4: phy_speed
+ * 3: pe100x_link_fail
+ * 2: pe10t_loss_carrier
+ * 1: pe10t_sqe_error
+ * 0: pe10t_jabber
*/
-typedef union _MAC_IF_STAT_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 reserved:22; /* bits 10-31 */
- u32 excess_defer:1; /* bit 9 */
- u32 clash:1; /* bit 8 */
- u32 phy_jabber:1; /* bit 7 */
- u32 phy_link_ok:1; /* bit 6 */
- u32 phy_full_duplex:1; /* bit 5 */
- u32 phy_speed:1; /* bit 4 */
- u32 pe100x_link_fail:1; /* bit 3 */
- u32 pe10t_loss_carrie:1; /* bit 2 */
- u32 pe10t_sqe_error:1; /* bit 1 */
- u32 pe10t_jabber:1; /* bit 0 */
-#else
- u32 pe10t_jabber:1; /* bit 0 */
- u32 pe10t_sqe_error:1; /* bit 1 */
- u32 pe10t_loss_carrie:1; /* bit 2 */
- u32 pe100x_link_fail:1; /* bit 3 */
- u32 phy_speed:1; /* bit 4 */
- u32 phy_full_duplex:1; /* bit 5 */
- u32 phy_link_ok:1; /* bit 6 */
- u32 phy_jabber:1; /* bit 7 */
- u32 clash:1; /* bit 8 */
- u32 excess_defer:1; /* bit 9 */
- u32 reserved:22; /* bits 10-31 */
-#endif
- } bits;
-} MAC_IF_STAT_t, *PMAC_IF_STAT_t;
/*
* structure for Mac Station Address, Part 1 reg in mac address map.
@@ -1428,7 +1179,7 @@ typedef struct _MAC_t { /* Location: */
u32 mii_mgmt_stat; /* 0x5030 */
u32 mii_mgmt_indicator; /* 0x5034 */
u32 if_ctrl; /* 0x5038 */
- MAC_IF_STAT_t if_stat; /* 0x503C */
+ u32 if_stat; /* 0x503C */
MAC_STATION_ADDR1_t station_addr_1; /* 0x5040 */
MAC_STATION_ADDR2_t station_addr_2; /* 0x5044 */
} MAC_t, *PMAC_t;
@@ -1498,8 +1249,9 @@ typedef struct _MAC_t { /* Location: */
/*
* MAC STATS Module of JAGCore Address Mapping
*/
-typedef struct _MAC_STAT_t { /* Location: */
- u32 pad[32]; /* 0x6000 - 607C */
+struct macstat_regs
+{ /* Location: */
+ u32 pad[32]; /* 0x6000 - 607C */
/* Tx/Rx 0-64 Byte Frame Counter */
u32 TR64; /* 0x6080 */
@@ -1644,7 +1396,7 @@ typedef struct _MAC_STAT_t { /* Location: */
/* Carry Register Two Mask Register */
u32 Carry2M; /* 0x613C */
-} MAC_STAT_t, *PMAC_STAT_t;
+};
/* END OF MAC STAT REGISTER ADDRESS MAP */
@@ -1682,70 +1434,49 @@ typedef struct _MAC_STAT_t { /* Location: */
/*
* Memory Control Module of JAGCore Address Mapping
*/
-typedef struct _MMC_t { /* Location: */
+struct mmc_regs { /* Location: */
u32 mmc_ctrl; /* 0x7000 */
u32 sram_access; /* 0x7004 */
u32 sram_word1; /* 0x7008 */
u32 sram_word2; /* 0x700C */
u32 sram_word3; /* 0x7010 */
u32 sram_word4; /* 0x7014 */
-} MMC_t, *PMMC_t;
+};
/* END OF MMC REGISTER ADDRESS MAP */
-/* START OF EXP ROM REGISTER ADDRESS MAP */
-
-/*
- * Expansion ROM Module of JAGCore Address Mapping
- */
-
-/* Take this out until it is not empty */
-#if 0
-typedef struct _EXP_ROM_t {
-
-} EXP_ROM_t, *PEXP_ROM_t;
-#endif
-
-/* END OF EXP ROM REGISTER ADDRESS MAP */
-
-
/*
* JAGCore Address Mapping
*/
typedef struct _ADDRESS_MAP_t {
- GLOBAL_t global;
+ struct global_regs global;
/* unused section of global address map */
- u8 unused_global[4096 - sizeof(GLOBAL_t)];
- TXDMA_t txdma;
+ u8 unused_global[4096 - sizeof(struct global_regs)];
+ struct txdma_regs txdma;
/* unused section of txdma address map */
- u8 unused_txdma[4096 - sizeof(TXDMA_t)];
- RXDMA_t rxdma;
+ u8 unused_txdma[4096 - sizeof(struct txdma_regs)];
+ struct rxdma_regs rxdma;
/* unused section of rxdma address map */
- u8 unused_rxdma[4096 - sizeof(RXDMA_t)];
- TXMAC_t txmac;
+ u8 unused_rxdma[4096 - sizeof(struct rxdma_regs)];
+ struct txmac_regs txmac;
/* unused section of txmac address map */
- u8 unused_txmac[4096 - sizeof(TXMAC_t)];
+ u8 unused_txmac[4096 - sizeof(struct txmac_regs)];
RXMAC_t rxmac;
/* unused section of rxmac address map */
u8 unused_rxmac[4096 - sizeof(RXMAC_t)];
MAC_t mac;
/* unused section of mac address map */
u8 unused_mac[4096 - sizeof(MAC_t)];
- MAC_STAT_t macStat;
+ struct macstat_regs macstat;
/* unused section of mac stat address map */
- u8 unused_mac_stat[4096 - sizeof(MAC_STAT_t)];
- MMC_t mmc;
+ u8 unused_mac_stat[4096 - sizeof(struct macstat_regs)];
+ struct mmc_regs mmc;
/* unused section of mmc address map */
- u8 unused_mmc[4096 - sizeof(MMC_t)];
+ u8 unused_mmc[4096 - sizeof(struct mmc_regs)];
/* unused section of address map */
u8 unused_[1015808];
-/* Take this out until it is not empty */
-#if 0
- EXP_ROM_t exp_rom;
-#endif
-
u8 unused_exp_rom[4096]; /* MGS-size TBD */
u8 unused__[524288]; /* unused section of address map */
} ADDRESS_MAP_t, *PADDRESS_MAP_t;
diff --git a/drivers/staging/et131x/et1310_eeprom.c b/drivers/staging/et131x/et1310_eeprom.c
index bcca1f86f51..3ca253672ba 100644
--- a/drivers/staging/et131x/et1310_eeprom.c
+++ b/drivers/staging/et131x/et1310_eeprom.c
@@ -84,17 +84,42 @@
#include <linux/ioport.h>
#include "et1310_phy.h"
-#include "et1310_pm.h"
-#include "et1310_jagcore.h"
-#include "et1310_eeprom.h"
-
#include "et131x_adapter.h"
-#include "et131x_initpci.h"
-#include "et131x_isr.h"
-
-#include "et1310_tx.h"
+#include "et131x.h"
+/*
+ * EEPROM Defines
+ */
+/* LBCIF Register Groups (addressed via 32-bit offsets) */
+#define LBCIF_DWORD0_GROUP 0xAC
+#define LBCIF_DWORD1_GROUP 0xB0
+
+/* LBCIF Registers (addressed via 8-bit offsets) */
+#define LBCIF_ADDRESS_REGISTER 0xAC
+#define LBCIF_DATA_REGISTER 0xB0
+#define LBCIF_CONTROL_REGISTER 0xB1
+#define LBCIF_STATUS_REGISTER 0xB2
+
+/* LBCIF Control Register Bits */
+#define LBCIF_CONTROL_SEQUENTIAL_READ 0x01
+#define LBCIF_CONTROL_PAGE_WRITE 0x02
+#define LBCIF_CONTROL_EEPROM_RELOAD 0x08
+#define LBCIF_CONTROL_TWO_BYTE_ADDR 0x20
+#define LBCIF_CONTROL_I2C_WRITE 0x40
+#define LBCIF_CONTROL_LBCIF_ENABLE 0x80
+
+/* LBCIF Status Register Bits */
+#define LBCIF_STATUS_PHY_QUEUE_AVAIL 0x01
+#define LBCIF_STATUS_I2C_IDLE 0x02
+#define LBCIF_STATUS_ACK_ERROR 0x04
+#define LBCIF_STATUS_GENERAL_ERROR 0x08
+#define LBCIF_STATUS_CHECKSUM_ERROR 0x40
+#define LBCIF_STATUS_EEPROM_PRESENT 0x80
+
+/* Miscellaneous Constraints */
+#define MAX_NUM_REGISTER_POLLS 1000
+#define MAX_NUM_WRITE_RETRIES 2
static int eeprom_wait_ready(struct pci_dev *pdev, u32 *status)
{
diff --git a/drivers/staging/et131x/et1310_eeprom.h b/drivers/staging/et131x/et1310_eeprom.h
deleted file mode 100644
index 6a6c6a632a8..00000000000
--- a/drivers/staging/et131x/et1310_eeprom.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Agere Systems Inc.
- * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- * http://www.agere.com
- *
- *------------------------------------------------------------------------------
- *
- * et1310_eeprom.h - Defines, structs, enums, prototypes, etc. used for EEPROM
- * access routines
- *
- *------------------------------------------------------------------------------
- *
- * SOFTWARE LICENSE
- *
- * This software is provided subject to the following terms and conditions,
- * which you should read carefully before using the software. Using this
- * software indicates your acceptance of these terms and conditions. If you do
- * not agree with these terms and conditions, do not use the software.
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source or binary forms, with or without
- * modifications, are permitted provided that the following conditions are met:
- *
- * . Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following Disclaimer as comments in the code as
- * well as in the documentation and/or other materials provided with the
- * distribution.
- *
- * . Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following Disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * . Neither the name of Agere Systems Inc. nor the names of the contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * Disclaimer
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
- * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
- * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- */
-
-#ifndef __ET1310_EEPROM_H__
-#define __ET1310_EEPROM_H__
-
-#include "et1310_address_map.h"
-
-/*
- * EEPROM Defines
- */
-
-/* LBCIF Register Groups (addressed via 32-bit offsets) */
-#define LBCIF_DWORD0_GROUP 0xAC
-#define LBCIF_DWORD1_GROUP 0xB0
-
-/* LBCIF Registers (addressed via 8-bit offsets) */
-#define LBCIF_ADDRESS_REGISTER 0xAC
-#define LBCIF_DATA_REGISTER 0xB0
-#define LBCIF_CONTROL_REGISTER 0xB1
-#define LBCIF_STATUS_REGISTER 0xB2
-
-/* LBCIF Control Register Bits */
-#define LBCIF_CONTROL_SEQUENTIAL_READ 0x01
-#define LBCIF_CONTROL_PAGE_WRITE 0x02
-#define LBCIF_CONTROL_EEPROM_RELOAD 0x08
-#define LBCIF_CONTROL_TWO_BYTE_ADDR 0x20
-#define LBCIF_CONTROL_I2C_WRITE 0x40
-#define LBCIF_CONTROL_LBCIF_ENABLE 0x80
-
-/* LBCIF Status Register Bits */
-#define LBCIF_STATUS_PHY_QUEUE_AVAIL 0x01
-#define LBCIF_STATUS_I2C_IDLE 0x02
-#define LBCIF_STATUS_ACK_ERROR 0x04
-#define LBCIF_STATUS_GENERAL_ERROR 0x08
-#define LBCIF_STATUS_CHECKSUM_ERROR 0x40
-#define LBCIF_STATUS_EEPROM_PRESENT 0x80
-
-/* Miscellaneous Constraints */
-#define MAX_NUM_REGISTER_POLLS 1000
-#define MAX_NUM_WRITE_RETRIES 2
-
-/* Forward declaration of the private adapter structure */
-struct et131x_adapter;
-
-int et131x_init_eeprom(struct et131x_adapter *etdev);
-
-#endif /* _ET1310_EEPROM_H_ */
diff --git a/drivers/staging/et131x/et1310_jagcore.h b/drivers/staging/et131x/et1310_jagcore.h
deleted file mode 100644
index 0807a01d88a..00000000000
--- a/drivers/staging/et131x/et1310_jagcore.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Agere Systems Inc.
- * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- * http://www.agere.com
- *
- *------------------------------------------------------------------------------
- *
- * et1310_jagcore.h - Defines, structs, enums, prototypes, etc. pertaining to
- * the JAGCore
- *
- *------------------------------------------------------------------------------
- *
- * SOFTWARE LICENSE
- *
- * This software is provided subject to the following terms and conditions,
- * which you should read carefully before using the software. Using this
- * software indicates your acceptance of these terms and conditions. If you do
- * not agree with these terms and conditions, do not use the software.
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source or binary forms, with or without
- * modifications, are permitted provided that the following conditions are met:
- *
- * . Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following Disclaimer as comments in the code as
- * well as in the documentation and/or other materials provided with the
- * distribution.
- *
- * . Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following Disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * . Neither the name of Agere Systems Inc. nor the names of the contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * Disclaimer
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
- * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
- * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- */
-
-#ifndef __ET1310_JAGCORE_H__
-#define __ET1310_JAGCORE_H__
-
-#include "et1310_address_map.h"
-
-
-#define INTERNAL_MEM_SIZE 0x400 /* 1024 of internal memory */
-#define INTERNAL_MEM_RX_OFFSET 0x1FF /* 50% Tx, 50% Rx */
-
-/*
- * For interrupts, normal running is:
- * rxdma_xfr_done, phy_interrupt, mac_stat_interrupt,
- * watchdog_interrupt & txdma_xfer_done
- *
- * In both cases, when flow control is enabled for either Tx or bi-direction,
- * we additional enable rx_fbr0_low and rx_fbr1_low, so we know when the
- * buffer rings are running low.
- */
-#define INT_MASK_DISABLE 0xffffffff
-
-/* NOTE: Masking out MAC_STAT Interrupt for now...
- * #define INT_MASK_ENABLE 0xfff6bf17
- * #define INT_MASK_ENABLE_NO_FLOW 0xfff6bfd7
- */
-#define INT_MASK_ENABLE 0xfffebf17
-#define INT_MASK_ENABLE_NO_FLOW 0xfffebfd7
-
-/* Forward declaration of the private adapter structure */
-struct et131x_adapter;
-
-void ConfigGlobalRegs(struct et131x_adapter *pAdapter);
-void ConfigMMCRegs(struct et131x_adapter *pAdapter);
-void et131x_enable_interrupts(struct et131x_adapter *adapter);
-void et131x_disable_interrupts(struct et131x_adapter *adapter);
-
-#endif /* __ET1310_JAGCORE_H__ */
diff --git a/drivers/staging/et131x/et1310_mac.c b/drivers/staging/et131x/et1310_mac.c
index b8a1f203731..a292b1edc41 100644
--- a/drivers/staging/et131x/et1310_mac.c
+++ b/drivers/staging/et131x/et1310_mac.c
@@ -85,12 +85,19 @@
#include <linux/crc32.h>
#include "et1310_phy.h"
-#include "et1310_pm.h"
-#include "et1310_jagcore.h"
-#include "et1310_mac.h"
-
#include "et131x_adapter.h"
-#include "et131x_initpci.h"
+#include "et131x.h"
+
+
+#define COUNTER_WRAP_28_BIT 0x10000000
+#define COUNTER_WRAP_22_BIT 0x400000
+#define COUNTER_WRAP_16_BIT 0x10000
+#define COUNTER_WRAP_12_BIT 0x1000
+
+#define COUNTER_MASK_28_BIT (COUNTER_WRAP_28_BIT - 1)
+#define COUNTER_MASK_22_BIT (COUNTER_WRAP_22_BIT - 1)
+#define COUNTER_MASK_16_BIT (COUNTER_WRAP_16_BIT - 1)
+#define COUNTER_MASK_12_BIT (COUNTER_WRAP_12_BIT - 1)
/**
* ConfigMacRegs1 - Initialize the first part of MAC regs
@@ -163,9 +170,9 @@ void ConfigMACRegs2(struct et131x_adapter *etdev)
u32 cfg1;
u32 cfg2;
u32 ifctrl;
- TXMAC_CTL_t ctl;
+ u32 ctl;
- ctl.value = readl(&etdev->regs->txmac.ctl.value);
+ ctl = readl(&etdev->regs->txmac.ctl);
cfg1 = readl(&pMac->cfg1);
cfg2 = readl(&pMac->cfg2);
ifctrl = readl(&pMac->if_ctrl);
@@ -219,9 +226,8 @@ void ConfigMACRegs2(struct et131x_adapter *etdev)
}
/* Enable TXMAC */
- ctl.bits.txmac_en = 0x1;
- ctl.bits.fc_disable = 0x1;
- writel(ctl.value, &etdev->regs->txmac.ctl.value);
+ ctl |= 0x05; /* TX mac enable, FC disable */
+ writel(ctl, &etdev->regs->txmac.ctl);
/* Ready to start the RXDMA/TXDMA engine */
if (etdev->Flags & fMP_ADAPTER_LOWER_POWER) {
@@ -235,15 +241,15 @@ void ConfigRxMacRegs(struct et131x_adapter *etdev)
struct _RXMAC_t __iomem *pRxMac = &etdev->regs->rxmac;
RXMAC_WOL_SA_LO_t sa_lo;
RXMAC_WOL_SA_HI_t sa_hi;
- RXMAC_PF_CTRL_t pf_ctrl = { 0 };
+ u32 pf_ctrl = 0;
/* Disable the MAC while it is being configured (also disable WOL) */
- writel(0x8, &pRxMac->ctrl.value);
+ writel(0x8, &pRxMac->ctrl);
/* Initialize WOL to disabled. */
- writel(0, &pRxMac->crc0.value);
- writel(0, &pRxMac->crc12.value);
- writel(0, &pRxMac->crc34.value);
+ writel(0, &pRxMac->crc0);
+ writel(0, &pRxMac->crc12);
+ writel(0, &pRxMac->crc34);
/* We need to set the WOL mask0 - mask4 next. We initialize it to
* its default Values of 0x00000000 because there are not WOL masks
@@ -286,12 +292,12 @@ void ConfigRxMacRegs(struct et131x_adapter *etdev)
writel(sa_hi.value, &pRxMac->sa_hi.value);
/* Disable all Packet Filtering */
- writel(0, &pRxMac->pf_ctrl.value);
+ writel(0, &pRxMac->pf_ctrl);
/* Let's initialize the Unicast Packet filtering address */
if (etdev->PacketFilter & ET131X_PACKET_TYPE_DIRECTED) {
SetupDeviceForUnicast(etdev);
- pf_ctrl.bits.filter_uni_en = 1;
+ pf_ctrl |= 4; /* Unicast filter */
} else {
writel(0, &pRxMac->uni_pf_addr1.value);
writel(0, &pRxMac->uni_pf_addr2.value);
@@ -299,20 +305,16 @@ void ConfigRxMacRegs(struct et131x_adapter *etdev)
}
/* Let's initialize the Multicast hash */
- if (etdev->PacketFilter & ET131X_PACKET_TYPE_ALL_MULTICAST) {
- pf_ctrl.bits.filter_multi_en = 0;
- } else {
- pf_ctrl.bits.filter_multi_en = 1;
+ if (!(etdev->PacketFilter & ET131X_PACKET_TYPE_ALL_MULTICAST)) {
+ pf_ctrl |= 2; /* Multicast filter */
SetupDeviceForMulticast(etdev);
}
/* Runt packet filtering. Didn't work in version A silicon. */
- pf_ctrl.bits.min_pkt_size = NIC_MIN_PACKET_SIZE + 4;
- pf_ctrl.bits.filter_frag_en = 1;
-
- if (etdev->RegistryJumboPacket > 8192) {
- RXMAC_MCIF_CTRL_MAX_SEG_t mcif_ctrl_max_seg;
+ pf_ctrl |= (NIC_MIN_PACKET_SIZE + 4) << 16;
+ pf_ctrl |= 8; /* Fragment filter */
+ if (etdev->RegistryJumboPacket > 8192)
/* In order to transmit jumbo packets greater than 8k, the
* FIFO between RxMAC and RxDMA needs to be reduced in size
* to (16k - Jumbo packet size). In order to implement this,
@@ -320,25 +322,21 @@ void ConfigRxMacRegs(struct et131x_adapter *etdev)
* packets down into segments which are (max_size * 16). In
* this case we selected 256 bytes, since this is the size of
* the PCI-Express TLP's that the 1310 uses.
+ *
+ * seg_en on, fc_en off, size 0x10
*/
- mcif_ctrl_max_seg.bits.seg_en = 0x1;
- mcif_ctrl_max_seg.bits.fc_en = 0x0;
- mcif_ctrl_max_seg.bits.max_size = 0x10;
-
- writel(mcif_ctrl_max_seg.value,
- &pRxMac->mcif_ctrl_max_seg.value);
- } else {
- writel(0, &pRxMac->mcif_ctrl_max_seg.value);
- }
+ writel(0x41, &pRxMac->mcif_ctrl_max_seg);
+ else
+ writel(0, &pRxMac->mcif_ctrl_max_seg);
/* Initialize the MCIF water marks */
- writel(0, &pRxMac->mcif_water_mark.value);
+ writel(0, &pRxMac->mcif_water_mark);
/* Initialize the MIF control */
- writel(0, &pRxMac->mif_ctrl.value);
+ writel(0, &pRxMac->mif_ctrl);
/* Initialize the Space Available Register */
- writel(0, &pRxMac->space_avail.value);
+ writel(0, &pRxMac->space_avail);
/* Initialize the the mif_ctrl register
* bit 3: Receive code error. One or more nibbles were signaled as
@@ -354,9 +352,9 @@ void ConfigRxMacRegs(struct et131x_adapter *etdev)
* bit 17: Drop packet enable
*/
if (etdev->linkspeed == TRUEPHY_SPEED_100MBPS)
- writel(0x30038, &pRxMac->mif_ctrl.value);
+ writel(0x30038, &pRxMac->mif_ctrl);
else
- writel(0x30030, &pRxMac->mif_ctrl.value);
+ writel(0x30030, &pRxMac->mif_ctrl);
/* Finally we initialize RxMac to be enabled & WOL disabled. Packet
* filter is always enabled since it is where the runt packets are
@@ -364,28 +362,28 @@ void ConfigRxMacRegs(struct et131x_adapter *etdev)
* dropping doesn't work, so it is disabled in the pf_ctrl register,
* but we still leave the packet filter on.
*/
- writel(pf_ctrl.value, &pRxMac->pf_ctrl.value);
- writel(0x9, &pRxMac->ctrl.value);
+ writel(pf_ctrl, &pRxMac->pf_ctrl);
+ writel(0x9, &pRxMac->ctrl);
}
void ConfigTxMacRegs(struct et131x_adapter *etdev)
{
- struct _TXMAC_t __iomem *pTxMac = &etdev->regs->txmac;
+ struct txmac_regs *txmac = &etdev->regs->txmac;
/* We need to update the Control Frame Parameters
* cfpt - control frame pause timer set to 64 (0x40)
* cfep - control frame extended pause timer set to 0x0
*/
if (etdev->FlowControl == None)
- writel(0, &pTxMac->cf_param);
+ writel(0, &txmac->cf_param);
else
- writel(0x40, &pTxMac->cf_param);
+ writel(0x40, &txmac->cf_param);
}
void ConfigMacStatRegs(struct et131x_adapter *etdev)
{
- struct _MAC_STAT_t __iomem *macstat =
- &etdev->regs->macStat;
+ struct macstat_regs __iomem *macstat =
+ &etdev->regs->macstat;
/* Next we need to initialize all the MAC_STAT registers to zero on
* the device.
@@ -456,8 +454,8 @@ void ConfigFlowControl(struct et131x_adapter *etdev)
void UpdateMacStatHostCounters(struct et131x_adapter *etdev)
{
struct _ce_stats_t *stats = &etdev->Stats;
- struct _MAC_STAT_t __iomem *macstat =
- &etdev->regs->macStat;
+ struct macstat_regs __iomem *macstat =
+ &etdev->regs->macstat;
stats->collisions += readl(&macstat->TNcl);
stats->first_collision += readl(&macstat->TScl);
@@ -493,11 +491,11 @@ void HandleMacStatInterrupt(struct et131x_adapter *etdev)
/* Read the interrupt bits from the register(s). These are Clear On
* Write.
*/
- Carry1 = readl(&etdev->regs->macStat.Carry1);
- Carry2 = readl(&etdev->regs->macStat.Carry2);
+ Carry1 = readl(&etdev->regs->macstat.Carry1);
+ Carry2 = readl(&etdev->regs->macstat.Carry2);
- writel(Carry1, &etdev->regs->macStat.Carry1);
- writel(Carry2, &etdev->regs->macStat.Carry2);
+ writel(Carry1, &etdev->regs->macstat.Carry1);
+ writel(Carry2, &etdev->regs->macstat.Carry2);
/* We need to do update the host copy of all the MAC_STAT counters.
* For each counter, check it's overflow bit. If the overflow bit is
diff --git a/drivers/staging/et131x/et1310_mac.h b/drivers/staging/et131x/et1310_mac.h
deleted file mode 100644
index 2c385959453..00000000000
--- a/drivers/staging/et131x/et1310_mac.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Agere Systems Inc.
- * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- * http://www.agere.com
- *
- *------------------------------------------------------------------------------
- *
- * et1310_mac.h - Defines, structs, enums, prototypes, etc. pertaining to the
- * MAC.
- *
- *------------------------------------------------------------------------------
- *
- * SOFTWARE LICENSE
- *
- * This software is provided subject to the following terms and conditions,
- * which you should read carefully before using the software. Using this
- * software indicates your acceptance of these terms and conditions. If you do
- * not agree with these terms and conditions, do not use the software.
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source or binary forms, with or without
- * modifications, are permitted provided that the following conditions are met:
- *
- * . Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following Disclaimer as comments in the code as
- * well as in the documentation and/or other materials provided with the
- * distribution.
- *
- * . Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following Disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * . Neither the name of Agere Systems Inc. nor the names of the contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * Disclaimer
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
- * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
- * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- */
-
-#ifndef _ET1310_MAC_H_
-#define _ET1310_MAC_H_
-
-
-#include "et1310_address_map.h"
-
-
-#define COUNTER_WRAP_28_BIT 0x10000000
-#define COUNTER_WRAP_22_BIT 0x400000
-#define COUNTER_WRAP_16_BIT 0x10000
-#define COUNTER_WRAP_12_BIT 0x1000
-
-#define COUNTER_MASK_28_BIT (COUNTER_WRAP_28_BIT - 1)
-#define COUNTER_MASK_22_BIT (COUNTER_WRAP_22_BIT - 1)
-#define COUNTER_MASK_16_BIT (COUNTER_WRAP_16_BIT - 1)
-#define COUNTER_MASK_12_BIT (COUNTER_WRAP_12_BIT - 1)
-
-#define UPDATE_COUNTER(HostCnt, DevCnt) \
- HostCnt = HostCnt + DevCnt;
-
-/* Forward declaration of the private adapter structure */
-struct et131x_adapter;
-
-void ConfigMACRegs1(struct et131x_adapter *adapter);
-void ConfigMACRegs2(struct et131x_adapter *adapter);
-void ConfigRxMacRegs(struct et131x_adapter *adapter);
-void ConfigTxMacRegs(struct et131x_adapter *adapter);
-void ConfigMacStatRegs(struct et131x_adapter *adapter);
-void ConfigFlowControl(struct et131x_adapter *adapter);
-void UpdateMacStatHostCounters(struct et131x_adapter *adapter);
-void HandleMacStatInterrupt(struct et131x_adapter *adapter);
-void SetupDeviceForMulticast(struct et131x_adapter *adapter);
-void SetupDeviceForUnicast(struct et131x_adapter *adapter);
-
-#endif /* _ET1310_MAC_H_ */
diff --git a/drivers/staging/et131x/et1310_phy.c b/drivers/staging/et131x/et1310_phy.c
index 6ecad619f77..4a55fbfbd59 100644
--- a/drivers/staging/et131x/et1310_phy.c
+++ b/drivers/staging/et131x/et1310_phy.c
@@ -85,17 +85,14 @@
#include <linux/random.h>
#include "et1310_phy.h"
-#include "et1310_pm.h"
-#include "et1310_jagcore.h"
#include "et131x_adapter.h"
-#include "et131x_netdev.h"
-#include "et131x_initpci.h"
#include "et1310_address_map.h"
#include "et1310_tx.h"
#include "et1310_rx.h"
-#include "et1310_mac.h"
+
+#include "et131x.h"
/* Prototypes for functions with local scope */
static void et131x_xcvr_init(struct et131x_adapter *etdev);
diff --git a/drivers/staging/et131x/et1310_phy.h b/drivers/staging/et131x/et1310_phy.h
index 758b9b25171..47907ba7601 100644
--- a/drivers/staging/et131x/et1310_phy.h
+++ b/drivers/staging/et131x/et1310_phy.h
@@ -736,32 +736,8 @@ typedef union _MI_LCR2_t {
/* MI Register 29 - 31: Reserved Reg(0x1D - 0x1E) */
-/* Forward declaration of the private adapter structure */
-struct et131x_adapter;
/* Prototypes for ET1310_phy.c */
-int et131x_xcvr_find(struct et131x_adapter *adapter);
-void et131x_setphy_normal(struct et131x_adapter *adapter);
-
-/* static inline function does not work because et131x_adapter is not always
- * defined
- */
-int PhyMiRead(struct et131x_adapter *adapter, u8 xcvrAddr,
- u8 xcvrReg, u16 *value);
-#define MiRead(adapter, xcvrReg, value) \
- PhyMiRead((adapter), (adapter)->Stats.xcvr_addr, (xcvrReg), (value))
-
-int32_t MiWrite(struct et131x_adapter *adapter,
- u8 xcvReg, u16 value);
-void et131x_Mii_check(struct et131x_adapter *pAdapter,
- MI_BMSR_t bmsr, MI_BMSR_t bmsr_ints);
-
-/* This last is not strictly required (the driver could call the TPAL
- * version instead), but this sets the adapter up correctly, and calls the
- * access routine indirectly. This protects the driver from changes in TPAL.
- */
-void SetPhy_10BaseTHalfDuplex(struct et131x_adapter *adapter);
-
/* Defines for PHY access routines */
/* Define bit operation flags */
@@ -843,14 +819,4 @@ void SetPhy_10BaseTHalfDuplex(struct et131x_adapter *adapter);
/* #define TRU_VMI_LINK_CONTROL_REGISTER 29 */
/* #define TRU_VMI_TIMING_CONTROL_REGISTER */
-/* Prototypes for PHY access routines */
-void ET1310_PhyInit(struct et131x_adapter *adapter);
-void ET1310_PhyReset(struct et131x_adapter *adapter);
-void ET1310_PhyPowerDown(struct et131x_adapter *adapter, bool down);
-void ET1310_PhyAdvertise1000BaseT(struct et131x_adapter *adapter,
- u16 duplex);
-void ET1310_PhyAccessMiBit(struct et131x_adapter *adapter,
- u16 action,
- u16 regnum, u16 bitnum, u8 *value);
-
#endif /* _ET1310_PHY_H_ */
diff --git a/drivers/staging/et131x/et1310_pm.c b/drivers/staging/et131x/et1310_pm.c
index 7d077235929..41019e390af 100644
--- a/drivers/staging/et131x/et1310_pm.c
+++ b/drivers/staging/et131x/et1310_pm.c
@@ -83,13 +83,9 @@
#include <linux/ioport.h>
#include "et1310_phy.h"
-#include "et1310_pm.h"
-#include "et1310_jagcore.h"
-#include "et1310_mac.h"
#include "et1310_rx.h"
-
#include "et131x_adapter.h"
-#include "et131x_initpci.h"
+#include "et131x.h"
/**
* EnablePhyComa - called when network cable is unplugged
diff --git a/drivers/staging/et131x/et1310_pm.h b/drivers/staging/et131x/et1310_pm.h
deleted file mode 100644
index 295f3ab132f..00000000000
--- a/drivers/staging/et131x/et1310_pm.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Agere Systems Inc.
- * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- * http://www.agere.com
- *
- *------------------------------------------------------------------------------
- *
- * et1310_pm.h - Defines, structs, enums, prototypes, etc. pertaining to power
- * management.
- *
- *------------------------------------------------------------------------------
- *
- * SOFTWARE LICENSE
- *
- * This software is provided subject to the following terms and conditions,
- * which you should read carefully before using the software. Using this
- * software indicates your acceptance of these terms and conditions. If you do
- * not agree with these terms and conditions, do not use the software.
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source or binary forms, with or without
- * modifications, are permitted provided that the following conditions are met:
- *
- * . Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following Disclaimer as comments in the code as
- * well as in the documentation and/or other materials provided with the
- * distribution.
- *
- * . Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following Disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * . Neither the name of Agere Systems Inc. nor the names of the contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * Disclaimer
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
- * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
- * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- */
-
-#ifndef _ET1310_PM_H_
-#define _ET1310_PM_H_
-
-#include "et1310_address_map.h"
-
-typedef struct _MP_POWER_MGMT {
- /* variable putting the phy into coma mode when boot up with no cable
- * plugged in after 5 seconds
- */
- u8 TransPhyComaModeOnBoot;
-
- /* Next two used to save power information at power down. This
- * information will be used during power up to set up parts of Power
- * Management in JAGCore
- */
- u16 PowerDownSpeed;
- u8 PowerDownDuplex;
-} MP_POWER_MGMT, *PMP_POWER_MGMT;
-
-/* Forward declaration of the private adapter structure
- */
-struct et131x_adapter;
-
-void EnablePhyComa(struct et131x_adapter *adapter);
-void DisablePhyComa(struct et131x_adapter *adapter);
-
-#endif /* _ET1310_PM_H_ */
diff --git a/drivers/staging/et131x/et1310_rx.c b/drivers/staging/et131x/et1310_rx.c
index 81c1a7478ad..54686e2ace6 100644
--- a/drivers/staging/et131x/et1310_rx.c
+++ b/drivers/staging/et131x/et1310_rx.c
@@ -84,14 +84,9 @@
#include <linux/ioport.h>
#include "et1310_phy.h"
-#include "et1310_pm.h"
-#include "et1310_jagcore.h"
-
#include "et131x_adapter.h"
-#include "et131x_initpci.h"
-
#include "et1310_rx.h"
-
+#include "et131x.h"
void nic_return_rfd(struct et131x_adapter *etdev, PMP_RFD pMpRfd);
@@ -109,17 +104,16 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
u32 i, j;
u32 bufsize;
u32 pktStatRingSize, FBRChunkSize;
- RX_RING_t *rx_ring;
+ struct rx_ring *rx_ring;
/* Setup some convenience pointers */
- rx_ring = (RX_RING_t *) &adapter->RxRing;
+ rx_ring = &adapter->rx_ring;
/* Alloc memory for the lookup table */
#ifdef USE_FBR0
- rx_ring->Fbr[0] = kmalloc(sizeof(FBRLOOKUPTABLE), GFP_KERNEL);
+ rx_ring->fbr[0] = kmalloc(sizeof(struct fbr_lookup), GFP_KERNEL);
#endif
-
- rx_ring->Fbr[1] = kmalloc(sizeof(FBRLOOKUPTABLE), GFP_KERNEL);
+ rx_ring->fbr[1] = kmalloc(sizeof(struct fbr_lookup), GFP_KERNEL);
/* The first thing we will do is configure the sizes of the buffer
* rings. These will change based on jumbo packet support. Larger
@@ -163,14 +157,14 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
}
#ifdef USE_FBR0
- adapter->RxRing.PsrNumEntries = adapter->RxRing.Fbr0NumEntries +
- adapter->RxRing.Fbr1NumEntries;
+ adapter->rx_ring.PsrNumEntries = adapter->rx_ring.Fbr0NumEntries +
+ adapter->rx_ring.Fbr1NumEntries;
#else
- adapter->RxRing.PsrNumEntries = adapter->RxRing.Fbr1NumEntries;
+ adapter->rx_ring.PsrNumEntries = adapter->rx_ring.Fbr1NumEntries;
#endif
/* Allocate an area of memory for Free Buffer Ring 1 */
- bufsize = (sizeof(FBR_DESC_t) * rx_ring->Fbr1NumEntries) + 0xfff;
+ bufsize = (sizeof(struct fbr_desc) * rx_ring->Fbr1NumEntries) + 0xfff;
rx_ring->pFbr1RingVa = pci_alloc_consistent(adapter->pdev,
bufsize,
&rx_ring->pFbr1RingPa);
@@ -194,12 +188,12 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
&rx_ring->Fbr1Realpa,
&rx_ring->Fbr1offset, 0x0FFF);
- rx_ring->pFbr1RingVa = (void *)((uint8_t *) rx_ring->pFbr1RingVa +
+ rx_ring->pFbr1RingVa = (void *)((u8 *) rx_ring->pFbr1RingVa +
rx_ring->Fbr1offset);
#ifdef USE_FBR0
/* Allocate an area of memory for Free Buffer Ring 0 */
- bufsize = (sizeof(FBR_DESC_t) * rx_ring->Fbr0NumEntries) + 0xfff;
+ bufsize = (sizeof(struct fbr_desc) * rx_ring->Fbr0NumEntries) + 0xfff;
rx_ring->pFbr0RingVa = pci_alloc_consistent(adapter->pdev,
bufsize,
&rx_ring->pFbr0RingPa);
@@ -223,7 +217,7 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
&rx_ring->Fbr0Realpa,
&rx_ring->Fbr0offset, 0x0FFF);
- rx_ring->pFbr0RingVa = (void *)((uint8_t *) rx_ring->pFbr0RingVa +
+ rx_ring->pFbr0RingVa = (void *)((u8 *) rx_ring->pFbr0RingVa +
rx_ring->Fbr0offset);
#endif
@@ -270,23 +264,23 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
/* Save the Virtual address of this index for quick
* access later
*/
- rx_ring->Fbr[1]->Va[index] =
- (uint8_t *) rx_ring->Fbr1MemVa[i] +
+ rx_ring->fbr[1]->virt[index] =
+ (u8 *) rx_ring->Fbr1MemVa[i] +
(j * rx_ring->Fbr1BufferSize) + Fbr1Offset;
/* now store the physical address in the descriptor
* so the device can access it
*/
- rx_ring->Fbr[1]->PAHigh[index] =
+ rx_ring->fbr[1]->bus_high[index] =
(u32) (Fbr1TempPa >> 32);
- rx_ring->Fbr[1]->PALow[index] = (u32) Fbr1TempPa;
+ rx_ring->fbr[1]->bus_low[index] = (u32) Fbr1TempPa;
Fbr1TempPa += rx_ring->Fbr1BufferSize;
- rx_ring->Fbr[1]->Buffer1[index] =
- rx_ring->Fbr[1]->Va[index];
- rx_ring->Fbr[1]->Buffer2[index] =
- rx_ring->Fbr[1]->Va[index] - 4;
+ rx_ring->fbr[1]->buffer1[index] =
+ rx_ring->fbr[1]->virt[index];
+ rx_ring->fbr[1]->buffer2[index] =
+ rx_ring->fbr[1]->virt[index] - 4;
}
}
@@ -319,27 +313,27 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
for (j = 0; j < FBR_CHUNKS; j++) {
u32 index = (i * FBR_CHUNKS) + j;
- rx_ring->Fbr[0]->Va[index] =
- (uint8_t *) rx_ring->Fbr0MemVa[i] +
+ rx_ring->fbr[0]->virt[index] =
+ (u8 *) rx_ring->Fbr0MemVa[i] +
(j * rx_ring->Fbr0BufferSize) + Fbr0Offset;
- rx_ring->Fbr[0]->PAHigh[index] =
+ rx_ring->fbr[0]->bus_high[index] =
(u32) (Fbr0TempPa >> 32);
- rx_ring->Fbr[0]->PALow[index] = (u32) Fbr0TempPa;
+ rx_ring->fbr[0]->bus_low[index] = (u32) Fbr0TempPa;
Fbr0TempPa += rx_ring->Fbr0BufferSize;
- rx_ring->Fbr[0]->Buffer1[index] =
- rx_ring->Fbr[0]->Va[index];
- rx_ring->Fbr[0]->Buffer2[index] =
- rx_ring->Fbr[0]->Va[index] - 4;
+ rx_ring->fbr[0]->buffer1[index] =
+ rx_ring->fbr[0]->virt[index];
+ rx_ring->fbr[0]->buffer2[index] =
+ rx_ring->fbr[0]->virt[index] - 4;
}
}
#endif
/* Allocate an area of memory for FIFO of Packet Status ring entries */
pktStatRingSize =
- sizeof(PKT_STAT_DESC_t) * adapter->RxRing.PsrNumEntries;
+ sizeof(struct pkt_stat_desc) * adapter->rx_ring.PsrNumEntries;
rx_ring->pPSRingVa = pci_alloc_consistent(adapter->pdev,
pktStatRingSize,
@@ -360,16 +354,16 @@ int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter)
*/
/* Allocate an area of memory for writeback of status information */
- rx_ring->pRxStatusVa = pci_alloc_consistent(adapter->pdev,
- sizeof(RX_STATUS_BLOCK_t),
- &rx_ring->pRxStatusPa);
- if (!rx_ring->pRxStatusVa) {
+ rx_ring->rx_status_block = pci_alloc_consistent(adapter->pdev,
+ sizeof(struct rx_status_block),
+ &rx_ring->rx_status_bus);
+ if (!rx_ring->rx_status_block) {
dev_err(&adapter->pdev->dev,
"Cannot alloc memory for Status Block\n");
return -ENOMEM;
}
rx_ring->NumRfd = NIC_DEFAULT_NUM_RFD;
- printk("PRS %lx\n", (unsigned long)rx_ring->pRxStatusPa);
+ printk("PRS %lx\n", (unsigned long)rx_ring->rx_status_bus);
/* Recv
* pci_pool_create initializes a lookaside list. After successful
@@ -403,10 +397,10 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
u32 bufsize;
u32 pktStatRingSize;
PMP_RFD rfd;
- RX_RING_t *rx_ring;
+ struct rx_ring *rx_ring;
/* Setup some convenience pointers */
- rx_ring = (RX_RING_t *) &adapter->RxRing;
+ rx_ring = &adapter->rx_ring;
/* Free RFDs and associated packet descriptors */
WARN_ON(rx_ring->nReadyRecv != rx_ring->NumRfd);
@@ -417,7 +411,7 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
list_del(&rfd->list_node);
rfd->Packet = NULL;
- kmem_cache_free(adapter->RxRing.RecvLookaside, rfd);
+ kmem_cache_free(adapter->rx_ring.RecvLookaside, rfd);
}
/* Free Free Buffer Ring 1 */
@@ -447,15 +441,14 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
}
/* Now the FIFO itself */
- rx_ring->pFbr1RingVa = (void *)((uint8_t *)
+ rx_ring->pFbr1RingVa = (void *)((u8 *)
rx_ring->pFbr1RingVa - rx_ring->Fbr1offset);
- bufsize =
- (sizeof(FBR_DESC_t) * rx_ring->Fbr1NumEntries) + 0xfff;
+ bufsize = (sizeof(struct fbr_desc) * rx_ring->Fbr1NumEntries)
+ + 0xfff;
- pci_free_consistent(adapter->pdev,
- bufsize,
- rx_ring->pFbr1RingVa, rx_ring->pFbr1RingPa);
+ pci_free_consistent(adapter->pdev, bufsize,
+ rx_ring->pFbr1RingVa, rx_ring->pFbr1RingPa);
rx_ring->pFbr1RingVa = NULL;
}
@@ -481,11 +474,11 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
}
/* Now the FIFO itself */
- rx_ring->pFbr0RingVa = (void *)((uint8_t *)
+ rx_ring->pFbr0RingVa = (void *)((u8 *)
rx_ring->pFbr0RingVa - rx_ring->Fbr0offset);
- bufsize =
- (sizeof(FBR_DESC_t) * rx_ring->Fbr0NumEntries) + 0xfff;
+ bufsize = (sizeof(struct fbr_desc) * rx_ring->Fbr0NumEntries)
+ + 0xfff;
pci_free_consistent(adapter->pdev,
bufsize,
@@ -498,7 +491,7 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
/* Free Packet Status Ring */
if (rx_ring->pPSRingVa) {
pktStatRingSize =
- sizeof(PKT_STAT_DESC_t) * adapter->RxRing.PsrNumEntries;
+ sizeof(struct pkt_stat_desc) * adapter->rx_ring.PsrNumEntries;
pci_free_consistent(adapter->pdev, pktStatRingSize,
rx_ring->pPSRingVa, rx_ring->pPSRingPa);
@@ -507,12 +500,11 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
}
/* Free area of memory for the writeback of status information */
- if (rx_ring->pRxStatusVa) {
+ if (rx_ring->rx_status_block) {
pci_free_consistent(adapter->pdev,
- sizeof(RX_STATUS_BLOCK_t),
- rx_ring->pRxStatusVa, rx_ring->pRxStatusPa);
-
- rx_ring->pRxStatusVa = NULL;
+ sizeof(struct rx_status_block),
+ rx_ring->rx_status_block, rx_ring->rx_status_bus);
+ rx_ring->rx_status_block = NULL;
}
/* Free receive buffer pool */
@@ -527,10 +519,10 @@ void et131x_rx_dma_memory_free(struct et131x_adapter *adapter)
/* Free the FBR Lookup Table */
#ifdef USE_FBR0
- kfree(rx_ring->Fbr[0]);
+ kfree(rx_ring->fbr[0]);
#endif
- kfree(rx_ring->Fbr[1]);
+ kfree(rx_ring->fbr[1]);
/* Reset Counters */
rx_ring->nReadyRecv = 0;
@@ -548,10 +540,10 @@ int et131x_init_recv(struct et131x_adapter *adapter)
PMP_RFD rfd = NULL;
u32 rfdct;
u32 numrfd = 0;
- RX_RING_t *rx_ring = NULL;
+ struct rx_ring *rx_ring;
/* Setup some convenience pointers */
- rx_ring = (RX_RING_t *) &adapter->RxRing;
+ rx_ring = &adapter->rx_ring;
/* Setup each RFD */
for (rfdct = 0; rfdct < rx_ring->NumRfd; rfdct++) {
@@ -594,9 +586,9 @@ int et131x_init_recv(struct et131x_adapter *adapter)
*/
void ConfigRxDmaRegs(struct et131x_adapter *etdev)
{
- struct _RXDMA_t __iomem *rx_dma = &etdev->regs->rxdma;
- struct _rx_ring_t *rx_local = &etdev->RxRing;
- PFBR_DESC_t fbr_entry;
+ struct rxdma_regs __iomem *rx_dma = &etdev->regs->rxdma;
+ struct rx_ring *rx_local = &etdev->rx_ring;
+ struct fbr_desc *fbr_entry;
u32 entry;
u32 psr_num_des;
unsigned long flags;
@@ -611,11 +603,11 @@ void ConfigRxDmaRegs(struct et131x_adapter *etdev)
* are ever returned, make sure the high part is retrieved here
* before storing the adjusted address.
*/
- writel((u32) ((u64)rx_local->pRxStatusPa >> 32),
+ writel((u32) ((u64)rx_local->rx_status_bus >> 32),
&rx_dma->dma_wb_base_hi);
- writel((u32) rx_local->pRxStatusPa, &rx_dma->dma_wb_base_lo);
+ writel((u32) rx_local->rx_status_bus, &rx_dma->dma_wb_base_lo);
- memset(rx_local->pRxStatusVa, 0, sizeof(RX_STATUS_BLOCK_t));
+ memset(rx_local->rx_status_block, 0, sizeof(struct rx_status_block));
/* Set the address and parameters of the packet status ring into the
* 1310's registers
@@ -636,11 +628,11 @@ void ConfigRxDmaRegs(struct et131x_adapter *etdev)
rx_local->local_psr_full = 0;
/* Now's the best time to initialize FBR1 contents */
- fbr_entry = (PFBR_DESC_t) rx_local->pFbr1RingVa;
+ fbr_entry = (struct fbr_desc *) rx_local->pFbr1RingVa;
for (entry = 0; entry < rx_local->Fbr1NumEntries; entry++) {
- fbr_entry->addr_hi = rx_local->Fbr[1]->PAHigh[entry];
- fbr_entry->addr_lo = rx_local->Fbr[1]->PALow[entry];
- fbr_entry->word2.bits.bi = entry;
+ fbr_entry->addr_hi = rx_local->fbr[1]->bus_high[entry];
+ fbr_entry->addr_lo = rx_local->fbr[1]->bus_low[entry];
+ fbr_entry->word2 = entry;
fbr_entry++;
}
@@ -661,11 +653,11 @@ void ConfigRxDmaRegs(struct et131x_adapter *etdev)
#ifdef USE_FBR0
/* Now's the best time to initialize FBR0 contents */
- fbr_entry = (PFBR_DESC_t) rx_local->pFbr0RingVa;
+ fbr_entry = (struct fbr_desc *) rx_local->pFbr0RingVa;
for (entry = 0; entry < rx_local->Fbr0NumEntries; entry++) {
- fbr_entry->addr_hi = rx_local->Fbr[0]->PAHigh[entry];
- fbr_entry->addr_lo = rx_local->Fbr[0]->PALow[entry];
- fbr_entry->word2.bits.bi = entry;
+ fbr_entry->addr_hi = rx_local->fbr[0]->bus_high[entry];
+ fbr_entry->addr_lo = rx_local->fbr[0]->bus_low[entry];
+ fbr_entry->word2 = entry;
fbr_entry++;
}
@@ -721,18 +713,17 @@ void SetRxDmaTimer(struct et131x_adapter *etdev)
*/
void et131x_rx_dma_disable(struct et131x_adapter *etdev)
{
- RXDMA_CSR_t csr;
-
+ u32 csr;
/* Setup the receive dma configuration register */
- writel(0x00002001, &etdev->regs->rxdma.csr.value);
- csr.value = readl(&etdev->regs->rxdma.csr.value);
- if (csr.bits.halt_status != 1) {
+ writel(0x00002001, &etdev->regs->rxdma.csr);
+ csr = readl(&etdev->regs->rxdma.csr);
+ if ((csr & 0x00020000) != 1) { /* Check halt status (bit 17) */
udelay(5);
- csr.value = readl(&etdev->regs->rxdma.csr.value);
- if (csr.bits.halt_status != 1)
+ csr = readl(&etdev->regs->rxdma.csr);
+ if ((csr & 0x00020000) != 1)
dev_err(&etdev->pdev->dev,
- "RX Dma failed to enter halt state. CSR 0x%08x\n",
- csr.value);
+ "RX Dma failed to enter halt state. CSR 0x%08x\n",
+ csr);
}
}
@@ -743,34 +734,33 @@ void et131x_rx_dma_disable(struct et131x_adapter *etdev)
void et131x_rx_dma_enable(struct et131x_adapter *etdev)
{
/* Setup the receive dma configuration register for normal operation */
- RXDMA_CSR_t csr = { 0 };
-
- csr.bits.fbr1_enable = 1;
- if (etdev->RxRing.Fbr1BufferSize == 4096)
- csr.bits.fbr1_size = 1;
- else if (etdev->RxRing.Fbr1BufferSize == 8192)
- csr.bits.fbr1_size = 2;
- else if (etdev->RxRing.Fbr1BufferSize == 16384)
- csr.bits.fbr1_size = 3;
+ u32 csr = 0x2000; /* FBR1 enable */
+
+ if (etdev->rx_ring.Fbr1BufferSize == 4096)
+ csr |= 0x0800;
+ else if (etdev->rx_ring.Fbr1BufferSize == 8192)
+ csr |= 0x1000;
+ else if (etdev->rx_ring.Fbr1BufferSize == 16384)
+ csr |= 0x1800;
#ifdef USE_FBR0
- csr.bits.fbr0_enable = 1;
- if (etdev->RxRing.Fbr0BufferSize == 256)
- csr.bits.fbr0_size = 1;
- else if (etdev->RxRing.Fbr0BufferSize == 512)
- csr.bits.fbr0_size = 2;
- else if (etdev->RxRing.Fbr0BufferSize == 1024)
- csr.bits.fbr0_size = 3;
+ csr |= 0x0400; /* FBR0 enable */
+ if (etdev->rx_ring.Fbr0BufferSize == 256)
+ csr |= 0x0100;
+ else if (etdev->rx_ring.Fbr0BufferSize == 512)
+ csr |= 0x0200;
+ else if (etdev->rx_ring.Fbr0BufferSize == 1024)
+ csr |= 0x0300;
#endif
- writel(csr.value, &etdev->regs->rxdma.csr.value);
+ writel(csr, &etdev->regs->rxdma.csr);
- csr.value = readl(&etdev->regs->rxdma.csr.value);
- if (csr.bits.halt_status != 0) {
+ csr = readl(&etdev->regs->rxdma.csr);
+ if ((csr & 0x00020000) != 0) {
udelay(5);
- csr.value = readl(&etdev->regs->rxdma.csr.value);
- if (csr.bits.halt_status != 0) {
+ csr = readl(&etdev->regs->rxdma.csr);
+ if ((csr & 0x00020000) != 0) {
dev_err(&etdev->pdev->dev,
"RX Dma failed to exit halt state. CSR 0x%08x\n",
- csr.value);
+ csr);
}
}
}
@@ -788,46 +778,44 @@ void et131x_rx_dma_enable(struct et131x_adapter *etdev)
*/
PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev)
{
- struct _rx_ring_t *rx_local = &etdev->RxRing;
- PRX_STATUS_BLOCK_t status;
- PPKT_STAT_DESC_t psr;
+ struct rx_ring *rx_local = &etdev->rx_ring;
+ struct rx_status_block *status;
+ struct pkt_stat_desc *psr;
PMP_RFD rfd;
u32 i;
- uint8_t *buf;
+ u8 *buf;
unsigned long flags;
struct list_head *element;
- uint8_t rindex;
- uint16_t bindex;
+ u8 rindex;
+ u16 bindex;
u32 len;
- PKT_STAT_DESC_WORD0_t Word0;
+ u32 word0;
+ u32 word1;
/* RX Status block is written by the DMA engine prior to every
* interrupt. It contains the next to be used entry in the Packet
* Status Ring, and also the two Free Buffer rings.
*/
- status = (PRX_STATUS_BLOCK_t) rx_local->pRxStatusVa;
+ status = rx_local->rx_status_block;
+ word1 = status->Word1 >> 16; /* Get the useful bits */
- /* FIXME: tidy later when conversions complete */
- if (status->Word1.bits.PSRoffset ==
- (rx_local->local_psr_full & 0xFFF) &&
- status->Word1.bits.PSRwrap ==
- ((rx_local->local_psr_full >> 12) & 1)) {
+ /* Check the PSR and wrap bits do not match */
+ if ((word1 & 0x1FFF) == (rx_local->local_psr_full & 0x1FFF))
/* Looks like this ring is not updated yet */
return NULL;
- }
/* The packet status ring indicates that data is available. */
- psr = (PPKT_STAT_DESC_t) (rx_local->pPSRingVa) +
+ psr = (struct pkt_stat_desc *) (rx_local->pPSRingVa) +
(rx_local->local_psr_full & 0xFFF);
/* Grab any information that is required once the PSR is
* advanced, since we can no longer rely on the memory being
* accurate
*/
- len = psr->word1.bits.length;
- rindex = (uint8_t) psr->word1.bits.ri;
- bindex = (uint16_t) psr->word1.bits.bi;
- Word0 = psr->word0;
+ len = psr->word1 & 0xFFFF;
+ rindex = (psr->word1 >> 26) & 0x03;
+ bindex = (psr->word1 >> 16) & 0x3FF;
+ word0 = psr->word0;
/* Indicate that we have used this PSR entry. */
/* FIXME wrap 12 */
@@ -842,9 +830,8 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev)
&etdev->regs->rxdma.psr_full_offset);
#ifndef USE_FBR0
- if (rindex != 1) {
+ if (rindex != 1)
return NULL;
- }
#endif
#ifdef USE_FBR0
@@ -899,7 +886,7 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev)
if (len) {
if (etdev->ReplicaPhyLoopbk == 1) {
- buf = rx_local->Fbr[rindex]->Va[bindex];
+ buf = rx_local->fbr[rindex]->virt[bindex];
if (memcmp(&buf[6], &etdev->CurrentAddress[0],
ETH_ALEN) == 0) {
@@ -911,8 +898,8 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev)
}
/* Determine if this is a multicast packet coming in */
- if ((Word0.value & ALCATEL_MULTICAST_PKT) &&
- !(Word0.value & ALCATEL_BROADCAST_PKT)) {
+ if ((word0 & ALCATEL_MULTICAST_PKT) &&
+ !(word0 & ALCATEL_BROADCAST_PKT)) {
/* Promiscuous mode and Multicast mode are
* not mutually exclusive as was first
* thought. I guess Promiscuous is just
@@ -923,8 +910,8 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev)
if ((etdev->PacketFilter & ET131X_PACKET_TYPE_MULTICAST)
&& !(etdev->PacketFilter & ET131X_PACKET_TYPE_PROMISCUOUS)
&& !(etdev->PacketFilter & ET131X_PACKET_TYPE_ALL_MULTICAST)) {
- buf = rx_local->Fbr[rindex]->
- Va[bindex];
+ buf = rx_local->fbr[rindex]->
+ virt[bindex];
/* Loop through our list to see if the
* destination address of this packet
@@ -963,7 +950,7 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev)
if (len > 0)
etdev->Stats.multircv++;
- } else if (Word0.value & ALCATEL_BROADCAST_PKT)
+ } else if (word0 & ALCATEL_BROADCAST_PKT)
etdev->Stats.brdcstrcv++;
else
/* Not sure what this counter measures in
@@ -990,7 +977,7 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev)
etdev->net_stats.rx_bytes += rfd->PacketSize;
memcpy(skb_put(skb, rfd->PacketSize),
- rx_local->Fbr[rindex]->Va[bindex],
+ rx_local->fbr[rindex]->virt[bindex],
rfd->PacketSize);
skb->dev = etdev->netdev;
@@ -1014,7 +1001,7 @@ PMP_RFD nic_rx_pkts(struct et131x_adapter *etdev)
*/
void et131x_reset_recv(struct et131x_adapter *etdev)
{
- WARN_ON(list_empty(&etdev->RxRing.RecvList));
+ WARN_ON(list_empty(&etdev->rx_ring.RecvList));
}
@@ -1032,8 +1019,8 @@ void et131x_handle_recv_interrupt(struct et131x_adapter *etdev)
/* Process up to available RFD's */
while (count < NUM_PACKETS_HANDLED) {
- if (list_empty(&etdev->RxRing.RecvList)) {
- WARN_ON(etdev->RxRing.nReadyRecv != 0);
+ if (list_empty(&etdev->rx_ring.RecvList)) {
+ WARN_ON(etdev->rx_ring.nReadyRecv != 0);
done = false;
break;
}
@@ -1058,7 +1045,7 @@ void et131x_handle_recv_interrupt(struct et131x_adapter *etdev)
etdev->Stats.ipackets++;
/* Set the status on the packet, either resources or success */
- if (etdev->RxRing.nReadyRecv < RFD_LOW_WATER_MARK) {
+ if (etdev->rx_ring.nReadyRecv < RFD_LOW_WATER_MARK) {
dev_warn(&etdev->pdev->dev,
"RFD's are running out\n");
}
@@ -1066,12 +1053,12 @@ void et131x_handle_recv_interrupt(struct et131x_adapter *etdev)
}
if (count == NUM_PACKETS_HANDLED || !done) {
- etdev->RxRing.UnfinishedReceives = true;
+ etdev->rx_ring.UnfinishedReceives = true;
writel(PARM_TX_TIME_INT_DEF * NANO_IN_A_MICRO,
&etdev->regs->global.watchdog_timer);
} else
/* Watchdog timer will disable itself if appropriate. */
- etdev->RxRing.UnfinishedReceives = false;
+ etdev->rx_ring.UnfinishedReceives = false;
}
static inline u32 bump_fbr(u32 *fbr, u32 limit)
@@ -1099,10 +1086,10 @@ static inline u32 bump_fbr(u32 *fbr, u32 limit)
*/
void nic_return_rfd(struct et131x_adapter *etdev, PMP_RFD rfd)
{
- struct _rx_ring_t *rx_local = &etdev->RxRing;
- struct _RXDMA_t __iomem *rx_dma = &etdev->regs->rxdma;
- uint16_t bi = rfd->bufferindex;
- uint8_t ri = rfd->ringindex;
+ struct rx_ring *rx_local = &etdev->rx_ring;
+ struct rxdma_regs __iomem *rx_dma = &etdev->regs->rxdma;
+ u16 bi = rfd->bufferindex;
+ u8 ri = rfd->ringindex;
unsigned long flags;
/* We don't use any of the OOB data besides status. Otherwise, we
@@ -1116,17 +1103,17 @@ void nic_return_rfd(struct et131x_adapter *etdev, PMP_RFD rfd)
spin_lock_irqsave(&etdev->FbrLock, flags);
if (ri == 1) {
- PFBR_DESC_t next =
- (PFBR_DESC_t) (rx_local->pFbr1RingVa) +
- INDEX10(rx_local->local_Fbr1_full);
+ struct fbr_desc *next =
+ (struct fbr_desc *) (rx_local->pFbr1RingVa) +
+ INDEX10(rx_local->local_Fbr1_full);
/* Handle the Free Buffer Ring advancement here. Write
* the PA / Buffer Index for the returned buffer into
* the oldest (next to be freed)FBR entry
*/
- next->addr_hi = rx_local->Fbr[1]->PAHigh[bi];
- next->addr_lo = rx_local->Fbr[1]->PALow[bi];
- next->word2.value = bi;
+ next->addr_hi = rx_local->fbr[1]->bus_high[bi];
+ next->addr_lo = rx_local->fbr[1]->bus_low[bi];
+ next->word2 = bi;
writel(bump_fbr(&rx_local->local_Fbr1_full,
rx_local->Fbr1NumEntries - 1),
@@ -1134,17 +1121,17 @@ void nic_return_rfd(struct et131x_adapter *etdev, PMP_RFD rfd)
}
#ifdef USE_FBR0
else {
- PFBR_DESC_t next =
- (PFBR_DESC_t) rx_local->pFbr0RingVa +
- INDEX10(rx_local->local_Fbr0_full);
+ struct fbr_desc *next = (struct fbr_desc *)
+ rx_local->pFbr0RingVa +
+ INDEX10(rx_local->local_Fbr0_full);
/* Handle the Free Buffer Ring advancement here. Write
* the PA / Buffer Index for the returned buffer into
* the oldest (next to be freed) FBR entry
*/
- next->addr_hi = rx_local->Fbr[0]->PAHigh[bi];
- next->addr_lo = rx_local->Fbr[0]->PALow[bi];
- next->word2.value = bi;
+ next->addr_hi = rx_local->fbr[0]->bus_high[bi];
+ next->addr_lo = rx_local->fbr[0]->bus_low[bi];
+ next->word2 = bi;
writel(bump_fbr(&rx_local->local_Fbr0_full,
rx_local->Fbr0NumEntries - 1),
diff --git a/drivers/staging/et131x/et1310_rx.h b/drivers/staging/et131x/et1310_rx.h
index 69514593612..ca84a9146d6 100644
--- a/drivers/staging/et131x/et1310_rx.h
+++ b/drivers/staging/et131x/et1310_rx.h
@@ -91,120 +91,60 @@
#define ALCATEL_BROADCAST_PKT 0x02000000
/* typedefs for Free Buffer Descriptors */
-typedef union _FBR_WORD2_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 reserved:22; /* bits 10-31 */
- u32 bi:10; /* bits 0-9(Buffer Index) */
-#else
- u32 bi:10; /* bits 0-9(Buffer Index) */
- u32 reserved:22; /* bit 10-31 */
-#endif
- } bits;
-} FBR_WORD2_t, *PFBR_WORD2_t;
-
-typedef struct _FBR_DESC_t {
+struct fbr_desc
+{
u32 addr_lo;
u32 addr_hi;
- FBR_WORD2_t word2;
-} FBR_DESC_t, *PFBR_DESC_t;
-
-/* Typedefs for Packet Status Ring Descriptors */
-typedef union _PKT_STAT_DESC_WORD0_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- /* top 16 bits are from the Alcatel Status Word as enumerated in */
- /* PE-MCXMAC Data Sheet IPD DS54 0210-1 (also IPD-DS80 0205-2) */
-#if 0
- u32 asw_trunc:1; /* bit 31(Rx frame truncated) */
-#endif
- u32 asw_long_evt:1; /* bit 31(Rx long event) */
- u32 asw_VLAN_tag:1; /* bit 30(VLAN tag detected) */
- u32 asw_unsupported_op:1; /* bit 29(unsupported OP code) */
- u32 asw_pause_frame:1; /* bit 28(is a pause frame) */
- u32 asw_control_frame:1; /* bit 27(is a control frame) */
- u32 asw_dribble_nibble:1; /* bit 26(spurious bits after EOP) */
- u32 asw_broadcast:1; /* bit 25(has a broadcast address) */
- u32 asw_multicast:1; /* bit 24(has a multicast address) */
- u32 asw_OK:1; /* bit 23(valid CRC + no code error) */
- u32 asw_too_long:1; /* bit 22(frame length > 1518 bytes) */
- u32 asw_len_chk_err:1; /* bit 21(frame length field incorrect) */
- u32 asw_CRC_err:1; /* bit 20(CRC error) */
- u32 asw_code_err:1; /* bit 19(one or more nibbles signalled as errors) */
- u32 asw_false_carrier_event:1; /* bit 18(bad carrier since last good packet) */
- u32 asw_RX_DV_event:1; /* bit 17(short receive event detected) */
- u32 asw_prev_pkt_dropped:1;/* bit 16(e.g. IFG too small on previous) */
- u32 unused:5; /* bits 11-15 */
- u32 vp:1; /* bit 10(VLAN Packet) */
- u32 jp:1; /* bit 9(Jumbo Packet) */
- u32 ft:1; /* bit 8(Frame Truncated) */
- u32 drop:1; /* bit 7(Drop packet) */
- u32 rxmac_error:1; /* bit 6(RXMAC Error Indicator) */
- u32 wol:1; /* bit 5(WOL Event) */
- u32 tcpp:1; /* bit 4(TCP checksum pass) */
- u32 tcpa:1; /* bit 3(TCP checksum assist) */
- u32 ipp:1; /* bit 2(IP checksum pass) */
- u32 ipa:1; /* bit 1(IP checksum assist) */
- u32 hp:1; /* bit 0(hash pass) */
-#else
- u32 hp:1; /* bit 0(hash pass) */
- u32 ipa:1; /* bit 1(IP checksum assist) */
- u32 ipp:1; /* bit 2(IP checksum pass) */
- u32 tcpa:1; /* bit 3(TCP checksum assist) */
- u32 tcpp:1; /* bit 4(TCP checksum pass) */
- u32 wol:1; /* bit 5(WOL Event) */
- u32 rxmac_error:1; /* bit 6(RXMAC Error Indicator) */
- u32 drop:1; /* bit 7(Drop packet) */
- u32 ft:1; /* bit 8(Frame Truncated) */
- u32 jp:1; /* bit 9(Jumbo Packet) */
- u32 vp:1; /* bit 10(VLAN Packet) */
- u32 unused:5; /* bits 11-15 */
- u32 asw_prev_pkt_dropped:1;/* bit 16(e.g. IFG too small on previous) */
- u32 asw_RX_DV_event:1; /* bit 17(short receive event detected) */
- u32 asw_false_carrier_event:1; /* bit 18(bad carrier since last good packet) */
- u32 asw_code_err:1; /* bit 19(one or more nibbles signalled as errors) */
- u32 asw_CRC_err:1; /* bit 20(CRC error) */
- u32 asw_len_chk_err:1; /* bit 21(frame length field incorrect) */
- u32 asw_too_long:1; /* bit 22(frame length > 1518 bytes) */
- u32 asw_OK:1; /* bit 23(valid CRC + no code error) */
- u32 asw_multicast:1; /* bit 24(has a multicast address) */
- u32 asw_broadcast:1; /* bit 25(has a broadcast address) */
- u32 asw_dribble_nibble:1; /* bit 26(spurious bits after EOP) */
- u32 asw_control_frame:1; /* bit 27(is a control frame) */
- u32 asw_pause_frame:1; /* bit 28(is a pause frame) */
- u32 asw_unsupported_op:1; /* bit 29(unsupported OP code) */
- u32 asw_VLAN_tag:1; /* bit 30(VLAN tag detected) */
- u32 asw_long_evt:1; /* bit 31(Rx long event) */
-#if 0
- u32 asw_trunc:1; /* bit 31(Rx frame truncated) */
-#endif
-#endif
- } bits;
-} PKT_STAT_DESC_WORD0_t, *PPKT_STAT_WORD0_t;
+ u32 word2; /* Bits 10-31 reserved, 0-9 descriptor */
+};
-typedef union _PKT_STAT_DESC_WORD1_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 unused:4; /* bits 28-31 */
- u32 ri:2; /* bits 26-27(Ring Index) */
- u32 bi:10; /* bits 16-25(Buffer Index) */
- u32 length:16; /* bit 0-15(length in bytes) */
-#else
- u32 length:16; /* bit 0-15(length in bytes) */
- u32 bi:10; /* bits 16-25(Buffer Index) */
- u32 ri:2; /* bits 26-27(Ring Index) */
- u32 unused:4; /* bits 28-31 */
-#endif
- } bits;
-} PKT_STAT_DESC_WORD1_t, *PPKT_STAT_WORD1_t;
+/* Packet Status Ring Descriptors
+ *
+ * Word 0:
+ *
+ * top 16 bits are from the Alcatel Status Word as enumerated in
+ * PE-MCXMAC Data Sheet IPD DS54 0210-1 (also IPD-DS80 0205-2)
+ *
+ * 0: hp hash pass
+ * 1: ipa IP checksum assist
+ * 2: ipp IP checksum pass
+ * 3: tcpa TCP checksum assist
+ * 4: tcpp TCP checksum pass
+ * 5: wol WOL Event
+ * 6: rxmac_error RXMAC Error Indicator
+ * 7: drop Drop packet
+ * 8: ft Frame Truncated
+ * 9: jp Jumbo Packet
+ * 10: vp VLAN Packet
+ * 11-15: unused
+ * 16: asw_prev_pkt_dropped e.g. IFG too small on previous
+ * 17: asw_RX_DV_event short receive event detected
+ * 18: asw_false_carrier_event bad carrier since last good packet
+ * 19: asw_code_err one or more nibbles signalled as errors
+ * 20: asw_CRC_err CRC error
+ * 21: asw_len_chk_err frame length field incorrect
+ * 22: asw_too_long frame length > 1518 bytes
+ * 23: asw_OK valid CRC + no code error
+ * 24: asw_multicast has a multicast address
+ * 25: asw_broadcast has a broadcast address
+ * 26: asw_dribble_nibble spurious bits after EOP
+ * 27: asw_control_frame is a control frame
+ * 28: asw_pause_frame is a pause frame
+ * 29: asw_unsupported_op unsupported OP code
+ * 30: asw_VLAN_tag VLAN tag detected
+ * 31: asw_long_evt Rx long event
+ *
+ * Word 1:
+ * 0-15: length length in bytes
+ * 16-25: bi Buffer Index
+ * 26-27: ri Ring Index
+ * 28-31: reserved
+ */
-typedef struct _PKT_STAT_DESC_t {
- PKT_STAT_DESC_WORD0_t word0;
- PKT_STAT_DESC_WORD1_t word1;
-} PKT_STAT_DESC_t, *PPKT_STAT_DESC_t;
+struct pkt_stat_desc {
+ u32 word0;
+ u32 word1;
+};
/* Typedefs for the RX DMA status word */
@@ -223,59 +163,38 @@ typedef struct _PKT_STAT_DESC_t {
* RXSTAT_WORD1_t structure holds part of the status bits of the Rx DMA engine
* that get copied out to memory by the ET-1310. Word 3 is a 32 bit word
* which contains the Packet Status Ring available offset.
+ *
+ * bit 0-15 reserved
+ * bit 16-27 PSRoffset
+ * bit 28 PSRwrap
+ * bit 29-31 unused
*/
-#define RXSTAT1_OFFSET 16
-#define RXSTAT1_MASK 0xFFF
-#define RXSTAT1_WRAP 0x10000000
-
-typedef union _rxstat_word1_t {
- u32 value;
- struct {
-#ifdef _BIT_FIELDS_HTOL
- u32 PSRunused:3; /* bits 29-31 */
- u32 PSRwrap:1; /* bit 28 */
- u32 PSRoffset:12; /* bits 16-27 */
- u32 reserved:16; /* bits 0-15 */
-#else
- u32 reserved:16; /* bits 0-15 */
- u32 PSRoffset:12; /* bits 16-27 */
- u32 PSRwrap:1; /* bit 28 */
- u32 PSRunused:3; /* bits 29-31 */
-#endif
- } bits;
-} RXSTAT_WORD1_t, *PRXSTAT_WORD1_t;
-
/*
- * RX_STATUS_BLOCK_t is sructure representing the status of the Rx DMA engine
- * it sits in free memory, and is pointed to by 0x101c / 0x1020
+ * struct rx_status_block is a structure representing the status of the Rx
+ * DMA engine it sits in free memory, and is pointed to by 0x101c / 0x1020
*/
-typedef struct _rx_status_block_t {
+struct rx_status_block {
u32 Word0;
- RXSTAT_WORD1_t Word1;
-} RX_STATUS_BLOCK_t, *PRX_STATUS_BLOCK_t;
+ u32 Word1;
+};
/*
* Structure for look-up table holding free buffer ring pointers
*/
-typedef struct _FbrLookupTable {
- void *Va[MAX_DESC_PER_RING_RX];
- void *Buffer1[MAX_DESC_PER_RING_RX];
- void *Buffer2[MAX_DESC_PER_RING_RX];
- u32 PAHigh[MAX_DESC_PER_RING_RX];
- u32 PALow[MAX_DESC_PER_RING_RX];
-} FBRLOOKUPTABLE, *PFBRLOOKUPTABLE;
-
-typedef enum {
- ONE_PACKET_INTERRUPT,
- FOUR_PACKET_INTERRUPT
-} eRX_INTERRUPT_STATE_t, *PeRX_INTERRUPT_STATE_t;
+struct fbr_lookup {
+ void *virt[MAX_DESC_PER_RING_RX];
+ void *buffer1[MAX_DESC_PER_RING_RX];
+ void *buffer2[MAX_DESC_PER_RING_RX];
+ u32 bus_high[MAX_DESC_PER_RING_RX];
+ u32 bus_low[MAX_DESC_PER_RING_RX];
+};
/*
- * RX_RING_t is sructure representing the adaptor's local reference(s) to the
- * rings
+ * struct rx_ring is the ssructure representing the adaptor's local
+ * reference(s) to the rings
*/
-typedef struct _rx_ring_t {
+struct rx_ring {
#ifdef USE_FBR0
void *pFbr0RingVa;
dma_addr_t pFbr0RingPa;
@@ -293,7 +212,7 @@ typedef struct _rx_ring_t {
dma_addr_t Fbr1MemPa[MAX_DESC_PER_RING_RX / FBR_CHUNKS];
uint64_t Fbr1Realpa;
uint64_t Fbr1offset;
- FBRLOOKUPTABLE *Fbr[2];
+ struct fbr_lookup *fbr[2]; /* One per ring */
u32 local_Fbr1_full;
u32 Fbr1NumEntries;
u32 Fbr1BufferSize;
@@ -303,8 +222,8 @@ typedef struct _rx_ring_t {
u32 local_psr_full;
u32 PsrNumEntries;
- void *pRxStatusVa;
- dma_addr_t pRxStatusPa;
+ struct rx_status_block *rx_status_block;
+ dma_addr_t rx_status_bus;
struct list_head RecvBufferPool;
@@ -320,30 +239,6 @@ typedef struct _rx_ring_t {
/* lookaside lists */
struct kmem_cache *RecvLookaside;
-} RX_RING_t, *PRX_RING_t;
-
-/* Forward reference of RFD */
-struct _MP_RFD;
-
-/* Forward declaration of the private adapter structure */
-struct et131x_adapter;
-
-/* PROTOTYPES for Initialization */
-int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter);
-void et131x_rx_dma_memory_free(struct et131x_adapter *adapter);
-int et131x_rfd_resources_alloc(struct et131x_adapter *adapter,
- struct _MP_RFD *pMpRfd);
-void et131x_rfd_resources_free(struct et131x_adapter *adapter,
- struct _MP_RFD *pMpRfd);
-int et131x_init_recv(struct et131x_adapter *adapter);
-
-void ConfigRxDmaRegs(struct et131x_adapter *adapter);
-void SetRxDmaTimer(struct et131x_adapter *adapter);
-void et131x_rx_dma_disable(struct et131x_adapter *adapter);
-void et131x_rx_dma_enable(struct et131x_adapter *adapter);
-
-void et131x_reset_recv(struct et131x_adapter *adapter);
-
-void et131x_handle_recv_interrupt(struct et131x_adapter *adapter);
+};
#endif /* __ET1310_RX_H__ */
diff --git a/drivers/staging/et131x/et1310_tx.c b/drivers/staging/et131x/et1310_tx.c
index 977e8b34e7a..b6ff20f47de 100644
--- a/drivers/staging/et131x/et1310_tx.c
+++ b/drivers/staging/et131x/et1310_tx.c
@@ -84,15 +84,9 @@
#include <linux/ioport.h>
#include "et1310_phy.h"
-#include "et1310_pm.h"
-#include "et1310_jagcore.h"
-
#include "et131x_adapter.h"
-#include "et131x_initpci.h"
-#include "et131x_isr.h"
-
#include "et1310_tx.h"
-
+#include "et131x.h"
static inline void et131x_free_send_packet(struct et131x_adapter *etdev,
struct tcb *tcb);
@@ -200,7 +194,7 @@ void et131x_tx_dma_memory_free(struct et131x_adapter *adapter)
*/
void ConfigTxDmaRegs(struct et131x_adapter *etdev)
{
- struct _TXDMA_t __iomem *txdma = &etdev->regs->txdma;
+ struct txdma_regs __iomem *txdma = &etdev->regs->txdma;
/* Load the hardware with the start of the transmit descriptor ring. */
writel((u32) ((u64)etdev->tx_ring.tx_desc_ring_pa >> 32),
diff --git a/drivers/staging/et131x/et1310_tx.h b/drivers/staging/et131x/et1310_tx.h
index 4f0ea81978f..82d06e9870d 100644
--- a/drivers/staging/et131x/et1310_tx.h
+++ b/drivers/staging/et131x/et1310_tx.h
@@ -147,18 +147,4 @@ struct tx_ring {
int since_irq;
};
-/* Forward declaration of the private adapter structure */
-struct et131x_adapter;
-
-/* PROTOTYPES for et1310_tx.c */
-int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter);
-void et131x_tx_dma_memory_free(struct et131x_adapter *adapter);
-void ConfigTxDmaRegs(struct et131x_adapter *adapter);
-void et131x_init_send(struct et131x_adapter *adapter);
-void et131x_tx_dma_disable(struct et131x_adapter *adapter);
-void et131x_tx_dma_enable(struct et131x_adapter *adapter);
-void et131x_handle_send_interrupt(struct et131x_adapter *adapter);
-void et131x_free_busy_send_packets(struct et131x_adapter *adapter);
-int et131x_send_packets(struct sk_buff *skb, struct net_device *netdev);
-
#endif /* __ET1310_TX_H__ */
diff --git a/drivers/staging/et131x/et131x.h b/drivers/staging/et131x/et131x.h
new file mode 100644
index 00000000000..a8abfe6ca81
--- /dev/null
+++ b/drivers/staging/et131x/et131x.h
@@ -0,0 +1,153 @@
+/*
+ * Merged from files
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ * http://www.agere.com
+ *
+ * SOFTWARE LICENSE
+ *
+ * This software is provided subject to the following terms and conditions,
+ * which you should read carefully before using the software. Using this
+ * software indicates your acceptance of these terms and conditions. If you do
+ * not agree with these terms and conditions, do not use the software.
+ *
+ * Copyright © 2005 Agere Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source or binary forms, with or without
+ * modifications, are permitted provided that the following conditions are met:
+ *
+ * . Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following Disclaimer as comments in the code as
+ * well as in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * . Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following Disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * . Neither the name of Agere Systems Inc. nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
+ * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
+ * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, 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.
+ *
+ */
+
+/* et131x_eeprom.c */
+int et131x_init_eeprom(struct et131x_adapter *etdev);
+
+/* et131x_initpci.c */
+void ConfigGlobalRegs(struct et131x_adapter *pAdapter);
+void ConfigMMCRegs(struct et131x_adapter *pAdapter);
+void et131x_enable_interrupts(struct et131x_adapter *adapter);
+void et131x_disable_interrupts(struct et131x_adapter *adapter);
+void et131x_align_allocated_memory(struct et131x_adapter *adapter,
+ u64 *phys_addr,
+ u64 *offset, u64 mask);
+
+int et131x_adapter_setup(struct et131x_adapter *adapter);
+int et131x_adapter_memory_alloc(struct et131x_adapter *adapter);
+void et131x_adapter_memory_free(struct et131x_adapter *adapter);
+void et131x_hwaddr_init(struct et131x_adapter *adapter);
+void et131x_soft_reset(struct et131x_adapter *adapter);
+
+/* et131x_isr.c */
+irqreturn_t et131x_isr(int irq, void *dev_id);
+void et131x_isr_handler(struct work_struct *work);
+
+/* et1310_mac.c */
+void ConfigMACRegs1(struct et131x_adapter *adapter);
+void ConfigMACRegs2(struct et131x_adapter *adapter);
+void ConfigRxMacRegs(struct et131x_adapter *adapter);
+void ConfigTxMacRegs(struct et131x_adapter *adapter);
+void ConfigMacStatRegs(struct et131x_adapter *adapter);
+void ConfigFlowControl(struct et131x_adapter *adapter);
+void UpdateMacStatHostCounters(struct et131x_adapter *adapter);
+void HandleMacStatInterrupt(struct et131x_adapter *adapter);
+void SetupDeviceForMulticast(struct et131x_adapter *adapter);
+void SetupDeviceForUnicast(struct et131x_adapter *adapter);
+
+/* et131x_netdev.c */
+struct net_device *et131x_device_alloc(void);
+
+/* et131x_pm.c */
+void EnablePhyComa(struct et131x_adapter *adapter);
+void DisablePhyComa(struct et131x_adapter *adapter);
+
+/* et131x_phy.c */
+void ET1310_PhyInit(struct et131x_adapter *adapter);
+void ET1310_PhyReset(struct et131x_adapter *adapter);
+void ET1310_PhyPowerDown(struct et131x_adapter *adapter, bool down);
+void ET1310_PhyAdvertise1000BaseT(struct et131x_adapter *adapter,
+ u16 duplex);
+void ET1310_PhyAccessMiBit(struct et131x_adapter *adapter,
+ u16 action,
+ u16 regnum, u16 bitnum, u8 *value);
+
+int et131x_xcvr_find(struct et131x_adapter *adapter);
+void et131x_setphy_normal(struct et131x_adapter *adapter);
+
+/* static inline function does not work because et131x_adapter is not always
+ * defined
+ */
+int PhyMiRead(struct et131x_adapter *adapter, u8 xcvrAddr,
+ u8 xcvrReg, u16 *value);
+#define MiRead(adapter, xcvrReg, value) \
+ PhyMiRead((adapter), (adapter)->Stats.xcvr_addr, (xcvrReg), (value))
+
+int32_t MiWrite(struct et131x_adapter *adapter,
+ u8 xcvReg, u16 value);
+void et131x_Mii_check(struct et131x_adapter *pAdapter,
+ MI_BMSR_t bmsr, MI_BMSR_t bmsr_ints);
+
+/* This last is not strictly required (the driver could call the TPAL
+ * version instead), but this sets the adapter up correctly, and calls the
+ * access routine indirectly. This protects the driver from changes in TPAL.
+ */
+void SetPhy_10BaseTHalfDuplex(struct et131x_adapter *adapter);
+
+
+/* et1310_rx.c */
+int et131x_rx_dma_memory_alloc(struct et131x_adapter *adapter);
+void et131x_rx_dma_memory_free(struct et131x_adapter *adapter);
+int et131x_rfd_resources_alloc(struct et131x_adapter *adapter,
+ struct _MP_RFD *pMpRfd);
+void et131x_rfd_resources_free(struct et131x_adapter *adapter,
+ struct _MP_RFD *pMpRfd);
+int et131x_init_recv(struct et131x_adapter *adapter);
+
+void ConfigRxDmaRegs(struct et131x_adapter *adapter);
+void SetRxDmaTimer(struct et131x_adapter *adapter);
+void et131x_rx_dma_disable(struct et131x_adapter *adapter);
+void et131x_rx_dma_enable(struct et131x_adapter *adapter);
+
+void et131x_reset_recv(struct et131x_adapter *adapter);
+
+void et131x_handle_recv_interrupt(struct et131x_adapter *adapter);
+
+/* et131x_tx.c */
+int et131x_tx_dma_memory_alloc(struct et131x_adapter *adapter);
+void et131x_tx_dma_memory_free(struct et131x_adapter *adapter);
+void ConfigTxDmaRegs(struct et131x_adapter *adapter);
+void et131x_init_send(struct et131x_adapter *adapter);
+void et131x_tx_dma_disable(struct et131x_adapter *adapter);
+void et131x_tx_dma_enable(struct et131x_adapter *adapter);
+void et131x_handle_send_interrupt(struct et131x_adapter *adapter);
+void et131x_free_busy_send_packets(struct et131x_adapter *adapter);
+int et131x_send_packets(struct sk_buff *skb, struct net_device *netdev);
+
diff --git a/drivers/staging/et131x/et131x_adapter.h b/drivers/staging/et131x/et131x_adapter.h
index 3f7f37a56b6..64a678fcb60 100644
--- a/drivers/staging/et131x/et131x_adapter.h
+++ b/drivers/staging/et131x/et131x_adapter.h
@@ -77,38 +77,11 @@
*/
#define NUM_TRAFFIC_CLASSES 1
-/*
- * There are three ways of counting errors - if there are more than X errors
- * in Y packets (represented by the "SAMPLE" macros), if there are more than
- * N errors in a S mSec time period (the "PERIOD" macros), or if there are
- * consecutive packets with errors (CONSEC_ERRORED_THRESH). This last covers
- * for "Bursty" errors, and the errored packets may well not be contiguous,
- * but several errors where the packet counter has changed by less than a
- * small amount will cause this count to increment.
- */
-#define TX_PACKETS_IN_SAMPLE 10000
-#define TX_MAX_ERRORS_IN_SAMPLE 50
-
#define TX_ERROR_PERIOD 1000
-#define TX_MAX_ERRORS_IN_PERIOD 10
-
-#define LINK_DETECTION_TIMER 5000
-
-#define TX_CONSEC_RANGE 5
-#define TX_CONSEC_ERRORED_THRESH 10
#define LO_MARK_PERCENT_FOR_PSR 15
#define LO_MARK_PERCENT_FOR_RX 15
-/* Counters for error rate monitoring */
-typedef struct _MP_ERR_COUNTERS {
- u32 PktCountTxPackets;
- u32 PktCountTxErrors;
- u32 TimerBasedTxErrors;
- u32 PktCountLastError;
- u32 ErredConsecPackets;
-} MP_ERR_COUNTERS, *PMP_ERR_COUNTERS;
-
/* RFD (Receive Frame Descriptor) */
typedef struct _MP_RFD {
struct list_head list_node;
@@ -174,6 +147,20 @@ typedef struct _ce_stats_t {
u32 InterruptStatus;
} CE_STATS_t, *PCE_STATS_t;
+typedef struct _MP_POWER_MGMT {
+ /* variable putting the phy into coma mode when boot up with no cable
+ * plugged in after 5 seconds
+ */
+ u8 TransPhyComaModeOnBoot;
+
+ /* Next two used to save power information at power down. This
+ * information will be used during power up to set up parts of Power
+ * Management in JAGCore
+ */
+ u16 PowerDownSpeed;
+ u8 PowerDownDuplex;
+} MP_POWER_MGMT, *PMP_POWER_MGMT;
+
/* The private adapter structure */
struct et131x_adapter {
struct net_device *netdev;
@@ -248,7 +235,7 @@ struct et131x_adapter {
struct tx_ring tx_ring;
/* Rx Memory Variables */
- RX_RING_t RxRing;
+ struct rx_ring rx_ring;
/* Loopback specifics */
u8 ReplicaPhyLoopbk; /* Replica Enable */
diff --git a/drivers/staging/et131x/et131x_config.h b/drivers/staging/et131x/et131x_config.h
deleted file mode 100644
index 642c0f6dd6f..00000000000
--- a/drivers/staging/et131x/et131x_config.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Agere Systems Inc.
- * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- * http://www.agere.com
- *
- *------------------------------------------------------------------------------
- *
- * et131x_config.h - Defines, structs, enums, prototypes, etc. to support
- * et131x_config.c
- *
- *------------------------------------------------------------------------------
- *
- * SOFTWARE LICENSE
- *
- * This software is provided subject to the following terms and conditions,
- * which you should read carefully before using the software. Using this
- * software indicates your acceptance of these terms and conditions. If you do
- * not agree with these terms and conditions, do not use the software.
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source or binary forms, with or without
- * modifications, are permitted provided that the following conditions are met:
- *
- * . Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following Disclaimer as comments in the code as
- * well as in the documentation and/or other materials provided with the
- * distribution.
- *
- * . Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following Disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * . Neither the name of Agere Systems Inc. nor the names of the contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * Disclaimer
- *
- * THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
- * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
- * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- */
-
-#ifndef __ET131X_CONFIG_H__
-#define __ET131X_CONFIG_H__
-
-/* Forward declaration of the private adapter structure */
-struct et131x_adapter;
-
-void et131x_config_parse(struct et131x_adapter *adapter);
-
-#endif /* __ET131X_CONFIG_H__ */
diff --git a/drivers/staging/et131x/et131x_initpci.c b/drivers/staging/et131x/et131x_initpci.c
index 0892b6a538d..5ad7e5a6f63 100644
--- a/drivers/staging/et131x/et131x_initpci.c
+++ b/drivers/staging/et131x/et131x_initpci.c
@@ -87,20 +87,16 @@
#include <linux/random.h>
#include "et1310_phy.h"
-#include "et1310_pm.h"
-#include "et1310_jagcore.h"
#include "et131x_adapter.h"
-#include "et131x_netdev.h"
-#include "et131x_config.h"
-#include "et131x_isr.h"
#include "et1310_address_map.h"
#include "et1310_tx.h"
#include "et1310_rx.h"
-#include "et1310_mac.h"
-#include "et1310_eeprom.h"
+#include "et131x.h"
+#define INTERNAL_MEM_SIZE 0x400 /* 1024 of internal memory */
+#define INTERNAL_MEM_RX_OFFSET 0x1FF /* 50% Tx, 50% Rx */
/* Defines for Parameter Default/Min/Max vaules */
#define PARM_SPEED_DUPLEX_MIN 0
@@ -327,7 +323,7 @@ void et131x_link_detection_handler(unsigned long data)
*/
void ConfigGlobalRegs(struct et131x_adapter *etdev)
{
- struct _GLOBAL_t __iomem *regs = &etdev->regs->global;
+ struct global_regs __iomem *regs = &etdev->regs->global;
writel(0, &regs->rxq_start_addr);
writel(INTERNAL_MEM_SIZE - 1, &regs->txq_end_addr);
diff --git a/drivers/staging/et131x/et131x_initpci.h b/drivers/staging/et131x/et131x_initpci.h
deleted file mode 100644
index 7269569a874..00000000000
--- a/drivers/staging/et131x/et131x_initpci.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Agere Systems Inc.
- * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- * http://www.agere.com
- *
- *------------------------------------------------------------------------------
- *
- * et131x_initpci.h - Header which includes common data and function prototypes
- * related to the driver's PCI (and PCI Express) information.
- *
- *------------------------------------------------------------------------------
- *
- * SOFTWARE LICENSE
- *
- * This software is provided subject to the following terms and conditions,
- * which you should read carefully before using the software. Using this
- * software indicates your acceptance of these terms and conditions. If you do
- * not agree with these terms and conditions, do not use the software.
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source or binary forms, with or without
- * modifications, are permitted provided that the following conditions are met:
- *
- * . Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following Disclaimer as comments in the code as
- * well as in the documentation and/or other materials provided with the
- * distribution.
- *
- * . Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following Disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * . Neither the name of Agere Systems Inc. nor the names of the contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * Disclaimer
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
- * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
- * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- */
-
-#ifndef __ET131X_INITPCI_H__
-#define __ET131X_INITPCI_H__
-
-/* Function Prototypes */
-void et131x_align_allocated_memory(struct et131x_adapter *adapter,
- u64 *phys_addr,
- u64 *offset, u64 mask);
-
-int et131x_adapter_setup(struct et131x_adapter *adapter);
-int et131x_adapter_memory_alloc(struct et131x_adapter *adapter);
-void et131x_adapter_memory_free(struct et131x_adapter *adapter);
-void et131x_hwaddr_init(struct et131x_adapter *adapter);
-void et131x_soft_reset(struct et131x_adapter *adapter);
-
-#endif /* __ET131X_INITPCI_H__ */
diff --git a/drivers/staging/et131x/et131x_isr.c b/drivers/staging/et131x/et131x_isr.c
index f6d452dd14e..8b6e0b7ec56 100644
--- a/drivers/staging/et131x/et131x_isr.c
+++ b/drivers/staging/et131x/et131x_isr.c
@@ -85,11 +85,27 @@
#include <linux/ioport.h>
#include "et1310_phy.h"
-#include "et1310_pm.h"
-#include "et1310_jagcore.h"
-#include "et1310_mac.h"
-
#include "et131x_adapter.h"
+#include "et131x.h"
+
+/*
+ * For interrupts, normal running is:
+ * rxdma_xfr_done, phy_interrupt, mac_stat_interrupt,
+ * watchdog_interrupt & txdma_xfer_done
+ *
+ * In both cases, when flow control is enabled for either Tx or bi-direction,
+ * we additional enable rx_fbr0_low and rx_fbr1_low, so we know when the
+ * buffer rings are running low.
+ */
+#define INT_MASK_DISABLE 0xffffffff
+
+/* NOTE: Masking out MAC_STAT Interrupt for now...
+ * #define INT_MASK_ENABLE 0xfff6bf17
+ * #define INT_MASK_ENABLE_NO_FLOW 0xfff6bfd7
+ */
+#define INT_MASK_ENABLE 0xfffebf17
+#define INT_MASK_ENABLE_NO_FLOW 0xfffebfd7
+
/**
* et131x_enable_interrupts - enable interrupt
@@ -185,7 +201,7 @@ irqreturn_t et131x_isr(int irq, void *dev_id)
if (++tcb->stale > 1)
status |= ET_INTR_TXDMA_ISR;
- if (adapter->RxRing.UnfinishedReceives)
+ if (adapter->rx_ring.UnfinishedReceives)
status |= ET_INTR_RXDMA_XFR_DONE;
else if (tcb == NULL)
writel(0, &adapter->regs->global.watchdog_timer);
@@ -390,7 +406,7 @@ void et131x_isr_handler(struct work_struct *work)
/* Let's move on to the TxMac */
if (status & ET_INTR_TXMAC) {
- u32 err = readl(&iomem->txmac.err.value);
+ u32 err = readl(&iomem->txmac.err);
/*
* When any of the errors occur and TXMAC generates
@@ -425,12 +441,12 @@ void et131x_isr_handler(struct work_struct *work)
dev_warn(&etdev->pdev->dev,
"RXMAC interrupt, error 0x%08x. Requesting reset\n",
- readl(&iomem->rxmac.err_reg.value));
+ readl(&iomem->rxmac.err_reg));
dev_warn(&etdev->pdev->dev,
"Enable 0x%08x, Diag 0x%08x\n",
- readl(&iomem->rxmac.ctrl.value),
- readl(&iomem->rxmac.rxq_diag.value));
+ readl(&iomem->rxmac.ctrl),
+ readl(&iomem->rxmac.rxq_diag));
/*
* If we are debugging, we want to see this error,
diff --git a/drivers/staging/et131x/et131x_isr.h b/drivers/staging/et131x/et131x_isr.h
deleted file mode 100644
index 906d57727e2..00000000000
--- a/drivers/staging/et131x/et131x_isr.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Agere Systems Inc.
- * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- * http://www.agere.com
- *
- *------------------------------------------------------------------------------
- *
- * et131x_isr.h - Defines, structs, enums, prototypes, etc. pertaining to the
- * ISR processing code.
- *
- *------------------------------------------------------------------------------
- *
- * SOFTWARE LICENSE
- *
- * This software is provided subject to the following terms and conditions,
- * which you should read carefully before using the software. Using this
- * software indicates your acceptance of these terms and conditions. If you do
- * not agree with these terms and conditions, do not use the software.
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source or binary forms, with or without
- * modifications, are permitted provided that the following conditions are met:
- *
- * . Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following Disclaimer as comments in the code as
- * well as in the documentation and/or other materials provided with the
- * distribution.
- *
- * . Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following Disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * . Neither the name of Agere Systems Inc. nor the names of the contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * Disclaimer
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
- * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
- * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- */
-
-#ifndef __ET131X_ISR_H__
-#define __ET131X_ISR_H__
-
-irqreturn_t et131x_isr(int irq, void *dev_id);
-void et131x_isr_handler(struct work_struct *work);
-
-#endif /* __ET131X_ISR_H__ */
diff --git a/drivers/staging/et131x/et131x_netdev.c b/drivers/staging/et131x/et131x_netdev.c
index edb78ae9e59..40f8954dde4 100644
--- a/drivers/staging/et131x/et131x_netdev.c
+++ b/drivers/staging/et131x/et131x_netdev.c
@@ -85,14 +85,9 @@
#include <linux/ioport.h>
#include "et1310_phy.h"
-#include "et1310_pm.h"
-#include "et1310_jagcore.h"
-#include "et1310_mac.h"
#include "et1310_tx.h"
-
#include "et131x_adapter.h"
-#include "et131x_isr.h"
-#include "et131x_initpci.h"
+#include "et131x.h"
struct net_device_stats *et131x_stats(struct net_device *netdev);
int et131x_open(struct net_device *netdev);
@@ -339,66 +334,64 @@ int et131x_ioctl(struct net_device *netdev, struct ifreq *reqbuf, int cmd)
* et131x_set_packet_filter - Configures the Rx Packet filtering on the device
* @adapter: pointer to our private adapter structure
*
+ * FIXME: lot of dups with MAC code
+ *
* Returns 0 on success, errno on failure
*/
int et131x_set_packet_filter(struct et131x_adapter *adapter)
{
int status = 0;
uint32_t filter = adapter->PacketFilter;
- RXMAC_CTRL_t ctrl;
- RXMAC_PF_CTRL_t pf_ctrl;
+ u32 ctrl;
+ u32 pf_ctrl;
- ctrl.value = readl(&adapter->regs->rxmac.ctrl.value);
- pf_ctrl.value = readl(&adapter->regs->rxmac.pf_ctrl.value);
+ ctrl = readl(&adapter->regs->rxmac.ctrl);
+ pf_ctrl = readl(&adapter->regs->rxmac.pf_ctrl);
/* Default to disabled packet filtering. Enable it in the individual
* case statements that require the device to filter something
*/
- ctrl.bits.pkt_filter_disable = 1;
+ ctrl |= 0x04;
/* Set us to be in promiscuous mode so we receive everything, this
* is also true when we get a packet filter of 0
*/
- if ((filter & ET131X_PACKET_TYPE_PROMISCUOUS) || filter == 0) {
- pf_ctrl.bits.filter_broad_en = 0;
- pf_ctrl.bits.filter_multi_en = 0;
- pf_ctrl.bits.filter_uni_en = 0;
- } else {
+ if ((filter & ET131X_PACKET_TYPE_PROMISCUOUS) || filter == 0)
+ pf_ctrl &= ~7; /* Clear filter bits */
+ else {
/*
* Set us up with Multicast packet filtering. Three cases are
* possible - (1) we have a multi-cast list, (2) we receive ALL
* multicast entries or (3) we receive none.
*/
- if (filter & ET131X_PACKET_TYPE_ALL_MULTICAST) {
- pf_ctrl.bits.filter_multi_en = 0;
- } else {
+ if (filter & ET131X_PACKET_TYPE_ALL_MULTICAST)
+ pf_ctrl &= ~2; /* Multicast filter bit */
+ else {
SetupDeviceForMulticast(adapter);
- pf_ctrl.bits.filter_multi_en = 1;
- ctrl.bits.pkt_filter_disable = 0;
+ pf_ctrl |= 2;
+ ctrl &= ~0x04;
}
/* Set us up with Unicast packet filtering */
if (filter & ET131X_PACKET_TYPE_DIRECTED) {
SetupDeviceForUnicast(adapter);
- pf_ctrl.bits.filter_uni_en = 1;
- ctrl.bits.pkt_filter_disable = 0;
+ pf_ctrl |= 4;
+ ctrl &= ~0x04;
}
/* Set us up with Broadcast packet filtering */
if (filter & ET131X_PACKET_TYPE_BROADCAST) {
- pf_ctrl.bits.filter_broad_en = 1;
- ctrl.bits.pkt_filter_disable = 0;
- } else {
- pf_ctrl.bits.filter_broad_en = 0;
- }
+ pf_ctrl |= 1; /* Broadcast filter bit */
+ ctrl &= ~0x04;
+ } else
+ pf_ctrl &= ~1;
/* Setup the receive mac configuration registers - Packet
* Filter control + the enable / disable for packet filter
* in the control reg.
*/
- writel(pf_ctrl.value,
- &adapter->regs->rxmac.pf_ctrl.value);
- writel(ctrl.value, &adapter->regs->rxmac.ctrl.value);
+ writel(pf_ctrl, &adapter->regs->rxmac.pf_ctrl);
+ writel(ctrl, &adapter->regs->rxmac.ctrl);
}
return status;
}
@@ -675,12 +668,8 @@ int et131x_set_mac_addr(struct net_device *netdev, void *new_mac)
memcpy(netdev->dev_addr, address->sa_data, netdev->addr_len);
- printk(KERN_INFO
- "%s: Setting MAC address to %02x:%02x:%02x:%02x:%02x:%02x\n",
- netdev->name,
- netdev->dev_addr[0], netdev->dev_addr[1],
- netdev->dev_addr[2], netdev->dev_addr[3],
- netdev->dev_addr[4], netdev->dev_addr[5]);
+ printk(KERN_INFO "%s: Setting MAC address to %pM\n",
+ netdev->name, netdev->dev_addr);
/* Free Rx DMA memory */
et131x_adapter_memory_free(adapter);
diff --git a/drivers/staging/et131x/et131x_netdev.h b/drivers/staging/et131x/et131x_netdev.h
deleted file mode 100644
index 1eb4a922c01..00000000000
--- a/drivers/staging/et131x/et131x_netdev.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Agere Systems Inc.
- * 10/100/1000 Base-T Ethernet Driver for the ET1301 and ET131x series MACs
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- * http://www.agere.com
- *
- *------------------------------------------------------------------------------
- *
- * et131x_netdev.h - Defines, structs, enums, prototypes, etc. related to the
- * driver's net_device support.
- *
- *------------------------------------------------------------------------------
- *
- * SOFTWARE LICENSE
- *
- * This software is provided subject to the following terms and conditions,
- * which you should read carefully before using the software. Using this
- * software indicates your acceptance of these terms and conditions. If you do
- * not agree with these terms and conditions, do not use the software.
- *
- * Copyright © 2005 Agere Systems Inc.
- * All rights reserved.
- *
- * Redistribution and use in source or binary forms, with or without
- * modifications, are permitted provided that the following conditions are met:
- *
- * . Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following Disclaimer as comments in the code as
- * well as in the documentation and/or other materials provided with the
- * distribution.
- *
- * . Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following Disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * . Neither the name of Agere Systems Inc. nor the names of the contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * Disclaimer
- *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY
- * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
- * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- *
- */
-
-#ifndef __ET131X_NETDEV_H__
-#define __ET131X_NETDEV_H__
-
-struct net_device *et131x_device_alloc(void);
-
-#endif /* __ET131X_NETDEV_H__ */
diff --git a/drivers/staging/et131x/et131x_version.h b/drivers/staging/et131x/et131x_version.h
index 568f6c8c34f..2aa9bda44ac 100644
--- a/drivers/staging/et131x/et131x_version.h
+++ b/drivers/staging/et131x/et131x_version.h
@@ -62,20 +62,13 @@
#define DRIVER_LICENSE "Dual BSD/GPL"
#define DRIVER_DEVICE_STRING "ET1310"
#define DRIVER_NAME "et131x"
-#define DRIVER_MAJOR_VERSION 1
-#define DRIVER_MINOR_VERSION 2
-#define DRIVER_PATCH_VERSION 3
-#define DRIVER_VERSION_STRING "1.2.3"
+#define DRIVER_VERSION_STRING "1.2.3-lk"
#define DRIVER_VENDOR "Agere Systems, http://www.agere.com"
#define DRIVER_DESC "10/100/1000 Base-T Ethernet Driver"
-#define STRUCT_MODULE "net" /* blux: missed by the kernel */
-
#define DRIVER_INFO DRIVER_DESC " for the "\
DRIVER_DEVICE_STRING ", v" \
DRIVER_VERSION_STRING " by " \
DRIVER_VENDOR
-#define DRIVER_NAME_EXT "et131x.ko"
-
#endif /* __ET131X_VERSION_H__ */
diff --git a/drivers/staging/frontier/alphatrack.c b/drivers/staging/frontier/alphatrack.c
index 15aed87fe1b..a50a21518a8 100644
--- a/drivers/staging/frontier/alphatrack.c
+++ b/drivers/staging/frontier/alphatrack.c
@@ -58,7 +58,7 @@
#endif
/* table of devices that work with this driver */
-static struct usb_device_id usb_alphatrack_table[] = {
+static const struct usb_device_id usb_alphatrack_table[] = {
{USB_DEVICE(VENDOR_ID, PRODUCT_ID)},
{} /* Terminating entry */
};
diff --git a/drivers/staging/frontier/tranzport.c b/drivers/staging/frontier/tranzport.c
index ef8fcc8c67b..2f03f43f3a2 100644
--- a/drivers/staging/frontier/tranzport.c
+++ b/drivers/staging/frontier/tranzport.c
@@ -55,7 +55,7 @@
#endif
/* table of devices that work with this driver */
-static struct usb_device_id usb_tranzport_table[] = {
+static const struct usb_device_id usb_tranzport_table[] = {
{USB_DEVICE(VENDOR_ID, PRODUCT_ID)},
{} /* Terminating entry */
};
diff --git a/drivers/staging/go7007/go7007-driver.c b/drivers/staging/go7007/go7007-driver.c
index fb1345ffb85..d42ba169699 100644
--- a/drivers/staging/go7007/go7007-driver.c
+++ b/drivers/staging/go7007/go7007-driver.c
@@ -128,6 +128,8 @@ static int go7007_load_encoder(struct go7007 *go)
return rv;
}
+MODULE_FIRMWARE("go7007fw.bin");
+
/*
* Boot the encoder and register the I2C adapter if requested. Do the
* minimum initialization necessary, since the board-specific code may
diff --git a/drivers/staging/go7007/go7007-usb.c b/drivers/staging/go7007/go7007-usb.c
index 1e89dc04ec2..ee278f64a16 100644
--- a/drivers/staging/go7007/go7007-usb.c
+++ b/drivers/staging/go7007/go7007-usb.c
@@ -444,7 +444,9 @@ static struct go7007_usb_board board_sensoray_2250 = {
},
};
-static struct usb_device_id go7007_usb_id_table[] = {
+MODULE_FIRMWARE("go7007tv.bin");
+
+static const struct usb_device_id go7007_usb_id_table[] = {
{
.match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
USB_DEVICE_ID_MATCH_INT_INFO,
diff --git a/drivers/staging/go7007/s2250-board.c b/drivers/staging/go7007/s2250-board.c
index c324f6ea002..dc89502ea1b 100644
--- a/drivers/staging/go7007/s2250-board.c
+++ b/drivers/staging/go7007/s2250-board.c
@@ -667,7 +667,7 @@ static int s2250_remove(struct i2c_client *client)
return 0;
}
-static struct i2c_device_id s2250_id[] = {
+static const struct i2c_device_id s2250_id[] = {
{ "s2250", 0 },
{ }
};
diff --git a/drivers/staging/go7007/s2250-loader.c b/drivers/staging/go7007/s2250-loader.c
index c152ab9be2f..1de2dfb16d3 100644
--- a/drivers/staging/go7007/s2250-loader.c
+++ b/drivers/staging/go7007/s2250-loader.c
@@ -139,7 +139,7 @@ failed2:
static void s2250loader_disconnect(struct usb_interface *interface)
{
- pdevice_extension_t s = usb_get_intfdata(interface);
+ pdevice_extension_t s;
printk(KERN_INFO "s2250: disconnect\n");
lock_kernel();
s = usb_get_intfdata(interface);
@@ -148,7 +148,7 @@ static void s2250loader_disconnect(struct usb_interface *interface)
unlock_kernel();
}
-static struct usb_device_id s2250loader_ids[] = {
+static const struct usb_device_id s2250loader_ids[] = {
{USB_DEVICE(0x1943, 0xa250)},
{} /* Terminating entry */
};
diff --git a/drivers/staging/go7007/saa7134-go7007.c b/drivers/staging/go7007/saa7134-go7007.c
index 665bbf59d02..b25d7d2090e 100644
--- a/drivers/staging/go7007/saa7134-go7007.c
+++ b/drivers/staging/go7007/saa7134-go7007.c
@@ -84,6 +84,7 @@ static struct go7007_board_info board_voyager = {
},
},
};
+MODULE_FIRMWARE("go7007tv.bin");
/********************* Driver for GPIO HPI interface *********************/
diff --git a/drivers/staging/go7007/wis-ov7640.c b/drivers/staging/go7007/wis-ov7640.c
index 04d6d3a498a..4f0cbdde276 100644
--- a/drivers/staging/go7007/wis-ov7640.c
+++ b/drivers/staging/go7007/wis-ov7640.c
@@ -77,7 +77,7 @@ static int wis_ov7640_remove(struct i2c_client *client)
return 0;
}
-static struct i2c_device_id wis_ov7640_id[] = {
+static const struct i2c_device_id wis_ov7640_id[] = {
{ "wis_ov7640", 0 },
{ }
};
diff --git a/drivers/staging/go7007/wis-saa7113.c b/drivers/staging/go7007/wis-saa7113.c
index 9ab893bd204..d196e16fe72 100644
--- a/drivers/staging/go7007/wis-saa7113.c
+++ b/drivers/staging/go7007/wis-saa7113.c
@@ -304,7 +304,7 @@ static int wis_saa7113_remove(struct i2c_client *client)
return 0;
}
-static struct i2c_device_id wis_saa7113_id[] = {
+static const struct i2c_device_id wis_saa7113_id[] = {
{ "wis_saa7113", 0 },
{ }
};
diff --git a/drivers/staging/go7007/wis-saa7115.c b/drivers/staging/go7007/wis-saa7115.c
index 8687ad2de76..0f2b4a0cecc 100644
--- a/drivers/staging/go7007/wis-saa7115.c
+++ b/drivers/staging/go7007/wis-saa7115.c
@@ -437,7 +437,7 @@ static int wis_saa7115_remove(struct i2c_client *client)
return 0;
}
-static struct i2c_device_id wis_saa7115_id[] = {
+static const struct i2c_device_id wis_saa7115_id[] = {
{ "wis_saa7115", 0 },
{ }
};
diff --git a/drivers/staging/go7007/wis-sony-tuner.c b/drivers/staging/go7007/wis-sony-tuner.c
index 086896cec49..c723e4aa714 100644
--- a/drivers/staging/go7007/wis-sony-tuner.c
+++ b/drivers/staging/go7007/wis-sony-tuner.c
@@ -688,7 +688,7 @@ static int wis_sony_tuner_remove(struct i2c_client *client)
return 0;
}
-static struct i2c_device_id wis_sony_tuner_id[] = {
+static const struct i2c_device_id wis_sony_tuner_id[] = {
{ "wis_sony_tuner", 0 },
{ }
};
diff --git a/drivers/staging/go7007/wis-tw2804.c b/drivers/staging/go7007/wis-tw2804.c
index e15794a2a0a..1983839f554 100644
--- a/drivers/staging/go7007/wis-tw2804.c
+++ b/drivers/staging/go7007/wis-tw2804.c
@@ -327,7 +327,7 @@ static int wis_tw2804_remove(struct i2c_client *client)
return 0;
}
-static struct i2c_device_id wis_tw2804_id[] = {
+static const struct i2c_device_id wis_tw2804_id[] = {
{ "wis_tw2804", 0 },
{ }
};
diff --git a/drivers/staging/go7007/wis-tw9903.c b/drivers/staging/go7007/wis-tw9903.c
index 506dca6e942..f97e2be3c0b 100644
--- a/drivers/staging/go7007/wis-tw9903.c
+++ b/drivers/staging/go7007/wis-tw9903.c
@@ -309,7 +309,7 @@ static int wis_tw9903_remove(struct i2c_client *client)
return 0;
}
-static struct i2c_device_id wis_tw9903_id[] = {
+static const struct i2c_device_id wis_tw9903_id[] = {
{ "wis_tw9903", 0 },
{ }
};
diff --git a/drivers/staging/go7007/wis-uda1342.c b/drivers/staging/go7007/wis-uda1342.c
index 739c7ae8913..5c4eb49d735 100644
--- a/drivers/staging/go7007/wis-uda1342.c
+++ b/drivers/staging/go7007/wis-uda1342.c
@@ -82,7 +82,7 @@ static int wis_uda1342_remove(struct i2c_client *client)
return 0;
}
-static struct i2c_device_id wis_uda1342_id[] = {
+static const struct i2c_device_id wis_uda1342_id[] = {
{ "wis_uda1342", 0 },
{ }
};
diff --git a/drivers/staging/hv/Channel.c b/drivers/staging/hv/Channel.c
index 746370e8211..d46eb145484 100644
--- a/drivers/staging/hv/Channel.c
+++ b/drivers/staging/hv/Channel.c
@@ -991,9 +991,8 @@ void VmbusChannelOnTimer(unsigned long data)
{
struct vmbus_channel *channel = (struct vmbus_channel *)data;
- if (channel->OnChannelCallback) {
+ if (channel->OnChannelCallback)
channel->OnChannelCallback(channel->ChannelCallbackContext);
- }
}
/**
diff --git a/drivers/staging/hv/Hv.c b/drivers/staging/hv/Hv.c
index c2809f2a2ce..51149e69f3e 100644
--- a/drivers/staging/hv/Hv.c
+++ b/drivers/staging/hv/Hv.c
@@ -208,50 +208,51 @@ int HvInit(void)
/* HvQueryHypervisorFeatures(maxLeaf); */
/*
- * Determine if we are running on xenlinux (ie x2v shim) or native
- * linux
+ * We only support running on top of Hyper-V
*/
rdmsrl(HV_X64_MSR_GUEST_OS_ID, gHvContext.GuestId);
- if (gHvContext.GuestId == 0) {
- /* Write our OS info */
- wrmsrl(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID);
- gHvContext.GuestId = HV_LINUX_GUEST_ID;
+
+ if (gHvContext.GuestId != 0) {
+ DPRINT_ERR(VMBUS, "Unknown guest id (0x%llx)!!",
+ gHvContext.GuestId);
+ goto Cleanup;
}
+ /* Write our OS info */
+ wrmsrl(HV_X64_MSR_GUEST_OS_ID, HV_LINUX_GUEST_ID);
+ gHvContext.GuestId = HV_LINUX_GUEST_ID;
+
/* See if the hypercall page is already set */
rdmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
- if (gHvContext.GuestId == HV_LINUX_GUEST_ID) {
- /* Allocate the hypercall page memory */
- /* virtAddr = osd_PageAlloc(1); */
- virtAddr = osd_VirtualAllocExec(PAGE_SIZE);
-
- if (!virtAddr) {
- DPRINT_ERR(VMBUS,
- "unable to allocate hypercall page!!");
- goto Cleanup;
- }
- hypercallMsr.Enable = 1;
- /* hypercallMsr.GuestPhysicalAddress =
- * virt_to_phys(virtAddr) >> PAGE_SHIFT; */
- hypercallMsr.GuestPhysicalAddress = vmalloc_to_pfn(virtAddr);
- wrmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
+ /*
+ * Allocate the hypercall page memory
+ * virtAddr = osd_PageAlloc(1);
+ */
+ virtAddr = osd_VirtualAllocExec(PAGE_SIZE);
- /* Confirm that hypercall page did get setup. */
- hypercallMsr.AsUINT64 = 0;
- rdmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
- if (!hypercallMsr.Enable) {
- DPRINT_ERR(VMBUS, "unable to set hypercall page!!");
- goto Cleanup;
- }
+ if (!virtAddr) {
+ DPRINT_ERR(VMBUS,
+ "unable to allocate hypercall page!!");
+ goto Cleanup;
+ }
- gHvContext.HypercallPage = virtAddr;
- } else {
- DPRINT_ERR(VMBUS, "Unknown guest id (0x%llx)!!",
- gHvContext.GuestId);
+ hypercallMsr.Enable = 1;
+
+ hypercallMsr.GuestPhysicalAddress = vmalloc_to_pfn(virtAddr);
+ wrmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
+
+ /* Confirm that hypercall page did get setup. */
+ hypercallMsr.AsUINT64 = 0;
+ rdmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
+
+ if (!hypercallMsr.Enable) {
+ DPRINT_ERR(VMBUS, "unable to set hypercall page!!");
goto Cleanup;
}
+ gHvContext.HypercallPage = virtAddr;
+
DPRINT_INFO(VMBUS, "Hypercall page VA=%p, PA=0x%0llx",
gHvContext.HypercallPage,
(u64)hypercallMsr.GuestPhysicalAddress << PAGE_SHIFT);
@@ -273,8 +274,6 @@ int HvInit(void)
gHvContext.SignalEventParam->FlagNumber = 0;
gHvContext.SignalEventParam->RsvdZ = 0;
- /* DPRINT_DBG(VMBUS, "My id %llu", HvGetCurrentPartitionId()); */
-
DPRINT_EXIT(VMBUS);
return ret;
@@ -311,17 +310,14 @@ void HvCleanup(void)
kfree(gHvContext.SignalEventBuffer);
}
- if (gHvContext.GuestId == HV_LINUX_GUEST_ID) {
- if (gHvContext.HypercallPage) {
- hypercallMsr.AsUINT64 = 0;
- wrmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
- vfree(gHvContext.HypercallPage);
- gHvContext.HypercallPage = NULL;
- }
+ if (gHvContext.HypercallPage) {
+ hypercallMsr.AsUINT64 = 0;
+ wrmsrl(HV_X64_MSR_HYPERCALL, hypercallMsr.AsUINT64);
+ vfree(gHvContext.HypercallPage);
+ gHvContext.HypercallPage = NULL;
}
DPRINT_EXIT(VMBUS);
-
}
/**
@@ -393,7 +389,7 @@ void HvSynicInit(void *irqarg)
union hv_synic_siefp siefp;
union hv_synic_sint sharedSint;
union hv_synic_scontrol sctrl;
- u64 guestID;
+
u32 irqVector = *((u32 *)(irqarg));
int cpu = smp_processor_id();
@@ -409,71 +405,41 @@ void HvSynicInit(void *irqarg)
DPRINT_INFO(VMBUS, "SynIC version: %llx", version);
- /* TODO: Handle SMP */
- if (gHvContext.GuestId == HV_XENLINUX_GUEST_ID) {
- DPRINT_INFO(VMBUS, "Skipping SIMP and SIEFP setup since "
- "it is already set.");
-
- rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
- rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
-
- DPRINT_DBG(VMBUS, "Simp: %llx, Sifep: %llx",
- simp.AsUINT64, siefp.AsUINT64);
-
- /*
- * Determine if we are running on xenlinux (ie x2v shim) or
- * native linux
- */
- rdmsrl(HV_X64_MSR_GUEST_OS_ID, guestID);
- if (guestID == HV_LINUX_GUEST_ID) {
- gHvContext.synICMessagePage[cpu] =
- phys_to_virt(simp.BaseSimpGpa << PAGE_SHIFT);
- gHvContext.synICEventPage[cpu] =
- phys_to_virt(siefp.BaseSiefpGpa << PAGE_SHIFT);
- } else {
- DPRINT_ERR(VMBUS, "unknown guest id!!");
- goto Cleanup;
- }
- DPRINT_DBG(VMBUS, "MAPPED: Simp: %p, Sifep: %p",
- gHvContext.synICMessagePage[cpu],
- gHvContext.synICEventPage[cpu]);
- } else {
- gHvContext.synICMessagePage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC);
- if (gHvContext.synICMessagePage[cpu] == NULL) {
- DPRINT_ERR(VMBUS,
- "unable to allocate SYNIC message page!!");
- goto Cleanup;
- }
+ gHvContext.synICMessagePage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC);
- gHvContext.synICEventPage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC);
- if (gHvContext.synICEventPage[cpu] == NULL) {
- DPRINT_ERR(VMBUS,
- "unable to allocate SYNIC event page!!");
- goto Cleanup;
- }
+ if (gHvContext.synICMessagePage[cpu] == NULL) {
+ DPRINT_ERR(VMBUS,
+ "unable to allocate SYNIC message page!!");
+ goto Cleanup;
+ }
- /* Setup the Synic's message page */
- rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
- simp.SimpEnabled = 1;
- simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[cpu])
- >> PAGE_SHIFT;
+ gHvContext.synICEventPage[cpu] = (void *)get_zeroed_page(GFP_ATOMIC);
- DPRINT_DBG(VMBUS, "HV_X64_MSR_SIMP msr set to: %llx",
- simp.AsUINT64);
+ if (gHvContext.synICEventPage[cpu] == NULL) {
+ DPRINT_ERR(VMBUS,
+ "unable to allocate SYNIC event page!!");
+ goto Cleanup;
+ }
- wrmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
+ /* Setup the Synic's message page */
+ rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
+ simp.SimpEnabled = 1;
+ simp.BaseSimpGpa = virt_to_phys(gHvContext.synICMessagePage[cpu])
+ >> PAGE_SHIFT;
- /* Setup the Synic's event page */
- rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
- siefp.SiefpEnabled = 1;
- siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[cpu])
- >> PAGE_SHIFT;
+ DPRINT_DBG(VMBUS, "HV_X64_MSR_SIMP msr set to: %llx", simp.AsUINT64);
- DPRINT_DBG(VMBUS, "HV_X64_MSR_SIEFP msr set to: %llx",
- siefp.AsUINT64);
+ wrmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
- wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
- }
+ /* Setup the Synic's event page */
+ rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
+ siefp.SiefpEnabled = 1;
+ siefp.BaseSiefpGpa = virt_to_phys(gHvContext.synICEventPage[cpu])
+ >> PAGE_SHIFT;
+
+ DPRINT_DBG(VMBUS, "HV_X64_MSR_SIEFP msr set to: %llx", siefp.AsUINT64);
+
+ wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
/* Setup the interception SINT. */
/* wrmsrl((HV_X64_MSR_SINT0 + HV_SYNIC_INTERCEPTION_SINT_INDEX), */
@@ -505,13 +471,11 @@ void HvSynicInit(void *irqarg)
return;
Cleanup:
- if (gHvContext.GuestId == HV_LINUX_GUEST_ID) {
- if (gHvContext.synICEventPage[cpu])
- osd_PageFree(gHvContext.synICEventPage[cpu], 1);
+ if (gHvContext.synICEventPage[cpu])
+ osd_PageFree(gHvContext.synICEventPage[cpu], 1);
- if (gHvContext.synICMessagePage[cpu])
- osd_PageFree(gHvContext.synICMessagePage[cpu], 1);
- }
+ if (gHvContext.synICMessagePage[cpu])
+ osd_PageFree(gHvContext.synICMessagePage[cpu], 1);
DPRINT_EXIT(VMBUS);
return;
@@ -542,27 +506,20 @@ void HvSynicCleanup(void *arg)
/* Disable the interrupt */
wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, sharedSint.AsUINT64);
- /*
- * Disable and free the resources only if we are running as
- * native linux since in xenlinux, we are sharing the
- * resources with the x2v shim
- */
- if (gHvContext.GuestId == HV_LINUX_GUEST_ID) {
- rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
- simp.SimpEnabled = 0;
- simp.BaseSimpGpa = 0;
+ rdmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
+ simp.SimpEnabled = 0;
+ simp.BaseSimpGpa = 0;
- wrmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
+ wrmsrl(HV_X64_MSR_SIMP, simp.AsUINT64);
- rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
- siefp.SiefpEnabled = 0;
- siefp.BaseSiefpGpa = 0;
+ rdmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
+ siefp.SiefpEnabled = 0;
+ siefp.BaseSiefpGpa = 0;
- wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
+ wrmsrl(HV_X64_MSR_SIEFP, siefp.AsUINT64);
- osd_PageFree(gHvContext.synICMessagePage[cpu], 1);
- osd_PageFree(gHvContext.synICEventPage[cpu], 1);
- }
+ osd_PageFree(gHvContext.synICMessagePage[cpu], 1);
+ osd_PageFree(gHvContext.synICEventPage[cpu], 1);
DPRINT_EXIT(VMBUS);
}
diff --git a/drivers/staging/hv/Hv.h b/drivers/staging/hv/Hv.h
index fce4b5cdac3..41f5ebb86e1 100644
--- a/drivers/staging/hv/Hv.h
+++ b/drivers/staging/hv/Hv.h
@@ -41,11 +41,6 @@ enum {
#define HV_PRESENT_BIT 0x80000000
-#define HV_XENLINUX_GUEST_ID_LO 0x00000000
-#define HV_XENLINUX_GUEST_ID_HI 0x0B00B135
-#define HV_XENLINUX_GUEST_ID (((u64)HV_XENLINUX_GUEST_ID_HI << 32) \
- | HV_XENLINUX_GUEST_ID_LO)
-
#define HV_LINUX_GUEST_ID_LO 0x00000000
#define HV_LINUX_GUEST_ID_HI 0xB16B00B5
#define HV_LINUX_GUEST_ID (((u64)HV_LINUX_GUEST_ID_HI << 32) | \
@@ -102,8 +97,9 @@ struct hv_input_signal_event_buffer {
};
struct hv_context {
- /* XenLinux or native Linux. If XenLinux, the hypercall and synic pages
- * has already been initialized */
+ /* We only support running on top of Hyper-V
+ * So at this point this really can only contain the Hyper-V ID
+ */
u64 GuestId;
void *HypercallPage;
diff --git a/drivers/staging/hv/NetVscApi.h b/drivers/staging/hv/NetVscApi.h
index 1ce2b74a34a..95d7a32b12f 100644
--- a/drivers/staging/hv/NetVscApi.h
+++ b/drivers/staging/hv/NetVscApi.h
@@ -105,8 +105,6 @@ struct netvsc_driver {
void (*OnLinkStatusChanged)(struct hv_device *dev, u32 Status);
/* Specific to this driver */
- int (*OnOpen)(struct hv_device *dev);
- int (*OnClose)(struct hv_device *dev);
int (*OnSend)(struct hv_device *dev, struct hv_netvsc_packet *packet);
void *Context;
@@ -119,5 +117,7 @@ struct netvsc_device_info {
/* Interface */
int NetVscInitialize(struct hv_driver *drv);
+int RndisFilterOnOpen(struct hv_device *Device);
+int RndisFilterOnClose(struct hv_device *Device);
#endif /* _NETVSC_API_H_ */
diff --git a/drivers/staging/hv/RingBuffer.c b/drivers/staging/hv/RingBuffer.c
index f69ae33a91e..80b8a2c7784 100644
--- a/drivers/staging/hv/RingBuffer.c
+++ b/drivers/staging/hv/RingBuffer.c
@@ -48,7 +48,7 @@ Description:
static inline void
GetRingBufferAvailBytes(RING_BUFFER_INFO *rbi, u32 *read, u32 *write)
{
- u32 read_loc,write_loc;
+ u32 read_loc, write_loc;
/* Capture the read/write indices before they changed */
read_loc = rbi->RingBuffer->ReadIndex;
@@ -68,7 +68,7 @@ Description:
--*/
static inline u32
-GetNextWriteLocation(RING_BUFFER_INFO* RingInfo)
+GetNextWriteLocation(RING_BUFFER_INFO *RingInfo)
{
u32 next = RingInfo->RingBuffer->WriteIndex;
@@ -87,7 +87,7 @@ Description:
--*/
static inline void
-SetNextWriteLocation(RING_BUFFER_INFO* RingInfo, u32 NextWriteLocation)
+SetNextWriteLocation(RING_BUFFER_INFO *RingInfo, u32 NextWriteLocation)
{
RingInfo->RingBuffer->WriteIndex = NextWriteLocation;
}
@@ -102,7 +102,7 @@ Description:
--*/
static inline u32
-GetNextReadLocation(RING_BUFFER_INFO* RingInfo)
+GetNextReadLocation(RING_BUFFER_INFO *RingInfo)
{
u32 next = RingInfo->RingBuffer->ReadIndex;
@@ -122,7 +122,7 @@ Description:
--*/
static inline u32
-GetNextReadLocationWithOffset(RING_BUFFER_INFO* RingInfo, u32 Offset)
+GetNextReadLocationWithOffset(RING_BUFFER_INFO *RingInfo, u32 Offset)
{
u32 next = RingInfo->RingBuffer->ReadIndex;
@@ -143,7 +143,7 @@ Description:
--*/
static inline void
-SetNextReadLocation(RING_BUFFER_INFO* RingInfo, u32 NextReadLocation)
+SetNextReadLocation(RING_BUFFER_INFO *RingInfo, u32 NextReadLocation)
{
RingInfo->RingBuffer->ReadIndex = NextReadLocation;
}
@@ -159,7 +159,7 @@ Description:
--*/
static inline void *
-GetRingBuffer(RING_BUFFER_INFO* RingInfo)
+GetRingBuffer(RING_BUFFER_INFO *RingInfo)
{
return (void *)RingInfo->RingBuffer->Buffer;
}
@@ -175,7 +175,7 @@ Description:
--*/
static inline u32
-GetRingBufferSize(RING_BUFFER_INFO* RingInfo)
+GetRingBufferSize(RING_BUFFER_INFO *RingInfo)
{
return RingInfo->RingDataSize;
}
@@ -190,9 +190,10 @@ Description:
--*/
static inline u64
-GetRingBufferIndices(RING_BUFFER_INFO* RingInfo)
+GetRingBufferIndices(RING_BUFFER_INFO *RingInfo)
{
- return ((u64)RingInfo->RingBuffer->WriteIndex << 32) || RingInfo->RingBuffer->ReadIndex;
+ return ((u64)RingInfo->RingBuffer->WriteIndex << 32)
+ || RingInfo->RingBuffer->ReadIndex;
}
@@ -210,9 +211,14 @@ void DumpRingInfo(RING_BUFFER_INFO *RingInfo, char *Prefix)
u32 bytesAvailToWrite;
u32 bytesAvailToRead;
- GetRingBufferAvailBytes(RingInfo, &bytesAvailToRead, &bytesAvailToWrite);
+ GetRingBufferAvailBytes(RingInfo,
+ &bytesAvailToRead,
+ &bytesAvailToWrite);
- DPRINT(VMBUS, DEBUG_RING_LVL, "%s <<ringinfo %p buffer %p avail write %u avail read %u read idx %u write idx %u>>",
+ DPRINT(VMBUS,
+ DEBUG_RING_LVL,
+ "%s <<ringinfo %p buffer %p avail write %u "
+ "avail read %u read idx %u write idx %u>>",
Prefix,
RingInfo,
RingInfo->RingBuffer->Buffer,
@@ -229,13 +235,13 @@ static u32
CopyToRingBuffer(
RING_BUFFER_INFO *RingInfo,
u32 StartWriteOffset,
- void * Src,
+ void *Src,
u32 SrcLen);
static u32
CopyFromRingBuffer(
RING_BUFFER_INFO *RingInfo,
- void * Dest,
+ void *Dest,
u32 DestLen,
u32 StartReadOffset);
@@ -256,15 +262,15 @@ void RingBufferGetDebugInfo(RING_BUFFER_INFO *RingInfo,
u32 bytesAvailToWrite;
u32 bytesAvailToRead;
- if (RingInfo->RingBuffer)
- {
- GetRingBufferAvailBytes(RingInfo, &bytesAvailToRead, &bytesAvailToWrite);
+ if (RingInfo->RingBuffer) {
+ GetRingBufferAvailBytes(RingInfo,
+ &bytesAvailToRead,
+ &bytesAvailToWrite);
DebugInfo->BytesAvailToRead = bytesAvailToRead;
DebugInfo->BytesAvailToWrite = bytesAvailToWrite;
DebugInfo->CurrentReadIndex = RingInfo->RingBuffer->ReadIndex;
DebugInfo->CurrentWriteIndex = RingInfo->RingBuffer->WriteIndex;
-
DebugInfo->CurrentInterruptMask = RingInfo->RingBuffer->InterruptMask;
}
}
@@ -299,7 +305,7 @@ int RingBufferInit(RING_BUFFER_INFO *RingInfo, void *Buffer, u32 BufferLen)
memset(RingInfo, 0, sizeof(RING_BUFFER_INFO));
- RingInfo->RingBuffer = (RING_BUFFER*)Buffer;
+ RingInfo->RingBuffer = (RING_BUFFER *)Buffer;
RingInfo->RingBuffer->ReadIndex = RingInfo->RingBuffer->WriteIndex = 0;
RingInfo->RingSize = BufferLen;
@@ -319,7 +325,7 @@ Description:
Cleanup the ring buffer
--*/
-void RingBufferCleanup(RING_BUFFER_INFO* RingInfo)
+void RingBufferCleanup(RING_BUFFER_INFO *RingInfo)
{
}
@@ -335,14 +341,14 @@ Description:
int RingBufferWrite(RING_BUFFER_INFO *OutRingInfo,
struct scatterlist *sglist, u32 sgcount)
{
- int i=0;
+ int i = 0;
u32 byteAvailToWrite;
u32 byteAvailToRead;
- u32 totalBytesToWrite=0;
+ u32 totalBytesToWrite = 0;
struct scatterlist *sg;
volatile u32 nextWriteLocation;
- u64 prevIndices=0;
+ u64 prevIndices = 0;
unsigned long flags;
DPRINT_ENTER(VMBUS);
@@ -356,17 +362,23 @@ int RingBufferWrite(RING_BUFFER_INFO *OutRingInfo,
spin_lock_irqsave(&OutRingInfo->ring_lock, flags);
- GetRingBufferAvailBytes(OutRingInfo, &byteAvailToRead, &byteAvailToWrite);
+ GetRingBufferAvailBytes(OutRingInfo,
+ &byteAvailToRead,
+ &byteAvailToWrite);
DPRINT_DBG(VMBUS, "Writing %u bytes...", totalBytesToWrite);
/* DumpRingInfo(OutRingInfo, "BEFORE "); */
- /* If there is only room for the packet, assume it is full. Otherwise, the next time around, we think the ring buffer */
+ /* If there is only room for the packet, assume it is full. */
+ /* Otherwise, the next time around, we think the ring buffer */
/* is empty since the read index == write index */
- if (byteAvailToWrite <= totalBytesToWrite)
- {
- DPRINT_DBG(VMBUS, "No more space left on outbound ring buffer (needed %u, avail %u)", totalBytesToWrite, byteAvailToWrite);
+ if (byteAvailToWrite <= totalBytesToWrite) {
+ DPRINT_DBG(VMBUS,
+ "No more space left on outbound ring buffer "
+ "(needed %u, avail %u)",
+ totalBytesToWrite,
+ byteAvailToWrite);
spin_unlock_irqrestore(&OutRingInfo->ring_lock, flags);
@@ -423,17 +435,22 @@ int RingBufferPeek(RING_BUFFER_INFO *InRingInfo, void *Buffer, u32 BufferLen)
{
u32 bytesAvailToWrite;
u32 bytesAvailToRead;
- u32 nextReadLocation=0;
+ u32 nextReadLocation = 0;
unsigned long flags;
spin_lock_irqsave(&InRingInfo->ring_lock, flags);
- GetRingBufferAvailBytes(InRingInfo, &bytesAvailToRead, &bytesAvailToWrite);
+ GetRingBufferAvailBytes(InRingInfo,
+ &bytesAvailToRead,
+ &bytesAvailToWrite);
/* Make sure there is something to read */
- if (bytesAvailToRead < BufferLen )
- {
- /* DPRINT_DBG(VMBUS, "got callback but not enough to read <avail to read %d read size %d>!!", bytesAvailToRead, BufferLen); */
+ if (bytesAvailToRead < BufferLen) {
+ /* DPRINT_DBG(VMBUS,
+ "got callback but not enough to read "
+ "<avail to read %d read size %d>!!",
+ bytesAvailToRead,
+ BufferLen); */
spin_unlock_irqrestore(&InRingInfo->ring_lock, flags);
@@ -444,9 +461,9 @@ int RingBufferPeek(RING_BUFFER_INFO *InRingInfo, void *Buffer, u32 BufferLen)
nextReadLocation = GetNextReadLocation(InRingInfo);
nextReadLocation = CopyFromRingBuffer(InRingInfo,
- Buffer,
- BufferLen,
- nextReadLocation);
+ Buffer,
+ BufferLen,
+ nextReadLocation);
spin_unlock_irqrestore(&InRingInfo->ring_lock, flags);
@@ -468,24 +485,29 @@ int RingBufferRead(RING_BUFFER_INFO *InRingInfo, void *Buffer,
{
u32 bytesAvailToWrite;
u32 bytesAvailToRead;
- u32 nextReadLocation=0;
- u64 prevIndices=0;
+ u32 nextReadLocation = 0;
+ u64 prevIndices = 0;
unsigned long flags;
ASSERT(BufferLen > 0);
spin_lock_irqsave(&InRingInfo->ring_lock, flags);
- GetRingBufferAvailBytes(InRingInfo, &bytesAvailToRead, &bytesAvailToWrite);
+ GetRingBufferAvailBytes(InRingInfo,
+ &bytesAvailToRead,
+ &bytesAvailToWrite);
DPRINT_DBG(VMBUS, "Reading %u bytes...", BufferLen);
/* DumpRingInfo(InRingInfo, "BEFORE "); */
/* Make sure there is something to read */
- if (bytesAvailToRead < BufferLen )
- {
- DPRINT_DBG(VMBUS, "got callback but not enough to read <avail to read %d read size %d>!!", bytesAvailToRead, BufferLen);
+ if (bytesAvailToRead < BufferLen) {
+ DPRINT_DBG(VMBUS,
+ "got callback but not enough to read "
+ "<avail to read %d read size %d>!!",
+ bytesAvailToRead,
+ BufferLen);
spin_unlock_irqrestore(&InRingInfo->ring_lock, flags);
@@ -495,17 +517,18 @@ int RingBufferRead(RING_BUFFER_INFO *InRingInfo, void *Buffer,
nextReadLocation = GetNextReadLocationWithOffset(InRingInfo, Offset);
nextReadLocation = CopyFromRingBuffer(InRingInfo,
- Buffer,
- BufferLen,
- nextReadLocation);
+ Buffer,
+ BufferLen,
+ nextReadLocation);
nextReadLocation = CopyFromRingBuffer(InRingInfo,
- &prevIndices,
- sizeof(u64),
- nextReadLocation);
+ &prevIndices,
+ sizeof(u64),
+ nextReadLocation);
/* Make sure all reads are done before we update the read index since */
- /* the writer may start writing to the read area once the read index is updated */
+ /* the writer may start writing to the read area once the read index */
+ /*is updated */
mb();
/* Update the read index */
@@ -533,25 +556,22 @@ static u32
CopyToRingBuffer(
RING_BUFFER_INFO *RingInfo,
u32 StartWriteOffset,
- void * Src,
+ void *Src,
u32 SrcLen)
{
- void * ringBuffer=GetRingBuffer(RingInfo);
- u32 ringBufferSize=GetRingBufferSize(RingInfo);
+ void *ringBuffer = GetRingBuffer(RingInfo);
+ u32 ringBufferSize = GetRingBufferSize(RingInfo);
u32 fragLen;
- if (SrcLen > ringBufferSize - StartWriteOffset) /* wrap-around detected! */
- {
+ /* wrap-around detected! */
+ if (SrcLen > ringBufferSize - StartWriteOffset) {
DPRINT_DBG(VMBUS, "wrap-around detected!");
fragLen = ringBufferSize - StartWriteOffset;
memcpy(ringBuffer + StartWriteOffset, Src, fragLen);
memcpy(ringBuffer, Src + fragLen, SrcLen - fragLen);
- }
- else
- {
+ } else
memcpy(ringBuffer + StartWriteOffset, Src, SrcLen);
- }
StartWriteOffset += SrcLen;
StartWriteOffset %= ringBufferSize;
@@ -573,28 +593,27 @@ Description:
static u32
CopyFromRingBuffer(
RING_BUFFER_INFO *RingInfo,
- void * Dest,
+ void *Dest,
u32 DestLen,
u32 StartReadOffset)
{
- void * ringBuffer=GetRingBuffer(RingInfo);
- u32 ringBufferSize=GetRingBufferSize(RingInfo);
+ void *ringBuffer = GetRingBuffer(RingInfo);
+ u32 ringBufferSize = GetRingBufferSize(RingInfo);
u32 fragLen;
- if (DestLen > ringBufferSize - StartReadOffset) /* wrap-around detected at the src */
- {
+ /* wrap-around detected at the src */
+ if (DestLen > ringBufferSize - StartReadOffset) {
DPRINT_DBG(VMBUS, "src wrap-around detected!");
fragLen = ringBufferSize - StartReadOffset;
memcpy(Dest, ringBuffer + StartReadOffset, fragLen);
memcpy(Dest + fragLen, ringBuffer, DestLen - fragLen);
- }
- else
- {
+ } else
+
memcpy(Dest, ringBuffer + StartReadOffset, DestLen);
- }
+
StartReadOffset += DestLen;
StartReadOffset %= ringBufferSize;
diff --git a/drivers/staging/hv/RndisFilter.c b/drivers/staging/hv/RndisFilter.c
index 26d79975387..1ab7fa97d37 100644
--- a/drivers/staging/hv/RndisFilter.c
+++ b/drivers/staging/hv/RndisFilter.c
@@ -85,10 +85,6 @@ static int RndisFilterOnDeviceRemove(struct hv_device *Device);
static void RndisFilterOnCleanup(struct hv_driver *Driver);
-static int RndisFilterOnOpen(struct hv_device *Device);
-
-static int RndisFilterOnClose(struct hv_device *Device);
-
static int RndisFilterOnSend(struct hv_device *Device,
struct hv_netvsc_packet *Packet);
@@ -654,8 +650,6 @@ int RndisFilterInit(struct netvsc_driver *Driver)
Driver->Base.OnDeviceRemove = RndisFilterOnDeviceRemove;
Driver->Base.OnCleanup = RndisFilterOnCleanup;
Driver->OnSend = RndisFilterOnSend;
- Driver->OnOpen = RndisFilterOnOpen;
- Driver->OnClose = RndisFilterOnClose;
/* Driver->QueryLinkStatus = RndisFilterQueryDeviceLinkStatus; */
Driver->OnReceiveCallback = RndisFilterOnReceive;
@@ -888,7 +882,7 @@ static void RndisFilterOnCleanup(struct hv_driver *Driver)
DPRINT_EXIT(NETVSC);
}
-static int RndisFilterOnOpen(struct hv_device *Device)
+int RndisFilterOnOpen(struct hv_device *Device)
{
int ret;
struct netvsc_device *netDevice = Device->Extension;
@@ -903,7 +897,7 @@ static int RndisFilterOnOpen(struct hv_device *Device)
return ret;
}
-static int RndisFilterOnClose(struct hv_device *Device)
+int RndisFilterOnClose(struct hv_device *Device)
{
int ret;
struct netvsc_device *netDevice = Device->Extension;
diff --git a/drivers/staging/hv/StorVsc.c b/drivers/staging/hv/StorVsc.c
index 2f7c425896f..38ea1407f22 100644
--- a/drivers/staging/hv/StorVsc.c
+++ b/drivers/staging/hv/StorVsc.c
@@ -625,7 +625,7 @@ static int StorVscOnDeviceRemove(struct hv_device *Device)
return 0;
}
-static int StorVscOnHostReset(struct hv_device *Device)
+int StorVscOnHostReset(struct hv_device *Device)
{
struct storvsc_device *storDevice;
struct storvsc_request_extension *request;
@@ -842,7 +842,6 @@ int StorVscInitialize(struct hv_driver *Driver)
storDriver->Base.OnCleanup = StorVscOnCleanup;
storDriver->OnIORequest = StorVscOnIORequest;
- storDriver->OnHostReset = StorVscOnHostReset;
DPRINT_EXIT(STORVSC);
diff --git a/drivers/staging/hv/StorVscApi.h b/drivers/staging/hv/StorVscApi.h
index 69c14066c47..126a8588edb 100644
--- a/drivers/staging/hv/StorVscApi.h
+++ b/drivers/staging/hv/StorVscApi.h
@@ -91,13 +91,9 @@ struct storvsc_driver_object {
/* Maximum # of requests in flight per channel/device */
u32 MaxOutstandingRequestsPerChannel;
- /* Set by the caller to allow us to re-enumerate the bus on the host */
- void (*OnHostRescan)(struct hv_device *Device);
-
/* Specific to this driver */
int (*OnIORequest)(struct hv_device *Device,
struct hv_storvsc_request *Request);
- int (*OnHostReset)(struct hv_device *Device);
};
struct storvsc_device_info {
@@ -108,6 +104,7 @@ struct storvsc_device_info {
/* Interface */
int StorVscInitialize(struct hv_driver *driver);
+int StorVscOnHostReset(struct hv_device *Device);
int BlkVscInitialize(struct hv_driver *driver);
#endif /* _STORVSC_API_H_ */
diff --git a/drivers/staging/hv/VersionInfo.h b/drivers/staging/hv/VersionInfo.h
index 9c3641d99ed..10d7b19a485 100644
--- a/drivers/staging/hv/VersionInfo.h
+++ b/drivers/staging/hv/VersionInfo.h
@@ -24,8 +24,24 @@
#ifndef __HV_VERSION_INFO
#define __HV_VERSION_INFO
-static const char VersionDate[] = __DATE__;
-static const char VersionTime[] = __TIME__;
-static const char VersionDesc[] = "Version 2.0";
+/*
+ * We use the same version numbering for all Hyper-V modules.
+ *
+ * Definition of versioning is as follows;
+ *
+ * Major Number Changes for these scenarios;
+ * 1. When a new version of Windows Hyper-V
+ * is released.
+ * 2. A Major change has occurred in the
+ * Linux IC's.
+ * (For example the merge for the first time
+ * into the kernel) Every time the Major Number
+ * changes, the Revision number is reset to 0.
+ * Minor Number Changes when new functionality is added
+ * to the Linux IC's that is not a bug fix.
+ *
+ */
+#define HV_DRV_VERSION "3.0"
+
#endif
diff --git a/drivers/staging/hv/Vmbus.c b/drivers/staging/hv/Vmbus.c
index 35a023e9f9d..3d0a240ed66 100644
--- a/drivers/staging/hv/Vmbus.c
+++ b/drivers/staging/hv/Vmbus.c
@@ -273,10 +273,8 @@ int VmbusInitialize(struct hv_driver *drv)
DPRINT_ENTER(VMBUS);
- DPRINT_INFO(VMBUS, "+++++++ Build Date=%s %s +++++++",
- VersionDate, VersionTime);
- DPRINT_INFO(VMBUS, "+++++++ Build Description=%s +++++++",
- VersionDesc);
+ DPRINT_INFO(VMBUS, "+++++++ HV Driver version = %s +++++++",
+ HV_DRV_VERSION);
DPRINT_INFO(VMBUS, "+++++++ Vmbus supported version = %d +++++++",
VMBUS_REVISION_NUMBER);
DPRINT_INFO(VMBUS, "+++++++ Vmbus using SINT %d +++++++",
diff --git a/drivers/staging/hv/blkvsc_drv.c b/drivers/staging/hv/blkvsc_drv.c
index 45d908114d1..abeac12c093 100644
--- a/drivers/staging/hv/blkvsc_drv.c
+++ b/drivers/staging/hv/blkvsc_drv.c
@@ -31,6 +31,7 @@
#include <scsi/scsi_dbg.h>
#include "osd.h"
#include "logging.h"
+#include "VersionInfo.h"
#include "vmbus.h"
#include "StorVscApi.h"
@@ -92,7 +93,7 @@ struct blkvsc_request {
/* Per device structure */
struct block_device_context {
/* point back to our device context */
- struct device_context *device_ctx;
+ struct vm_device *device_ctx;
struct kmem_cache *request_pool;
spinlock_t lock;
struct gendisk *gd;
@@ -254,7 +255,7 @@ static int blkvsc_probe(struct device *device)
(struct blkvsc_driver_context *)driver_ctx;
struct storvsc_driver_object *storvsc_drv_obj =
&blkvsc_drv_ctx->drv_obj;
- struct device_context *device_ctx = device_to_device_context(device);
+ struct vm_device *device_ctx = device_to_vm_device(device);
struct hv_device *device_obj = &device_ctx->device_obj;
struct block_device_context *blkdev = NULL;
@@ -742,7 +743,7 @@ static int blkvsc_remove(struct device *device)
(struct blkvsc_driver_context *)driver_ctx;
struct storvsc_driver_object *storvsc_drv_obj =
&blkvsc_drv_ctx->drv_obj;
- struct device_context *device_ctx = device_to_device_context(device);
+ struct vm_device *device_ctx = device_to_vm_device(device);
struct hv_device *device_obj = &device_ctx->device_obj;
struct block_device_context *blkdev = dev_get_drvdata(device);
unsigned long flags;
@@ -862,7 +863,7 @@ static int blkvsc_submit_request(struct blkvsc_request *blkvsc_req,
void (*request_completion)(struct hv_storvsc_request *))
{
struct block_device_context *blkdev = blkvsc_req->dev;
- struct device_context *device_ctx = blkdev->device_ctx;
+ struct vm_device *device_ctx = blkdev->device_ctx;
struct driver_context *driver_ctx =
driver_to_driver_context(device_ctx->device.driver);
struct blkvsc_driver_context *blkvsc_drv_ctx =
@@ -1504,6 +1505,7 @@ static void __exit blkvsc_exit(void)
}
MODULE_LICENSE("GPL");
+MODULE_VERSION(HV_DRV_VERSION);
module_param(blkvsc_ringbuffer_size, int, S_IRUGO);
module_init(blkvsc_init);
module_exit(blkvsc_exit);
diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c
index 0d7459e2d03..1af3dcbafd6 100644
--- a/drivers/staging/hv/netvsc_drv.c
+++ b/drivers/staging/hv/netvsc_drv.c
@@ -35,14 +35,13 @@
#include <net/pkt_sched.h>
#include "osd.h"
#include "logging.h"
+#include "VersionInfo.h"
#include "vmbus.h"
#include "NetVscApi.h"
-MODULE_LICENSE("GPL");
-
struct net_device_context {
/* point back to our device context */
- struct device_context *device_ctx;
+ struct vm_device *device_ctx;
struct net_device_stats stats;
};
@@ -72,11 +71,6 @@ static void netvsc_set_multicast_list(struct net_device *net)
static int netvsc_open(struct net_device *net)
{
struct net_device_context *net_device_ctx = netdev_priv(net);
- struct driver_context *driver_ctx =
- driver_to_driver_context(net_device_ctx->device_ctx->device.driver);
- struct netvsc_driver_context *net_drv_ctx =
- (struct netvsc_driver_context *)driver_ctx;
- struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
struct hv_device *device_obj = &net_device_ctx->device_ctx->device_obj;
int ret = 0;
@@ -87,7 +81,7 @@ static int netvsc_open(struct net_device *net)
sizeof(struct net_device_stats));
/* Open up the device */
- ret = net_drv_obj->OnOpen(device_obj);
+ ret = RndisFilterOnOpen(device_obj);
if (ret != 0) {
DPRINT_ERR(NETVSC_DRV,
"unable to open device (ret %d).", ret);
@@ -106,11 +100,6 @@ static int netvsc_open(struct net_device *net)
static int netvsc_close(struct net_device *net)
{
struct net_device_context *net_device_ctx = netdev_priv(net);
- struct driver_context *driver_ctx =
- driver_to_driver_context(net_device_ctx->device_ctx->device.driver);
- struct netvsc_driver_context *net_drv_ctx =
- (struct netvsc_driver_context *)driver_ctx;
- struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
struct hv_device *device_obj = &net_device_ctx->device_ctx->device_obj;
int ret;
@@ -118,7 +107,7 @@ static int netvsc_close(struct net_device *net)
netif_stop_queue(net);
- ret = net_drv_obj->OnClose(device_obj);
+ ret = RndisFilterOnClose(device_obj);
if (ret != 0)
DPRINT_ERR(NETVSC_DRV, "unable to close device (ret %d).", ret);
@@ -282,7 +271,7 @@ retry_send:
static void netvsc_linkstatus_callback(struct hv_device *device_obj,
unsigned int status)
{
- struct device_context *device_ctx = to_device_context(device_obj);
+ struct vm_device *device_ctx = to_vm_device(device_obj);
struct net_device *net = dev_get_drvdata(&device_ctx->device);
DPRINT_ENTER(NETVSC_DRV);
@@ -309,7 +298,7 @@ static void netvsc_linkstatus_callback(struct hv_device *device_obj,
static int netvsc_recv_callback(struct hv_device *device_obj,
struct hv_netvsc_packet *packet)
{
- struct device_context *device_ctx = to_device_context(device_obj);
+ struct vm_device *device_ctx = to_vm_device(device_obj);
struct net_device *net = dev_get_drvdata(&device_ctx->device);
struct net_device_context *net_device_ctx;
struct sk_buff *skb;
@@ -401,7 +390,7 @@ static int netvsc_probe(struct device *device)
struct netvsc_driver_context *net_drv_ctx =
(struct netvsc_driver_context *)driver_ctx;
struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
- struct device_context *device_ctx = device_to_device_context(device);
+ struct vm_device *device_ctx = device_to_vm_device(device);
struct hv_device *device_obj = &device_ctx->device_obj;
struct net_device *net = NULL;
struct net_device_context *net_device_ctx;
@@ -473,7 +462,7 @@ static int netvsc_remove(struct device *device)
struct netvsc_driver_context *net_drv_ctx =
(struct netvsc_driver_context *)driver_ctx;
struct netvsc_driver *net_drv_obj = &net_drv_ctx->drv_obj;
- struct device_context *device_ctx = device_to_device_context(device);
+ struct vm_device *device_ctx = device_to_vm_device(device);
struct net_device *net = dev_get_drvdata(&device_ctx->device);
struct hv_device *device_obj = &device_ctx->device_obj;
int ret;
@@ -613,6 +602,8 @@ static void __exit netvsc_exit(void)
DPRINT_EXIT(NETVSC_DRV);
}
+MODULE_LICENSE("GPL");
+MODULE_VERSION(HV_DRV_VERSION);
module_param(netvsc_ringbuffer_size, int, S_IRUGO);
module_init(netvsc_init);
diff --git a/drivers/staging/hv/storvsc_drv.c b/drivers/staging/hv/storvsc_drv.c
index d49dc21d4cb..3988f4bec1c 100644
--- a/drivers/staging/hv/storvsc_drv.c
+++ b/drivers/staging/hv/storvsc_drv.c
@@ -32,6 +32,7 @@
#include <scsi/scsi_dbg.h>
#include "osd.h"
#include "logging.h"
+#include "VersionInfo.h"
#include "vmbus.h"
#include "StorVscApi.h"
@@ -39,10 +40,8 @@
struct host_device_context {
/* must be 1st field
* FIXME this is a bug */
- struct work_struct host_rescan_work;
-
/* point back to our device context */
- struct device_context *device_ctx;
+ struct vm_device *device_ctx;
struct kmem_cache *request_pool;
unsigned int port;
unsigned char path;
@@ -77,8 +76,6 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
static int storvsc_device_alloc(struct scsi_device *);
static int storvsc_device_configure(struct scsi_device *);
static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd);
-static void storvsc_host_rescan_callback(struct work_struct *work);
-static void storvsc_host_rescan(struct hv_device *device_obj);
static int storvsc_remove(struct device *dev);
static struct scatterlist *create_bounce_buffer(struct scatterlist *sgl,
@@ -94,8 +91,6 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl,
struct scatterlist *bounce_sgl,
unsigned int orig_sgl_count);
-static int storvsc_report_luns(struct scsi_device *sdev, unsigned int luns[],
- unsigned int *lun_count);
static int storvsc_get_chs(struct scsi_device *sdev, struct block_device *bdev,
sector_t capacity, int *info);
@@ -148,7 +143,6 @@ static int storvsc_drv_init(int (*drv_init)(struct hv_driver *drv))
vmbus_get_interface(&storvsc_drv_obj->Base.VmbusChannelInterface);
storvsc_drv_obj->RingBufferSize = storvsc_ringbuffer_size;
- storvsc_drv_obj->OnHostRescan = storvsc_host_rescan;
/* Callback to client driver to complete the initialization */
drv_init(&storvsc_drv_obj->Base);
@@ -240,7 +234,7 @@ static int storvsc_probe(struct device *device)
(struct storvsc_driver_context *)driver_ctx;
struct storvsc_driver_object *storvsc_drv_obj =
&storvsc_drv_ctx->drv_obj;
- struct device_context *device_ctx = device_to_device_context(device);
+ struct vm_device *device_ctx = device_to_vm_device(device);
struct hv_device *device_obj = &device_ctx->device_obj;
struct Scsi_Host *host;
struct host_device_context *host_device_ctx;
@@ -266,9 +260,6 @@ static int storvsc_probe(struct device *device)
host_device_ctx->port = host->host_no;
host_device_ctx->device_ctx = device_ctx;
- INIT_WORK(&host_device_ctx->host_rescan_work,
- storvsc_host_rescan_callback);
-
host_device_ctx->request_pool =
kmem_cache_create(dev_name(&device_ctx->device),
sizeof(struct storvsc_cmd_request) +
@@ -339,7 +330,7 @@ static int storvsc_remove(struct device *device)
(struct storvsc_driver_context *)driver_ctx;
struct storvsc_driver_object *storvsc_drv_obj =
&storvsc_drv_ctx->drv_obj;
- struct device_context *device_ctx = device_to_device_context(device);
+ struct vm_device *device_ctx = device_to_vm_device(device);
struct hv_device *device_obj = &device_ctx->device_obj;
struct Scsi_Host *host = dev_get_drvdata(device);
struct host_device_context *host_device_ctx =
@@ -640,7 +631,7 @@ static int storvsc_queuecommand(struct scsi_cmnd *scmnd,
int ret;
struct host_device_context *host_device_ctx =
(struct host_device_context *)scmnd->device->host->hostdata;
- struct device_context *device_ctx = host_device_ctx->device_ctx;
+ struct vm_device *device_ctx = host_device_ctx->device_ctx;
struct driver_context *driver_ctx =
driver_to_driver_context(device_ctx->device.driver);
struct storvsc_driver_context *storvsc_drv_ctx =
@@ -879,14 +870,7 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
int ret;
struct host_device_context *host_device_ctx =
(struct host_device_context *)scmnd->device->host->hostdata;
- struct device_context *device_ctx = host_device_ctx->device_ctx;
- struct driver_context *driver_ctx =
- driver_to_driver_context(device_ctx->device.driver);
- struct storvsc_driver_context *storvsc_drv_ctx =
- (struct storvsc_driver_context *)driver_ctx;
-
- struct storvsc_driver_object *storvsc_drv_obj =
- &storvsc_drv_ctx->drv_obj;
+ struct vm_device *device_ctx = host_device_ctx->device_ctx;
DPRINT_ENTER(STORVSC_DRV);
@@ -894,8 +878,7 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
scmnd->device, &device_ctx->device_obj);
/* Invokes the vsc to reset the host/bus */
- ASSERT(storvsc_drv_obj->OnHostReset);
- ret = storvsc_drv_obj->OnHostReset(&device_ctx->device_obj);
+ ret = StorVscOnHostReset(&device_ctx->device_obj);
if (ret != 0) {
DPRINT_EXIT(STORVSC_DRV);
return ret;
@@ -909,201 +892,6 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd)
return ret;
}
-/**
- * storvsc_host_rescan - Rescan the scsi HBA
- */
-static void storvsc_host_rescan_callback(struct work_struct *work)
-{
- struct hv_device *device_obj =
- &((struct host_device_context *)work)->device_ctx->device_obj;
- struct device_context *device_ctx = to_device_context(device_obj);
- struct Scsi_Host *host = dev_get_drvdata(&device_ctx->device);
- struct scsi_device *sdev;
- struct host_device_context *host_device_ctx;
- struct scsi_device **sdevs_remove_list;
- unsigned int sdevs_count = 0;
- unsigned int found;
- unsigned int i;
- unsigned int lun_count = 0;
- unsigned int *lun_list;
-
- DPRINT_ENTER(STORVSC_DRV);
-
- host_device_ctx = (struct host_device_context *)host->hostdata;
- lun_list = kcalloc(STORVSC_MAX_LUNS_PER_TARGET, sizeof(unsigned int),
- GFP_ATOMIC);
- if (!lun_list) {
- DPRINT_ERR(STORVSC_DRV, "unable to allocate lun list");
- return;
- }
-
- sdevs_remove_list = kcalloc(STORVSC_MAX_LUNS_PER_TARGET,
- sizeof(void *), GFP_ATOMIC);
- if (!sdevs_remove_list) {
- kfree(lun_list);
- DPRINT_ERR(STORVSC_DRV, "unable to allocate lun remove list");
- return;
- }
-
- DPRINT_INFO(STORVSC_DRV, "rescanning host for new scsi devices...");
-
- /* Rescan for new device */
- scsi_scan_target(&host->shost_gendev, host_device_ctx->path,
- host_device_ctx->target, SCAN_WILD_CARD, 1);
-
- DPRINT_INFO(STORVSC_DRV, "rescanning host for removed scsi device...");
-
- /* Use the 1st device to send the report luns cmd */
- shost_for_each_device(sdev, host) {
- lun_count = STORVSC_MAX_LUNS_PER_TARGET;
- storvsc_report_luns(sdev, lun_list, &lun_count);
-
- DPRINT_INFO(STORVSC_DRV,
- "report luns on scsi device (%p) found %u luns ",
- sdev, lun_count);
- DPRINT_INFO(STORVSC_DRV,
- "existing luns on scsi device (%p) host (%d)",
- sdev, host->host_no);
-
- scsi_device_put(sdev);
- break;
- }
-
- for (i = 0; i < lun_count; i++)
- DPRINT_INFO(STORVSC_DRV, "%d) lun %u", i, lun_list[i]);
-
- /* Rescan for devices that may have been removed.
- * We do not have to worry that new devices may have been added since
- * this callback is serialized by the workqueue ie add/remove are done
- * here.
- */
- shost_for_each_device(sdev, host) {
- /* See if this device is still here */
- found = 0;
- for (i = 0; i < lun_count; i++) {
- if (sdev->lun == lun_list[i]) {
- found = 1;
- break;
- }
- }
- if (!found) {
- DPRINT_INFO(STORVSC_DRV, "lun (%u) does not exists",
- sdev->lun);
- sdevs_remove_list[sdevs_count++] = sdev;
- }
- }
-
- /* Now remove the devices */
- for (i = 0; i < sdevs_count; i++) {
- DPRINT_INFO(STORVSC_DRV,
- "removing scsi device (%p) lun (%u)...",
- sdevs_remove_list[i], sdevs_remove_list[i]->lun);
-
- /* make sure it is not removed from underneath us */
- if (!scsi_device_get(sdevs_remove_list[i])) {
- scsi_remove_device(sdevs_remove_list[i]);
- scsi_device_put(sdevs_remove_list[i]);
- }
- }
-
- DPRINT_INFO(STORVSC_DRV, "rescan completed on dev obj (%p) "
- "target (%u) bus (%u)", device_obj,
- host_device_ctx->target, host_device_ctx->path);
-
- kfree(lun_list);
- kfree(sdevs_remove_list);
-
- DPRINT_EXIT(STORVSC_DRV);
-}
-
-static int storvsc_report_luns(struct scsi_device *sdev, unsigned int luns[],
- unsigned int *lun_count)
-{
- int i, j;
- unsigned int lun = 0;
- unsigned int num_luns;
- int result;
- unsigned char *data;
- struct scsi_sense_hdr sshdr;
- unsigned char cmd[16] = {0};
- /* Add 1 to cover the report_lun header */
- unsigned int report_len = 8 * (STORVSC_MAX_LUNS_PER_TARGET+1);
- unsigned long long *report_luns;
- const unsigned int in_lun_count = *lun_count;
-
- *lun_count = 0;
-
- report_luns = kzalloc(report_len, GFP_ATOMIC);
- if (!report_luns)
- return -ENOMEM;
-
- cmd[0] = REPORT_LUNS;
-
- /* cmd length */
- *(unsigned int *)&cmd[6] = cpu_to_be32(report_len);
-
- result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE,
- (unsigned char *)report_luns, report_len,
- &sshdr, 30 * HZ, 3, NULL);
- if (result != 0) {
- kfree(report_luns);
- return -EBUSY;
- }
-
- /* get the length from the first four bytes */
- report_len = be32_to_cpu(*(unsigned int *)&report_luns[0]);
-
- num_luns = (report_len / sizeof(unsigned long long));
- if (num_luns > in_lun_count) {
- kfree(report_luns);
- return -EINVAL;
- }
-
- *lun_count = num_luns;
-
- DPRINT_DBG(STORVSC_DRV,
- "report luns on scsi device (%p) found %u luns ",
- sdev, num_luns);
-
- /* lun id starts at 1 */
- for (i = 1; i < num_luns + 1; i++) {
- lun = 0;
- data = (unsigned char *)&report_luns[i];
- for (j = 0; j < sizeof(lun); j += 2) {
- lun = lun | (((data[j] << 8) | data[j + 1]) <<
- (j * 8));
- }
-
- luns[i-1] = lun;
- }
-
- kfree(report_luns);
- return 0;
-}
-
-static void storvsc_host_rescan(struct hv_device *device_obj)
-{
- struct device_context *device_ctx = to_device_context(device_obj);
- struct Scsi_Host *host = dev_get_drvdata(&device_ctx->device);
- struct host_device_context *host_device_ctx;
-
- DPRINT_ENTER(STORVSC_DRV);
-
- host_device_ctx = (struct host_device_context *)host->hostdata;
-
- DPRINT_INFO(STORVSC_DRV, "initiating rescan on dev obj (%p) "
- "target (%u) bus (%u)...", device_obj,
- host_device_ctx->target, host_device_ctx->path);
-
- /*
- * We need to queue this since the scanning may block and the caller
- * may be in an intr context
- */
- /* scsi_queue_work(host, &host_device_ctx->host_rescan_work); */
- schedule_work(&host_device_ctx->host_rescan_work);
- DPRINT_EXIT(STORVSC_DRV);
-}
-
static int storvsc_get_chs(struct scsi_device *sdev, struct block_device * bdev,
sector_t capacity, int *info)
{
@@ -1203,6 +991,7 @@ static void __exit storvsc_exit(void)
}
MODULE_LICENSE("GPL");
+MODULE_VERSION(HV_DRV_VERSION);
module_param(storvsc_ringbuffer_size, int, S_IRUGO);
module_init(storvsc_init);
module_exit(storvsc_exit);
diff --git a/drivers/staging/hv/vmbus.h b/drivers/staging/hv/vmbus.h
index ae0a896eb39..6404b8424be 100644
--- a/drivers/staging/hv/vmbus.h
+++ b/drivers/staging/hv/vmbus.h
@@ -43,23 +43,23 @@ struct driver_context {
void (*shutdown)(struct device *);
};
-struct device_context {
+struct vm_device {
struct work_struct probe_failed_work_item;
struct hv_guid class_id;
struct hv_guid device_id;
int probe_error;
- struct device device;
struct hv_device device_obj;
+ struct device device;
};
-static inline struct device_context *to_device_context(struct hv_device *d)
+static inline struct vm_device *to_vm_device(struct hv_device *d)
{
- return container_of(d, struct device_context, device_obj);
+ return container_of(d, struct vm_device, device_obj);
}
-static inline struct device_context *device_to_device_context(struct device *d)
+static inline struct vm_device *device_to_vm_device(struct device *d)
{
- return container_of(d, struct device_context, device);
+ return container_of(d, struct vm_device, device);
}
static inline struct driver_context *driver_to_driver_context(struct device_driver *d)
diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
index 894eecfc63c..2c906195b9c 100644
--- a/drivers/staging/hv/vmbus_drv.c
+++ b/drivers/staging/hv/vmbus_drv.c
@@ -24,6 +24,9 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/sysctl.h>
+#include <linux/pci.h>
+#include <linux/dmi.h>
+#include "VersionInfo.h"
#include "osd.h"
#include "logging.h"
#include "vmbus.h"
@@ -47,7 +50,7 @@ struct vmbus_driver_context {
struct tasklet_struct event_dpc;
/* The bus root device */
- struct device_context device_ctx;
+ struct vm_device device_ctx;
};
static int vmbus_match(struct device *device, struct device_driver *driver);
@@ -135,7 +138,7 @@ static ssize_t vmbus_show_device_attr(struct device *dev,
struct device_attribute *dev_attr,
char *buf)
{
- struct device_context *device_ctx = device_to_device_context(dev);
+ struct vm_device *device_ctx = device_to_vm_device(dev);
struct hv_device_info device_info;
memset(&device_info, 0, sizeof(struct hv_device_info));
@@ -245,7 +248,7 @@ static int vmbus_bus_init(int (*drv_init)(struct hv_driver *drv))
{
struct vmbus_driver_context *vmbus_drv_ctx = &g_vmbus_drv;
struct vmbus_driver *vmbus_drv_obj = &g_vmbus_drv.drv_obj;
- struct device_context *dev_ctx = &g_vmbus_drv.device_ctx;
+ struct vm_device *dev_ctx = &g_vmbus_drv.device_ctx;
int ret;
unsigned int vector;
@@ -307,7 +310,7 @@ static int vmbus_bus_init(int (*drv_init)(struct hv_driver *drv))
DPRINT_INFO(VMBUS_DRV, "irq 0x%x vector 0x%x", vmbus_irq, vector);
/* Call to bus driver to add the root device */
- memset(dev_ctx, 0, sizeof(struct device_context));
+ memset(dev_ctx, 0, sizeof(struct vm_device));
ret = vmbus_drv_obj->Base.OnDeviceAdd(&dev_ctx->device_obj, &vector);
if (ret != 0) {
@@ -368,7 +371,7 @@ static void vmbus_bus_exit(void)
struct vmbus_driver *vmbus_drv_obj = &g_vmbus_drv.drv_obj;
struct vmbus_driver_context *vmbus_drv_ctx = &g_vmbus_drv;
- struct device_context *dev_ctx = &g_vmbus_drv.device_ctx;
+ struct vm_device *dev_ctx = &g_vmbus_drv.device_ctx;
DPRINT_ENTER(VMBUS_DRV);
@@ -471,13 +474,13 @@ static struct hv_device *vmbus_child_device_create(struct hv_guid *type,
struct hv_guid *instance,
void *context)
{
- struct device_context *child_device_ctx;
+ struct vm_device *child_device_ctx;
struct hv_device *child_device_obj;
DPRINT_ENTER(VMBUS_DRV);
/* Allocate the new child device */
- child_device_ctx = kzalloc(sizeof(struct device_context), GFP_KERNEL);
+ child_device_ctx = kzalloc(sizeof(struct vm_device), GFP_KERNEL);
if (!child_device_ctx) {
DPRINT_ERR(VMBUS_DRV,
"unable to allocate device_context for child device");
@@ -526,10 +529,10 @@ static int vmbus_child_device_register(struct hv_device *root_device_obj,
struct hv_device *child_device_obj)
{
int ret = 0;
- struct device_context *root_device_ctx =
- to_device_context(root_device_obj);
- struct device_context *child_device_ctx =
- to_device_context(child_device_obj);
+ struct vm_device *root_device_ctx =
+ to_vm_device(root_device_obj);
+ struct vm_device *child_device_ctx =
+ to_vm_device(child_device_obj);
static atomic_t device_num = ATOMIC_INIT(0);
DPRINT_ENTER(VMBUS_DRV);
@@ -572,7 +575,7 @@ static int vmbus_child_device_register(struct hv_device *root_device_obj,
*/
static void vmbus_child_device_unregister(struct hv_device *device_obj)
{
- struct device_context *device_ctx = to_device_context(device_obj);
+ struct vm_device *device_ctx = to_vm_device(device_obj);
DPRINT_ENTER(VMBUS_DRV);
@@ -610,7 +613,7 @@ static void vmbus_child_device_destroy(struct hv_device *device_obj)
*/
static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
{
- struct device_context *device_ctx = device_to_device_context(device);
+ struct vm_device *device_ctx = device_to_vm_device(device);
int ret;
DPRINT_ENTER(VMBUS_DRV);
@@ -687,7 +690,7 @@ static int vmbus_match(struct device *device, struct device_driver *driver)
{
int match = 0;
struct driver_context *driver_ctx = driver_to_driver_context(driver);
- struct device_context *device_ctx = device_to_device_context(device);
+ struct vm_device *device_ctx = device_to_vm_device(device);
DPRINT_ENTER(VMBUS_DRV);
@@ -724,7 +727,7 @@ static int vmbus_match(struct device *device, struct device_driver *driver)
*/
static void vmbus_probe_failed_cb(struct work_struct *context)
{
- struct device_context *device_ctx = (struct device_context *)context;
+ struct vm_device *device_ctx = (struct vm_device *)context;
DPRINT_ENTER(VMBUS_DRV);
@@ -746,8 +749,8 @@ static int vmbus_probe(struct device *child_device)
int ret = 0;
struct driver_context *driver_ctx =
driver_to_driver_context(child_device->driver);
- struct device_context *device_ctx =
- device_to_device_context(child_device);
+ struct vm_device *device_ctx =
+ device_to_vm_device(child_device);
DPRINT_ENTER(VMBUS_DRV);
@@ -871,7 +874,7 @@ static void vmbus_bus_release(struct device *device)
*/
static void vmbus_device_release(struct device *device)
{
- struct device_context *device_ctx = device_to_device_context(device);
+ struct vm_device *device_ctx = device_to_vm_device(device);
DPRINT_ENTER(VMBUS_DRV);
@@ -946,6 +949,19 @@ static irqreturn_t vmbus_isr(int irq, void *dev_id)
}
}
+static struct dmi_system_id __initdata microsoft_hv_dmi_table[] = {
+ {
+ .ident = "Hyper-V",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"),
+ DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"),
+ },
+ },
+ { },
+};
+MODULE_DEVICE_TABLE(dmi, microsoft_hv_dmi_table);
+
static int __init vmbus_init(void)
{
int ret = 0;
@@ -957,6 +973,9 @@ static int __init vmbus_init(void)
vmbus_loglevel, HIWORD(vmbus_loglevel), LOWORD(vmbus_loglevel));
/* Todo: it is used for loglevel, to be ported to new kernel. */
+ if (!dmi_check_system(microsoft_hv_dmi_table))
+ return -ENODEV;
+
ret = vmbus_bus_init(VmbusInitialize);
DPRINT_EXIT(VMBUS_DRV);
@@ -973,7 +992,20 @@ static void __exit vmbus_exit(void)
return;
}
+/*
+ * We use a PCI table to determine if we should autoload this driver This is
+ * needed by distro tools to determine if the hyperv drivers should be
+ * installed and/or configured. We don't do anything else with the table, but
+ * it needs to be present.
+ */
+const static struct pci_device_id microsoft_hv_pci_table[] = {
+ { PCI_DEVICE(0x1414, 0x5353) }, /* VGA compatible controller */
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, microsoft_hv_pci_table);
+
MODULE_LICENSE("GPL");
+MODULE_VERSION(HV_DRV_VERSION);
module_param(vmbus_irq, int, S_IRUGO);
module_param(vmbus_loglevel, int, S_IRUGO);
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c
index 768f44894d0..b456dfc8fe2 100644
--- a/drivers/staging/iio/industrialio-core.c
+++ b/drivers/staging/iio/industrialio-core.c
@@ -79,11 +79,14 @@ EXPORT_SYMBOL(__iio_change_event);
/* Does anyone care? */
mutex_lock(&ev_int->event_list_lock);
if (test_bit(IIO_BUSY_BIT_POS, &ev_int->handler.flags)) {
- if (ev_int->current_events == ev_int->max_events)
+ if (ev_int->current_events == ev_int->max_events) {
+ mutex_unlock(&ev_int->event_list_lock);
return 0;
+ }
ev = kmalloc(sizeof(*ev), GFP_KERNEL);
if (ev == NULL) {
ret = -ENOMEM;
+ mutex_unlock(&ev_int->event_list_lock);
goto error_ret;
}
ev->ev.id = ev_code;
@@ -115,7 +118,7 @@ int iio_push_event(struct iio_dev *dev_info,
EXPORT_SYMBOL(iio_push_event);
/* Generic interrupt line interrupt handler */
-irqreturn_t iio_interrupt_handler(int irq, void *_int_info)
+static irqreturn_t iio_interrupt_handler(int irq, void *_int_info)
{
struct iio_interrupt *int_info = _int_info;
struct iio_dev *dev_info = int_info->dev_info;
@@ -249,10 +252,10 @@ void iio_remove_event_from_list(struct iio_event_handler_list *el,
}
EXPORT_SYMBOL(iio_remove_event_from_list);
-ssize_t iio_event_chrdev_read(struct file *filep,
- char *buf,
- size_t count,
- loff_t *f_ps)
+static ssize_t iio_event_chrdev_read(struct file *filep,
+ char __user *buf,
+ size_t count,
+ loff_t *f_ps)
{
struct iio_event_interface *ev_int = filep->private_data;
struct iio_detected_event_list *el;
@@ -289,16 +292,16 @@ ssize_t iio_event_chrdev_read(struct file *filep,
mutex_unlock(&ev_int->event_list_lock);
/*
* Possible concurency issue if an update of this event is on its way
- * through. May lead to new even being removed whilst the reported event
- * was the unescalated event. In typical use case this is not a problem
- * as userspace will say read half the buffer due to a 50% full event
- * which would make the correct 100% full incorrect anyway.
+ * through. May lead to new event being removed whilst the reported
+ * event was the unescalated event. In typical use case this is not a
+ * problem as userspace will say read half the buffer due to a 50%
+ * full event which would make the correct 100% full incorrect anyway.
*/
- spin_lock(&el->shared_pointer->lock);
- if (el->shared_pointer)
+ if (el->shared_pointer) {
+ spin_lock(&el->shared_pointer->lock);
(el->shared_pointer->ev_p) = NULL;
- spin_unlock(&el->shared_pointer->lock);
-
+ spin_unlock(&el->shared_pointer->lock);
+ }
kfree(el);
return len;
@@ -310,7 +313,7 @@ error_ret:
return ret;
}
-int iio_event_chrdev_release(struct inode *inode, struct file *filep)
+static int iio_event_chrdev_release(struct inode *inode, struct file *filep)
{
struct iio_handler *hand = iio_cdev_to_handler(inode->i_cdev);
struct iio_event_interface *ev_int = hand->private;
@@ -332,7 +335,7 @@ int iio_event_chrdev_release(struct inode *inode, struct file *filep)
return 0;
}
-int iio_event_chrdev_open(struct inode *inode, struct file *filep)
+static int iio_event_chrdev_open(struct inode *inode, struct file *filep)
{
struct iio_handler *hand = iio_cdev_to_handler(inode->i_cdev);
struct iio_event_interface *ev_int = hand->private;
diff --git a/drivers/staging/iio/ring_generic.h b/drivers/staging/iio/ring_generic.h
index 93b91b28a02..09044adf732 100644
--- a/drivers/staging/iio/ring_generic.h
+++ b/drivers/staging/iio/ring_generic.h
@@ -146,8 +146,7 @@ static inline void __iio_init_ring_buffer(struct iio_ring_buffer *ring,
ring->length = length;
ring->loopcount = 0;
ring->shared_ev_pointer.ev_p = 0;
- ring->shared_ev_pointer.lock =
- __SPIN_LOCK_UNLOCKED(ring->shared_ev_pointer->loc);
+ spin_lock_init(&ring->shared_ev_pointer.lock);
}
/**
diff --git a/drivers/staging/iio/ring_sw.c b/drivers/staging/iio/ring_sw.c
index 359ff9208f3..6f7f4d5a93f 100644
--- a/drivers/staging/iio/ring_sw.c
+++ b/drivers/staging/iio/ring_sw.c
@@ -8,7 +8,6 @@
*/
#include <linux/kernel.h>
-#include <linux/device.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/workqueue.h>
@@ -21,7 +20,7 @@ static inline int __iio_init_sw_ring_buffer(struct iio_sw_ring_buffer *ring,
return -EINVAL;
__iio_init_ring_buffer(&ring->buf, bytes_per_datum, length);
- ring->use_lock = __SPIN_LOCK_UNLOCKED((ring)->use_lock);
+ spin_lock_init(&ring->use_lock);
ring->data = kmalloc(length*ring->buf.bpd, GFP_KERNEL);
ring->read_p = 0;
ring->write_p = 0;
diff --git a/drivers/staging/iio/trigger_consumer.h b/drivers/staging/iio/trigger_consumer.h
index a02d70b0d24..9d52d963777 100644
--- a/drivers/staging/iio/trigger_consumer.h
+++ b/drivers/staging/iio/trigger_consumer.h
@@ -27,7 +27,7 @@ int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info);
* iio_device_register_trigger_consumer() - set up an iio_dev to use triggers
* @dev_info: iio_dev associated with the device that will consume the trigger
**/
-int iio_device_register_trigger_consumer(struct iio_dev *dev_info)
+static int iio_device_register_trigger_consumer(struct iio_dev *dev_info)
{
return 0;
};
@@ -36,7 +36,7 @@ int iio_device_register_trigger_consumer(struct iio_dev *dev_info)
* iio_device_unregister_trigger_consumer() - reverse the registration process
* @dev_info: iio_dev associated with the device that consumed the trigger
**/
-int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info)
+static int iio_device_unregister_trigger_consumer(struct iio_dev *dev_info)
{
return 0;
};
diff --git a/drivers/staging/line6/driver.c b/drivers/staging/line6/driver.c
index e4078a92d39..0392a4bc8cc 100644
--- a/drivers/staging/line6/driver.c
+++ b/drivers/staging/line6/driver.c
@@ -33,7 +33,7 @@
/* table of devices that work with this driver */
-static struct usb_device_id line6_id_table[] = {
+static const struct usb_device_id line6_id_table[] = {
{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXT) },
{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXTLIVE) },
{ USB_DEVICE(LINE6_VENDOR_ID, LINE6_DEVID_BASSPODXTPRO) },
diff --git a/drivers/staging/line6/variax.c b/drivers/staging/line6/variax.c
index 48d834b0fa1..58fef82c247 100644
--- a/drivers/staging/line6/variax.c
+++ b/drivers/staging/line6/variax.c
@@ -254,7 +254,7 @@ static ssize_t variax_set_active(struct device *dev,
if (ret)
return ret;
- variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = value ? 1: 0;
+ variax->buffer_activate[VARIAX_OFFSET_ACTIVATE] = value ? 1 : 0;
line6_send_raw_message_async(&variax->line6, variax->buffer_activate,
sizeof(variax_activate));
return count;
diff --git a/drivers/staging/mimio/Kconfig b/drivers/staging/mimio/Kconfig
deleted file mode 100644
index 505dcb27579..00000000000
--- a/drivers/staging/mimio/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-config INPUT_MIMIO
- tristate "Mimio Xi interactive whiteboard support"
- depends on USB && INPUT
- default N
- help
- Say Y here if you want to use a Mimio Xi interactive
- whiteboard device.
-
- To compile this driver as a module, choose M here: the
- module will be called mimio.
diff --git a/drivers/staging/mimio/Makefile b/drivers/staging/mimio/Makefile
deleted file mode 100644
index 77807ee0450..00000000000
--- a/drivers/staging/mimio/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_INPUT_MIMIO) += mimio.o
diff --git a/drivers/staging/mimio/mimio.c b/drivers/staging/mimio/mimio.c
deleted file mode 100644
index 1ba8103f500..00000000000
--- a/drivers/staging/mimio/mimio.c
+++ /dev/null
@@ -1,914 +0,0 @@
-/*
- * Hardware event => input event mapping:
- *
- *
- *
- input.h:#define BTN_TOOL_PEN 0x140 black
- input.h:#define BTN_TOOL_RUBBER 0x141 blue
- input.h:#define BTN_TOOL_BRUSH 0x142 green
- input.h:#define BTN_TOOL_PENCIL 0x143 red
- input.h:#define BTN_TOOL_AIRBRUSH 0x144 eraser
- input.h:#define BTN_TOOL_FINGER 0x145 small eraser
- input.h:#define BTN_TOOL_MOUSE 0x146 mimio interactive
- input.h:#define BTN_TOOL_LENS 0x147 mimio interactive but1
- input.h:#define LOCALBTN_TOOL_EXTRA1 0x14a mimio interactive but2 == BTN_TOUCH
- input.h:#define LOCALBTN_TOOL_EXTRA2 0x14b mimio extra pens (orange, brown, yellow, purple) == BTN_STYLUS
- input.h:#define LOCALBTN_TOOL_EXTRA3 0x14c unused == BTN_STYLUS2
- input.h:#define BTN_TOOL_DOUBLETAP 0x14d unused
- input.h:#define BTN_TOOL_TRIPLETAP 0x14e unused
- *
- * MIMIO_EV_PENDOWN(MIMIO_PEN_K) => EV_KEY BIT(BTN_TOOL_PEN)
- * MIMIO_EV_PENDOWN(MIMIO_PEN_B) => EV_KEY BIT(BTN_TOOL_RUBBER)
- * MIMIO_EV_PENDOWN(MIMIO_PEN_G) => EV_KEY BIT(BTN_TOOL_BRUSH)
- * MIMIO_EV_PENDOWN(MIMIO_PEN_R) => EV_KEY BIT(BTN_TOOL_PENCIL)
- * MIMIO_EV_PENDOWN(MIMIO_PEN_E) => EV_KEY BIT(BTN_TOOL_AIRBRUSH)
- * MIMIO_EV_PENDOWN(MIMIO_PEN_ES) => EV_KEY BIT(BTN_TOOL_FINGER)
- * MIMIO_EV_PENDOWN(MIMIO_PEN_I) => EV_KEY BIT(BTN_TOOL_MOUSE)
- * MIMIO_EV_PENDOWN(MIMIO_PEN_IL) => EV_KEY BIT(BTN_TOOL_LENS)
- * MIMIO_EV_PENDOWN(MIMIO_PEN_IR) => EV_KEY BIT(BTN_TOOL_DOUBLETAP)
- * MIMIO_EV_PENDOWN(MIMIO_PEN_EX) => EV_KEY BIT(BTN_TOOL_TRIPLETAP)
- * MIMIO_EV_PENDATA => EV_ABS BIT(ABS_X), BIT(ABS_Y)
- * MIMIO_EV_MEMRESET => EV_KEY BIT(BTN_0)
- * MIMIO_EV_ACC(ACC_NEWPAGE) => EV_KEY BIT(BTN_1)
- * MIMIO_EV_ACC(ACC_TAGPAGE) => EV_KEY BIT(BTN_2)
- * MIMIO_EV_ACC(ACC_PRINTPAGE) => EV_KEY BIT(BTN_3)
- * MIMIO_EV_ACC(ACC_MAXIMIZE) => EV_KEY BIT(BTN_4)
- * MIMIO_EV_ACC(ACC_FINDCTLPNL) => EV_KEY BIT(BTN_5)
- *
- *
- * open issues:
- * - cold-load of data captured when mimio in standalone mode not yet
- * supported; need to snoop Win32 box to see datastream for this.
- * - mimio mouse not yet supported; need to snoop Win32 box to see the
- * datastream for this.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/input.h>
-#include <linux/usb.h>
-
-#define DRIVER_VERSION "v0.031"
-#define DRIVER_AUTHOR "mwilder@cs.nmsu.edu"
-#define DRIVER_DESC "USB mimio-xi driver"
-
-enum {UPVALUE, DOWNVALUE, MOVEVALUE};
-
-#define MIMIO_XRANGE_MAX 9600
-#define MIMIO_YRANGE_MAX 4800
-
-#define LOCALBTN_TOOL_EXTRA1 BTN_TOUCH
-#define LOCALBTN_TOOL_EXTRA2 BTN_STYLUS
-#define LOCALBTN_TOOL_EXTRA3 BTN_STYLUS2
-
-#define MIMIO_VENDOR_ID 0x08d3
-#define MIMIO_PRODUCT_ID 0x0001
-#define MIMIO_MAXPAYLOAD (8)
-#define MIMIO_MAXNAMELEN (64)
-#define MIMIO_TXWAIT (1)
-#define MIMIO_TXDONE (2)
-
-#define MIMIO_EV_PENDOWN (0x22)
-#define MIMIO_EV_PENDATA (0x24)
-#define MIMIO_EV_PENUP (0x51)
-#define MIMIO_EV_MEMRESET (0x45)
-#define MIMIO_EV_ACC (0xb2)
-
-#define MIMIO_PEN_K (1) /* black pen */
-#define MIMIO_PEN_B (2) /* blue pen */
-#define MIMIO_PEN_G (3) /* green pen */
-#define MIMIO_PEN_R (4) /* red pen */
-/* 5, 6, 7, 8 are extra pens */
-#define MIMIO_PEN_E (9) /* big eraser */
-#define MIMIO_PEN_ES (10) /* lil eraser */
-#define MIMIO_PENJUMP_START (10)
-#define MIMIO_PENJUMP (6)
-#define MIMIO_PEN_I (17) /* mimio interactive */
-#define MIMIO_PEN_IL (18) /* mimio interactive button 1 */
-#define MIMIO_PEN_IR (19) /* mimio interactive button 2 */
-
-#define MIMIO_PEN_MAX (MIMIO_PEN_IR)
-
-#define ACC_DONE (0)
-#define ACC_NEWPAGE (1)
-#define ACC_TAGPAGE (2)
-#define ACC_PRINTPAGE (4)
-#define ACC_MAXIMIZE (8)
-#define ACC_FINDCTLPNL (16)
-
-#define isvalidtxsize(n) ((n) > 0 && (n) <= MIMIO_MAXPAYLOAD)
-
-
-struct pktbuf {
- unsigned char instr;
- unsigned char buf[16];
- unsigned char *p;
- unsigned char *q;
-};
-
-struct usbintendpt {
- dma_addr_t dma;
- struct urb *urb;
- unsigned char *buf;
- struct usb_endpoint_descriptor *desc;
-};
-
-struct mimio {
- struct input_dev *idev;
- struct usb_device *udev;
- struct usb_interface *uifc;
- int open;
- int present;
- int greeted;
- int txflags;
- char phys[MIMIO_MAXNAMELEN];
- struct usbintendpt in;
- struct usbintendpt out;
- struct pktbuf pktbuf;
- unsigned char minor;
- wait_queue_head_t waitq;
- spinlock_t txlock;
- void (*rxhandler)(struct mimio *, unsigned char *, unsigned int);
- int last_pen_down;
-};
-
-static void mimio_close(struct input_dev *);
-static void mimio_dealloc(struct mimio *);
-static void mimio_disconnect(struct usb_interface *);
-static int mimio_greet(struct mimio *);
-static void mimio_irq_in(struct urb *);
-static void mimio_irq_out(struct urb *);
-static int mimio_open(struct input_dev *);
-static int mimio_probe(struct usb_interface *, const struct usb_device_id *);
-static void mimio_rx_handler(struct mimio *, unsigned char *, unsigned int);
-static int mimio_tx(struct mimio *, const char *, int);
-
-static char mimio_name[] = "VirtualInk mimio-Xi";
-static struct usb_device_id mimio_table [] = {
- { USB_DEVICE(MIMIO_VENDOR_ID, MIMIO_PRODUCT_ID) },
- { USB_DEVICE(0x0525, 0xa4a0) }, /* gadget zero firmware */
- { }
-};
-
-MODULE_DEVICE_TABLE(usb, mimio_table);
-
-static struct usb_driver mimio_driver = {
- .name = "mimio",
- .probe = mimio_probe,
- .disconnect = mimio_disconnect,
- .id_table = mimio_table,
-};
-
-static DECLARE_MUTEX(disconnect_sem);
-
-static void mimio_close(struct input_dev *idev)
-{
- struct mimio *mimio;
-
- mimio = input_get_drvdata(idev);
- if (!mimio) {
- dev_err(&idev->dev, "null mimio attached to input device\n");
- return;
- }
-
- if (mimio->open <= 0)
- dev_err(&idev->dev, "mimio not open.\n");
- else
- mimio->open--;
-
- if (mimio->present == 0 && mimio->open == 0)
- mimio_dealloc(mimio);
-}
-
-static void mimio_dealloc(struct mimio *mimio)
-{
- if (mimio == NULL)
- return;
-
- usb_kill_urb(mimio->in.urb);
-
- usb_kill_urb(mimio->out.urb);
-
- if (mimio->idev) {
- input_unregister_device(mimio->idev);
- if (mimio->idev->grab)
- input_close_device(mimio->idev->grab);
- else
- dev_dbg(&mimio->idev->dev, "mimio->idev->grab == NULL"
- " -- didn't call input_close_device\n");
- }
-
- usb_free_urb(mimio->in.urb);
-
- usb_free_urb(mimio->out.urb);
-
- if (mimio->in.buf) {
- usb_buffer_free(mimio->udev, MIMIO_MAXPAYLOAD, mimio->in.buf,
- mimio->in.dma);
- }
-
- if (mimio->out.buf)
- usb_buffer_free(mimio->udev, MIMIO_MAXPAYLOAD, mimio->out.buf,
- mimio->out.dma);
-
- if (mimio->idev)
- input_free_device(mimio->idev);
-
- kfree(mimio);
-}
-
-static void mimio_disconnect(struct usb_interface *ifc)
-{
- struct mimio *mimio;
-
- down(&disconnect_sem);
-
- mimio = usb_get_intfdata(ifc);
- usb_set_intfdata(ifc, NULL);
- dev_dbg(&mimio->idev->dev, "disconnect\n");
-
- if (mimio) {
- mimio->present = 0;
-
- if (mimio->open <= 0)
- mimio_dealloc(mimio);
- }
-
- up(&disconnect_sem);
-}
-
-static int mimio_greet(struct mimio *mimio)
-{
- const struct grtpkt {
- int nbytes;
- unsigned delay;
- char data[8];
- } grtpkts[] = {
- { 3, 0, { 0x11, 0x55, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00 } },
- { 5, 0, { 0x53, 0x55, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00 } },
- { 5, 0, { 0x43, 0x55, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00 } },
- { 5, 0, { 0x33, 0x55, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00 } },
- { 5, 0, { 0x13, 0x00, 0x5e, 0x02, 0x4f, 0x00, 0x00, 0x00 } },
- { 5, 0, { 0x13, 0x00, 0x04, 0x03, 0x14, 0x00, 0x00, 0x00 } },
- { 5, 2, { 0x13, 0x00, 0x00, 0x04, 0x17, 0x00, 0x00, 0x00 } },
- { 5, 0, { 0x13, 0x00, 0x0d, 0x08, 0x16, 0x00, 0x00, 0x00 } },
- { 5, 0, { 0x13, 0x00, 0x4d, 0x01, 0x5f, 0x00, 0x00, 0x00 } },
- { 3, 0, { 0xf1, 0x55, 0xa4, 0x00, 0x00, 0x00, 0x00, 0x00 } },
- { 7, 2, { 0x52, 0x55, 0x00, 0x07, 0x31, 0x55, 0x64, 0x00 } },
- { 0, 0, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
- };
- int rslt;
- const struct grtpkt *pkt;
-
- for (pkt = grtpkts; pkt->nbytes; pkt++) {
- rslt = mimio_tx(mimio, pkt->data, pkt->nbytes);
- if (rslt)
- return rslt;
- if (pkt->delay)
- msleep(pkt->delay);
- }
-
- return 0;
-}
-
-static void mimio_irq_in(struct urb *urb)
-{
- int rslt;
- char *data;
- const char *reason = "going down";
- struct mimio *mimio;
-
- mimio = urb->context;
-
- if (mimio == NULL)
- /* paranoia */
- return;
-
- switch (urb->status) {
- case 0:
- /* success */
- break;
- case -ETIMEDOUT:
- reason = "timeout -- unplugged?";
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- dev_dbg(&mimio->idev->dev, "%s.\n", reason);
- return;
- default:
- dev_dbg(&mimio->idev->dev, "unknown urb-status: %d.\n",
- urb->status);
- goto exit;
- }
- data = mimio->in.buf;
-
- if (mimio->rxhandler)
- mimio->rxhandler(mimio, data, urb->actual_length);
-exit:
- /*
- * Keep listening to device on same urb.
- */
- rslt = usb_submit_urb(urb, GFP_ATOMIC);
- if (rslt)
- dev_err(&mimio->idev->dev, "usb_submit_urb failure: %d.\n",
- rslt);
-}
-
-static void mimio_irq_out(struct urb *urb)
-{
- unsigned long flags;
- struct mimio *mimio;
-
- mimio = urb->context;
-
- if (urb->status)
- dev_dbg(&mimio->idev->dev, "urb-status: %d.\n", urb->status);
-
- spin_lock_irqsave(&mimio->txlock, flags);
- mimio->txflags |= MIMIO_TXDONE;
- spin_unlock_irqrestore(&mimio->txlock, flags);
- wmb();
- wake_up(&mimio->waitq);
-}
-
-static int mimio_open(struct input_dev *idev)
-{
- int rslt;
- struct mimio *mimio;
-
- rslt = 0;
- down(&disconnect_sem);
- mimio = input_get_drvdata(idev);
- dev_dbg(&idev->dev, "mimio_open\n");
-
- if (mimio == NULL) {
- dev_err(&idev->dev, "null mimio.\n");
- rslt = -ENODEV;
- goto exit;
- }
-
- if (mimio->open++)
- goto exit;
-
- if (mimio->present && !mimio->greeted) {
- struct urb *urb = mimio->in.urb;
- mimio->in.urb->dev = mimio->udev;
- rslt = usb_submit_urb(mimio->in.urb, GFP_KERNEL);
- if (rslt) {
- dev_err(&idev->dev, "usb_submit_urb failure "
- "(res = %d: %s). Not greeting.\n",
- rslt,
- (!urb ? "urb is NULL" :
- (urb->hcpriv ? "urb->hcpriv is non-NULL" :
- (!urb->complete ? "urb is not complete" :
- (urb->number_of_packets <= 0 ? "urb has no packets" :
- (urb->interval <= 0 ? "urb interval too small" :
- "urb interval too large or some other error"))))));
- rslt = -EIO;
- goto exit;
- }
- rslt = mimio_greet(mimio);
- if (rslt == 0) {
- dev_dbg(&idev->dev, "Mimio greeted OK.\n");
- mimio->greeted = 1;
- } else {
- dev_dbg(&idev->dev, "Mimio greet Failure (%d)\n",
- rslt);
- }
- }
-
-exit:
- up(&disconnect_sem);
- return rslt;
-}
-
-static int mimio_probe(struct usb_interface *ifc,
- const struct usb_device_id *id)
-{
- char path[64];
- int pipe, maxp;
- struct mimio *mimio;
- struct usb_device *udev;
- struct usb_host_interface *hostifc;
- struct input_dev *input_dev;
- int res = 0;
- int i;
-
- udev = interface_to_usbdev(ifc);
-
- mimio = kzalloc(sizeof(struct mimio), GFP_KERNEL);
- if (!mimio)
- return -ENOMEM;
-
- input_dev = input_allocate_device();
- if (!input_dev) {
- mimio_dealloc(mimio);
- return -ENOMEM;
- }
-
- mimio->uifc = ifc;
- mimio->udev = udev;
- mimio->pktbuf.p = mimio->pktbuf.buf;
- mimio->pktbuf.q = mimio->pktbuf.buf;
- /* init_input_dev(mimio->idev); */
- mimio->idev = input_dev;
- init_waitqueue_head(&mimio->waitq);
- spin_lock_init(&mimio->txlock);
- hostifc = ifc->cur_altsetting;
-
- if (hostifc->desc.bNumEndpoints != 2) {
- dev_err(&udev->dev, "Unexpected endpoint count: %d.\n",
- hostifc->desc.bNumEndpoints);
- mimio_dealloc(mimio);
- return -ENODEV;
- }
-
- mimio->in.desc = &(hostifc->endpoint[0].desc);
- mimio->out.desc = &(hostifc->endpoint[1].desc);
-
- mimio->in.buf = usb_buffer_alloc(udev, MIMIO_MAXPAYLOAD, GFP_KERNEL,
- &mimio->in.dma);
- mimio->out.buf = usb_buffer_alloc(udev, MIMIO_MAXPAYLOAD, GFP_KERNEL,
- &mimio->out.dma);
-
- if (mimio->in.buf == NULL || mimio->out.buf == NULL) {
- dev_err(&udev->dev, "usb_buffer_alloc failure.\n");
- mimio_dealloc(mimio);
- return -ENOMEM;
- }
-
- mimio->in.urb = usb_alloc_urb(0, GFP_KERNEL);
- mimio->out.urb = usb_alloc_urb(0, GFP_KERNEL);
-
- if (mimio->in.urb == NULL || mimio->out.urb == NULL) {
- dev_err(&udev->dev, "usb_alloc_urb failure.\n");
- mimio_dealloc(mimio);
- return -ENOMEM;
- }
-
- /*
- * Build the input urb.
- */
- pipe = usb_rcvintpipe(udev, mimio->in.desc->bEndpointAddress);
- maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
- if (maxp > MIMIO_MAXPAYLOAD)
- maxp = MIMIO_MAXPAYLOAD;
- usb_fill_int_urb(mimio->in.urb, udev, pipe, mimio->in.buf, maxp,
- mimio_irq_in, mimio, mimio->in.desc->bInterval);
- mimio->in.urb->transfer_dma = mimio->in.dma;
- mimio->in.urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
- /*
- * Build the output urb.
- */
- pipe = usb_sndintpipe(udev, mimio->out.desc->bEndpointAddress);
- maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe));
- if (maxp > MIMIO_MAXPAYLOAD)
- maxp = MIMIO_MAXPAYLOAD;
- usb_fill_int_urb(mimio->out.urb, udev, pipe, mimio->out.buf, maxp,
- mimio_irq_out, mimio, mimio->out.desc->bInterval);
- mimio->out.urb->transfer_dma = mimio->out.dma;
- mimio->out.urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
-
- /*
- * Build input device info
- */
- usb_make_path(udev, path, 64);
- snprintf(mimio->phys, MIMIO_MAXNAMELEN, "%s/input0", path);
- input_set_drvdata(input_dev, mimio);
- /* input_dev->dev = &ifc->dev; */
- input_dev->open = mimio_open;
- input_dev->close = mimio_close;
- input_dev->name = mimio_name;
- input_dev->phys = mimio->phys;
- input_dev->dev.parent = &ifc->dev;
-
- input_dev->id.bustype = BUS_USB;
- input_dev->id.vendor = le16_to_cpu(udev->descriptor.idVendor);
- input_dev->id.product = le16_to_cpu(udev->descriptor.idProduct);
- input_dev->id.version = le16_to_cpu(udev->descriptor.bcdDevice);
-
- input_dev->evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS);
- for (i = BTN_TOOL_PEN; i <= LOCALBTN_TOOL_EXTRA2; ++i)
- set_bit(i, input_dev->keybit);
-
- input_dev->keybit[BIT_WORD(BTN_MISC)] |= BIT_MASK(BTN_0) |
- BIT_MASK(BTN_1) |
- BIT_MASK(BTN_2) |
- BIT_MASK(BTN_3) |
- BIT_MASK(BTN_4) |
- BIT_MASK(BTN_5);
- /* input_dev->keybit[BTN_MOUSE] |= BIT(BTN_LEFT); */
- input_dev->absbit[0] |= BIT_MASK(ABS_X) | BIT_MASK(ABS_Y);
- input_set_abs_params(input_dev, ABS_X, 0, MIMIO_XRANGE_MAX, 0, 0);
- input_set_abs_params(input_dev, ABS_Y, 0, MIMIO_YRANGE_MAX, 0, 0);
- input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC);
-
-#if 0
- input_dev->absmin[ABS_X] = 0;
- input_dev->absmin[ABS_Y] = 0;
- input_dev->absmax[ABS_X] = 9600;
- input_dev->absmax[ABS_Y] = 4800;
- input_dev->absfuzz[ABS_X] = 0;
- input_dev->absfuzz[ABS_Y] = 0;
- input_dev->absflat[ABS_X] = 0;
- input_dev->absflat[ABS_Y] = 0;
-#endif
-
-#if 0
- /* this will just reduce the precision */
- input_dev->absfuzz[ABS_X] = 8; /* experimental; may need to change */
- input_dev->absfuzz[ABS_Y] = 8; /* experimental; may need to change */
-#endif
-
- /*
- * Register the input device.
- */
- res = input_register_device(mimio->idev);
- if (res) {
- dev_err(&udev->dev, "input_register_device failure (%d)\n",
- res);
- mimio_dealloc(mimio);
- return -EIO;
- }
- dev_dbg(&mimio->idev->dev, "input: %s on %s (res = %d).\n",
- input_dev->name, input_dev->phys, res);
-
- usb_set_intfdata(ifc, mimio);
- mimio->present = 1;
-
- /*
- * Submit the input urb to the usb subsystem.
- */
- mimio->in.urb->dev = mimio->udev;
- res = usb_submit_urb(mimio->in.urb, GFP_KERNEL);
- if (res) {
- dev_err(&mimio->idev->dev, "usb_submit_urb failure (%d)\n",
- res);
- mimio_dealloc(mimio);
- return -EIO;
- }
-
- /*
- * Attempt to greet the mimio after giving
- * it some post-init settling time.
- *
- * note: sometimes this sleep interval isn't
- * long enough to permit the device to re-init
- * after a hot-swap; maybe need to bump it up.
- *
- * As it is, this probably breaks module unloading support!
- */
- msleep(1024);
-
- res = mimio_greet(mimio);
- if (res == 0) {
- dev_dbg(&mimio->idev->dev, "Mimio greeted OK.\n");
- mimio->greeted = 1;
- mimio->rxhandler = mimio_rx_handler;
- } else {
- dev_dbg(&mimio->idev->dev, "Mimio greet Failure (%d)\n", res);
- }
-
- return 0;
-}
-
-static int handle_mimio_rx_penupdown(struct mimio *mimio,
- int down,
- const char *const instr[],
- const int instr_ofst[])
-{
- int penid, x;
- if (mimio->pktbuf.q - mimio->pktbuf.p < (down ? 4 : 3))
- return 1; /* partial pkt */
-
- if (down) {
- x = *mimio->pktbuf.p ^ *(mimio->pktbuf.p + 1) ^
- *(mimio->pktbuf.p + 2);
- if (x != *(mimio->pktbuf.p + 3)) {
- dev_dbg(&mimio->idev->dev, "EV_PEN%s: bad xsum.\n",
- down ? "DOWN":"UP");
- /* skip this event data */
- mimio->pktbuf.p += 4;
- /* decode any remaining events */
- return 0;
- }
- penid = mimio->pktbuf.instr = *(mimio->pktbuf.p + 2);
- if (penid > MIMIO_PEN_MAX) {
- dev_dbg(&mimio->idev->dev,
- "Unmapped penID (not in [0, %d]): %d\n",
- MIMIO_PEN_MAX, (int)mimio->pktbuf.instr);
- penid = mimio->pktbuf.instr = 0;
- }
- mimio->last_pen_down = penid;
- } else {
- penid = mimio->last_pen_down;
- }
- dev_dbg(&mimio->idev->dev, "%s (id %d, code %d) %s.\n", instr[penid],
- instr_ofst[penid], penid, down ? "down" : "up");
-
- if (instr_ofst[penid] >= 0) {
- int code = BTN_TOOL_PEN + instr_ofst[penid];
- int value = down ? DOWNVALUE : UPVALUE;
- if (code > KEY_MAX)
- dev_dbg(&mimio->idev->dev, "input_event will ignore "
- "-- code (%d) > KEY_MAX\n", code);
- if (!test_bit(code, mimio->idev->keybit))
- dev_dbg(&mimio->idev->dev, "input_event will ignore "
- "-- bit for code (%d) not enabled\n", code);
- if (!!test_bit(code, mimio->idev->key) == value)
- dev_dbg(&mimio->idev->dev, "input_event will ignore "
- "-- bit for code (%d) already set to %d\n",
- code, value);
- if (value != DOWNVALUE) {
- /* input_regs(mimio->idev, regs); */
- input_report_key(mimio->idev, code, value);
- input_sync(mimio->idev);
- } else {
- /* wait until we get some coordinates */
- }
- } else {
- dev_dbg(&mimio->idev->dev, "penID offset[%d] == %d is < 0 "
- "- not sending\n", penid, instr_ofst[penid]);
- }
- mimio->pktbuf.p += down ? 4 : 3; /* 3 for up, 4 for down */
- return 0;
-}
-
-/*
- * Stay tuned for partial-packet excitement.
- *
- * This routine buffers data packets received from the mimio device
- * in the mimio's data space. This buffering is necessary because
- * the mimio's in endpoint can serve us partial packets of data, and
- * we want the driver to support the servicing of multiple mimios.
- * Empirical evidence gathered so far suggests that the method of
- * buffering packet data in the mimio's data space works. Previous
- * versions of this driver did not buffer packet data in each mimio's
- * data-space, and were therefore not able to service multiple mimios.
- * Note that since the caller of this routine is running in interrupt
- * context, care needs to be taken to ensure that this routine does not
- * become bloated, and it may be that another spinlock is needed in each
- * mimio to guard the buffered packet data properly.
- */
-static void mimio_rx_handler(struct mimio *mimio,
- unsigned char *data,
- unsigned int nbytes)
-{
- struct device *dev = &mimio->idev->dev;
- unsigned int x;
- unsigned int y;
- static const char * const instr[] = {
- "?0",
- "black pen", "blue pen", "green pen", "red pen",
- "brown pen", "orange pen", "purple pen", "yellow pen",
- "big eraser", "lil eraser",
- "?11", "?12", "?13", "?14", "?15", "?16",
- "mimio interactive", "interactive button1",
- "interactive button2"
- };
-
- /* Mimio Interactive gives:
- * down: [0x22 0x01 0x11 0x32 0x24]
- * b1 : [0x22 0x01 0x12 0x31 0x24]
- * b2 : [0x22 0x01 0x13 0x30 0x24]
- */
- static const int instr_ofst[] = {
- -1,
- 0, 1, 2, 3,
- 9, 9, 9, 9,
- 4, 5,
- -1, -1, -1, -1, -1, -1,
- 6, 7, 8,
- };
-
- memcpy(mimio->pktbuf.q, data, nbytes);
- mimio->pktbuf.q += nbytes;
-
- while (mimio->pktbuf.p < mimio->pktbuf.q) {
- int t = *mimio->pktbuf.p;
- switch (t) {
- case MIMIO_EV_PENUP:
- case MIMIO_EV_PENDOWN:
- if (handle_mimio_rx_penupdown(mimio,
- t == MIMIO_EV_PENDOWN,
- instr, instr_ofst))
- return; /* partial packet */
- break;
-
- case MIMIO_EV_PENDATA:
- if (mimio->pktbuf.q - mimio->pktbuf.p < 6)
- /* partial pkt */
- return;
- x = *mimio->pktbuf.p ^ *(mimio->pktbuf.p + 1) ^
- *(mimio->pktbuf.p + 2) ^
- *(mimio->pktbuf.p + 3) ^
- *(mimio->pktbuf.p + 4);
- if (x != *(mimio->pktbuf.p + 5)) {
- dev_dbg(dev, "EV_PENDATA: bad xsum.\n");
- mimio->pktbuf.p += 6; /* skip this event data */
- break; /* decode any remaining events */
- }
- x = *(mimio->pktbuf.p + 1);
- x <<= 8;
- x |= *(mimio->pktbuf.p + 2);
- y = *(mimio->pktbuf.p + 3);
- y <<= 8;
- y |= *(mimio->pktbuf.p + 4);
- dev_dbg(dev, "coord: (%d, %d)\n", x, y);
- if (instr_ofst[mimio->pktbuf.instr] >= 0) {
- int code = BTN_TOOL_PEN +
- instr_ofst[mimio->last_pen_down];
-#if 0
- /* Utter hack to ensure we get forwarded _AND_
- * so we can identify when a complete signal is
- * received */
- mimio->idev->abs[ABS_Y] = -1;
- mimio->idev->abs[ABS_X] = -1;
-#endif
- /* input_regs(mimio->idev, regs); */
- input_report_abs(mimio->idev, ABS_X, x);
- input_report_abs(mimio->idev, ABS_Y, y);
- /* fake a penup */
- change_bit(code, mimio->idev->key);
- input_report_key(mimio->idev,
- code,
- DOWNVALUE);
- /* always sync here */
- mimio->idev->sync = 0;
- input_sync(mimio->idev);
- }
- mimio->pktbuf.p += 6;
- break;
- case MIMIO_EV_MEMRESET:
- if (mimio->pktbuf.q - mimio->pktbuf.p < 7)
- /* partial pkt */
- return;
- dev_dbg(dev, "mem-reset.\n");
- /* input_regs(mimio->idev, regs); */
- input_event(mimio->idev, EV_KEY, BTN_0, 1);
- input_event(mimio->idev, EV_KEY, BTN_0, 0);
- input_sync(mimio->idev);
- mimio->pktbuf.p += 7;
- break;
- case MIMIO_EV_ACC:
- if (mimio->pktbuf.q - mimio->pktbuf.p < 4)
- /* partial pkt */
- return;
- x = *mimio->pktbuf.p ^ *(mimio->pktbuf.p + 1) ^
- *(mimio->pktbuf.p + 2);
- if (x != *(mimio->pktbuf.p + 3)) {
- dev_dbg(dev, "EV_ACC: bad xsum.\n");
- mimio->pktbuf.p += 4; /* skip this event data */
- break; /* decode any remaining events */
- }
- switch (*(mimio->pktbuf.p + 2)) {
- case ACC_NEWPAGE:
- dev_dbg(&mimio->idev->dev, "new-page.\n");
- /* input_regs(mimio->idev, regs); */
- input_event(mimio->idev, EV_KEY, BTN_1, 1);
- input_event(mimio->idev, EV_KEY, BTN_1, 0);
- input_sync(mimio->idev);
- break;
- case ACC_TAGPAGE:
- dev_dbg(&mimio->idev->dev, "tag-page.\n");
- /* input_regs(mimio->idev, regs); */
- input_event(mimio->idev, EV_KEY, BTN_2, 1);
- input_event(mimio->idev, EV_KEY, BTN_2, 0);
- input_sync(mimio->idev);
- break;
- case ACC_PRINTPAGE:
- dev_dbg(&mimio->idev->dev, "print-page.\n");
- /* input_regs(mimio->idev, regs);*/
- input_event(mimio->idev, EV_KEY, BTN_3, 1);
- input_event(mimio->idev, EV_KEY, BTN_3, 0);
- input_sync(mimio->idev);
- break;
- case ACC_MAXIMIZE:
- dev_dbg(&mimio->idev->dev,
- "maximize-window.\n");
- /* input_regs(mimio->idev, regs); */
- input_event(mimio->idev, EV_KEY, BTN_4, 1);
- input_event(mimio->idev, EV_KEY, BTN_4, 0);
- input_sync(mimio->idev);
- break;
- case ACC_FINDCTLPNL:
- dev_dbg(&mimio->idev->dev, "find-ctl-panel.\n");
- /* input_regs(mimio->idev, regs); */
- input_event(mimio->idev, EV_KEY, BTN_5, 1);
- input_event(mimio->idev, EV_KEY, BTN_5, 0);
- input_sync(mimio->idev);
- break;
- case ACC_DONE:
- dev_dbg(&mimio->idev->dev, "acc-done.\n");
- /* no event is dispatched to the input
- * subsystem for this device event.
- */
- break;
- default:
- dev_dbg(dev, "unknown acc event.\n");
- break;
- }
- mimio->pktbuf.p += 4;
- break;
- default:
- mimio->pktbuf.p++;
- break;
- }
- }
-
- /*
- * No partial event was received, so reset mimio's pktbuf ptrs.
- */
- mimio->pktbuf.p = mimio->pktbuf.q = mimio->pktbuf.buf;
-}
-
-static int mimio_tx(struct mimio *mimio, const char *buf, int nbytes)
-{
- int rslt;
- int timeout;
- unsigned long flags;
- DECLARE_WAITQUEUE(wait, current);
-
- if (!(isvalidtxsize(nbytes))) {
- dev_err(&mimio->idev->dev, "invalid arg: nbytes: %d.\n",
- nbytes);
- return -EINVAL;
- }
-
- /*
- * Init the out urb and copy the data to send.
- */
- mimio->out.urb->dev = mimio->udev;
- mimio->out.urb->transfer_buffer_length = nbytes;
- memcpy(mimio->out.urb->transfer_buffer, buf, nbytes);
-
- /*
- * Send the data.
- */
- spin_lock_irqsave(&mimio->txlock, flags);
- mimio->txflags = MIMIO_TXWAIT;
- rslt = usb_submit_urb(mimio->out.urb, GFP_ATOMIC);
- spin_unlock_irqrestore(&mimio->txlock, flags);
- dev_dbg(&mimio->idev->dev, "rslt: %d.\n", rslt);
-
- if (rslt) {
- dev_err(&mimio->idev->dev, "usb_submit_urb failure: %d.\n",
- rslt);
- return rslt;
- }
-
- /*
- * Wait for completion to be signalled (the mimio_irq_out
- * completion routine will or MIMIO_TXDONE in with txflags).
- */
- timeout = HZ;
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&mimio->waitq, &wait);
-
- while (timeout && ((mimio->txflags & MIMIO_TXDONE) == 0)) {
- timeout = schedule_timeout(timeout);
- rmb();
- }
-
- if ((mimio->txflags & MIMIO_TXDONE) == 0)
- dev_dbg(&mimio->idev->dev, "tx timed out.\n");
-
- /*
- * Now that completion has been signalled,
- * unlink the urb so that it can be recycled.
- */
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&mimio->waitq, &wait);
- usb_unlink_urb(mimio->out.urb);
-
- return rslt;
-}
-
-static int __init mimio_init(void)
-{
- int rslt;
-
- rslt = usb_register(&mimio_driver);
- if (rslt != 0) {
- err("%s: usb_register failure: %d", __func__, rslt);
- return rslt;
- }
-
- printk(KERN_INFO KBUILD_MODNAME ":"
- DRIVER_DESC " " DRIVER_VERSION "\n");
- return rslt;
-}
-
-static void __exit mimio_exit(void)
-{
- usb_deregister(&mimio_driver);
-}
-
-module_init(mimio_init);
-module_exit(mimio_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/otus/80211core/cagg.c b/drivers/staging/otus/80211core/cagg.c
index dbd0a5f0fcd..f9514c06c14 100644
--- a/drivers/staging/otus/80211core/cagg.c
+++ b/drivers/staging/otus/80211core/cagg.c
@@ -1832,14 +1832,12 @@ u16_t zfAggRxClear(zdev_t* dev, u32_t time)
struct agg_tid_rx* zfAggRxEnabled(zdev_t* dev, zbuf_t* buf)
{
- u16_t dst0, src[3], ac, aid, fragOff;
- u8_t up;
+ u16_t dst0, src[3], aid;
u16_t offset = 0;
u16_t seq_no;
u16_t frameType;
u16_t frameCtrl;
u16_t frameSubtype;
- u32_t tcp_seq;
//struct aggSta *agg_sta;
#if ZM_AGG_FPGA_REORDERING
struct agg_tid_rx *tid_rx;
@@ -1864,13 +1862,17 @@ struct agg_tid_rx* zfAggRxEnabled(zdev_t* dev, zbuf_t* buf)
return NULL;
}
#ifdef ZM_ENABLE_PERFORMANCE_EVALUATION
- tcp_seq = zmw_rx_buf_readb(dev, buf, 22+36) << 24;
- tcp_seq += zmw_rx_buf_readb(dev, buf, 22+37) << 16;
- tcp_seq += zmw_rx_buf_readb(dev, buf, 22+38) << 8;
- tcp_seq += zmw_rx_buf_readb(dev, buf, 22+39);
+ {
+ u32_t tcp_seq;
+
+ tcp_seq = zmw_rx_buf_readb(dev, buf, 22+36) << 24;
+ tcp_seq += zmw_rx_buf_readb(dev, buf, 22+37) << 16;
+ tcp_seq += zmw_rx_buf_readb(dev, buf, 22+38) << 8;
+ tcp_seq += zmw_rx_buf_readb(dev, buf, 22+39);
+ ZM_SEQ_DEBUG("In %5d, %12u\n", seq_no, tcp_seq);
+ }
#endif
- ZM_SEQ_DEBUG("In %5d, %12u\n", seq_no, tcp_seq);
dst0 = zmw_rx_buf_readh(dev, buf, offset+4);
src[0] = zmw_rx_buf_readh(dev, buf, offset+10);
diff --git a/drivers/staging/otus/80211core/ccmd.c b/drivers/staging/otus/80211core/ccmd.c
index 8da28eee7fb..3e3d9b500f6 100644
--- a/drivers/staging/otus/80211core/ccmd.c
+++ b/drivers/staging/otus/80211core/ccmd.c
@@ -1659,7 +1659,7 @@ void zfiWlanSetPacketTypePromiscuous(zdev_t *dev, u32_t setValue)
if (setValue) {
/* write register for sniffer mode */
zfHpSetSnifferMode(dev, 1);
- zm_msg0_mm(ZM_LV_1, "enalbe sniffer mode");
+ zm_msg0_mm(ZM_LV_1, "enable sniffer mode");
} else {
zfHpSetSnifferMode(dev, 0);
zm_msg0_mm(ZM_LV_0, "disalbe sniffer mode");
diff --git a/drivers/staging/otus/80211core/cfunc.c b/drivers/staging/otus/80211core/cfunc.c
index d7c49d7523d..e0a9f383c75 100644
--- a/drivers/staging/otus/80211core/cfunc.c
+++ b/drivers/staging/otus/80211core/cfunc.c
@@ -1194,8 +1194,6 @@ u16_t zfFindMinimumUtilizationChannelIndex(zdev_t* dev, u16_t* array, u16_t coun
u8_t i;
u16_t tempMinIndex, tempMinValue;
- zmw_get_wlan_dev(dev);
-
i = 1;
tempMinIndex = 0;
tempMinValue = array[tempMinIndex];
diff --git a/drivers/staging/otus/80211core/cmm.c b/drivers/staging/otus/80211core/cmm.c
index a6c1b41ba84..484e753df35 100644
--- a/drivers/staging/otus/80211core/cmm.c
+++ b/drivers/staging/otus/80211core/cmm.c
@@ -346,8 +346,6 @@ u16_t zfFindSuperGElement(zdev_t* dev, zbuf_t* buf, u8_t type)
u8_t super_feature;
u8_t ouiSuperG[6] = {0x00,0x03,0x7f,0x01, 0x01, 0x00};
- zmw_get_wlan_dev(dev);
-
/* Get offset of first element */
subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
if ((offset = zgElementOffsetTable[subType]) == 0xff)
@@ -411,8 +409,6 @@ u16_t zfFindXRElement(zdev_t* dev, zbuf_t* buf, u8_t type)
u8_t id;
u8_t ouixr[6] = {0x00,0x03,0x7f,0x03, 0x01, 0x00};
- zmw_get_wlan_dev(dev);
-
/* Get offset of first element */
subType = (zmw_rx_buf_readb(dev, buf, 0) >> 4);
if ((offset = zgElementOffsetTable[subType]) == 0xff)
diff --git a/drivers/staging/otus/80211core/cmmsta.c b/drivers/staging/otus/80211core/cmmsta.c
index a11d559167b..c3fd47529c1 100644
--- a/drivers/staging/otus/80211core/cmmsta.c
+++ b/drivers/staging/otus/80211core/cmmsta.c
@@ -2808,7 +2808,7 @@ void zfStaProcessProbeReq(zdev_t* dev, zbuf_t* buf, u16_t* src)
zmw_get_wlan_dev(dev);
/* check mode : AP/IBSS */
- if ((wd->wlanMode != ZM_MODE_AP) || (wd->wlanMode != ZM_MODE_IBSS))
+ if ((wd->wlanMode != ZM_MODE_AP) && (wd->wlanMode != ZM_MODE_IBSS))
{
zm_msg0_mm(ZM_LV_3, "Ignore probe req");
return;
@@ -4848,8 +4848,6 @@ u16_t zfStaAddIePowerCap(zdev_t* dev, zbuf_t* buf, u16_t offset)
u8_t MaxTxPower;
u8_t MinTxPower;
- zmw_get_wlan_dev(dev);
-
/* Element ID */
zmw_tx_buf_writeb(dev, buf, offset++, ZM_WLAN_EID_POWER_CAPABILITY);
@@ -5276,7 +5274,6 @@ u16_t zfStaRxValidateFrame(zdev_t* dev, zbuf_t* buf)
u8_t da0;
//u16_t sa[3];
u16_t ret;
- u16_t i;
//u8_t sa0;
zmw_get_wlan_dev(dev);
@@ -5738,8 +5735,6 @@ u16_t zfComputeBssInfoWeightValue(zdev_t *dev, u8_t isBMode, u8_t isHT, u8_t isH
u8_t weightOfN40BelowThr = 16;
u8_t weightOfN40UpThr = 32;
- zmw_get_wlan_dev(dev);
-
if( isBMode == 0 )
return (signalStrength + weightOfB); // pure b mode , do not add the weight value for this AP !
else
diff --git a/drivers/staging/otus/80211core/cpsmgr.c b/drivers/staging/otus/80211core/cpsmgr.c
index cf73caca8e5..98e1f0cc072 100644
--- a/drivers/staging/otus/80211core/cpsmgr.c
+++ b/drivers/staging/otus/80211core/cpsmgr.c
@@ -381,8 +381,6 @@ static void zfPowerSavingMgrSleepIfIdle(zdev_t *dev)
static void zfPowerSavingMgrDisconnectMain(zdev_t* dev)
{
- zmw_get_wlan_dev(dev);
-
#ifdef ZM_ENABLE_DISCONNECT_PS
switch(wd->sta.psMgr.state)
{
diff --git a/drivers/staging/otus/80211core/cscanmgr.c b/drivers/staging/otus/80211core/cscanmgr.c
index b32835c8759..be7d8ebe82b 100644
--- a/drivers/staging/otus/80211core/cscanmgr.c
+++ b/drivers/staging/otus/80211core/cscanmgr.c
@@ -289,8 +289,6 @@ static void zfScanMgrEventSetFreqCompleteCb(zdev_t* dev)
static void zfScanMgrEventScanCompleteCb(zdev_t* dev)
{
- zmw_get_wlan_dev(dev);
-
if ((zfStaIsConnected(dev)) && (!zfPowerSavingMgrIsSleeping(dev)))
{
zfSendNullData(dev, 0);
diff --git a/drivers/staging/otus/80211core/ctkip.c b/drivers/staging/otus/80211core/ctkip.c
index be42f7aaa37..ca0740227be 100644
--- a/drivers/staging/otus/80211core/ctkip.c
+++ b/drivers/staging/otus/80211core/ctkip.c
@@ -255,7 +255,8 @@ void zfTkipInit(u8_t* key, u8_t* ta, struct zsTkipSeed* pSeed, u8_t* initIv)
zfMemoryCopy(pSeed->ta, ta, 6);
zfMemoryCopy(pSeed->tk, key, 16);
- iv16 = *initIv++;
+ iv16 = *initIv;
+ initIv++;
iv16 += *initIv<<8;
initIv++;
@@ -264,7 +265,7 @@ void zfTkipInit(u8_t* key, u8_t* ta, struct zsTkipSeed* pSeed, u8_t* initIv)
for(i=0; i<4; i++) // initiv is little endian
{
iv32 += *initIv<<(i*8);
- *initIv++;
+ initIv++;
}
pSeed->iv32 = iv32+1; // Force Recalculating on Tkip Phase1
diff --git a/drivers/staging/otus/80211core/ctxrx.c b/drivers/staging/otus/80211core/ctxrx.c
index ac54d5a636b..4e7f4bd86f4 100644
--- a/drivers/staging/otus/80211core/ctxrx.c
+++ b/drivers/staging/otus/80211core/ctxrx.c
@@ -536,8 +536,7 @@ void zfProtRspSim(zdev_t* dev, zbuf_t* buf)
zm_msg2_rx(ZM_LV_2, "ip1=", dip[1]);
//ARP request to 192.168.1.15
- if ((arpOp == 0x0100) && (dip[0] == 0xa8c0) && (dip[1] == 0x0f01));
- {
+ if ((arpOp == 0x0100) && (dip[0] == 0xa8c0) && (dip[1] == 0x0f01)) {
zm_msg0_rx(ZM_LV_2, "ARP");
/* ARP response */
zmw_rx_buf_writeh(dev, buf, 20, 0x0200);
@@ -883,7 +882,6 @@ zlError:
/************************************************************************/
u16_t zfTxSendEth(zdev_t* dev, zbuf_t* buf, u16_t port, u16_t bufType, u16_t flag)
{
- u16_t err;
//u16_t addrTblSize;
//struct zsAddrTbl addrTbl;
u16_t removeLen;
@@ -905,7 +903,6 @@ u16_t zfTxSendEth(zdev_t* dev, zbuf_t* buf, u16_t port, u16_t bufType, u16_t fla
u8_t qosType, keyIdx = 0;
u16_t fragOff;
u16_t newFlag;
- struct zsMicVar* pMicKey;
u8_t tkipFrameOffset = 0;
zmw_get_wlan_dev(dev);
@@ -1693,8 +1690,6 @@ void zfShowTxEAPOL(zdev_t* dev, zbuf_t* buf, u16_t offset)
u16_t packetLen, keyInfo, keyLen, keyDataLen, length, Op_Code;
u32_t replayCounterH, replayCounterL, vendorId, VendorType;
- zmw_get_wlan_dev(dev);
-
zm_debug_msg1("EAPOL Packet size = ", zfwBufGetSize(dev, buf));
/* EAPOL packet type */
@@ -2437,7 +2432,6 @@ void zfiRecv80211(zdev_t* dev, zbuf_t* buf, struct zsAdditionInfo* addInfo)
u16_t IvOffset;
u8_t keyLen = 5;
u8_t iv[3];
- u8_t *wepKey;
u8_t keyIdx;
IvOffset = offset + ZM_SIZE_OF_WLAN_DATA_HEADER;
diff --git a/drivers/staging/otus/80211core/ledmgr.c b/drivers/staging/otus/80211core/ledmgr.c
index 1e104a928ca..eafce0b1204 100644
--- a/drivers/staging/otus/80211core/ledmgr.c
+++ b/drivers/staging/otus/80211core/ledmgr.c
@@ -187,7 +187,6 @@ void zfLedCtrlType2_scan(zdev_t* dev);
void zfLedCtrlType2(zdev_t* dev)
{
- u32_t ton, toff, tmp, period;
u16_t OperateLED;
zmw_get_wlan_dev(dev);
diff --git a/drivers/staging/otus/80211core/pub_zfi.h b/drivers/staging/otus/80211core/pub_zfi.h
index b7b7f455f35..5202e5a645d 100644
--- a/drivers/staging/otus/80211core/pub_zfi.h
+++ b/drivers/staging/otus/80211core/pub_zfi.h
@@ -814,7 +814,6 @@ extern void zfiRxPerformanceReg(zdev_t* dev, u32_t reg, u32_t rsp);
#define ZM_PERFORMANCE_RX_AMSDU(dev, buf, len)
#define ZM_PERFORMANCE_RX_FLUSH(dev)
#define ZM_PERFORMANCE_RX_CLEAR(dev)
-#define ZM_SEQ_DEBUG
#define ZM_PERFORMANCE_RX_REORDER(dev)
#endif
/***** End of section 3 *****/
diff --git a/drivers/staging/otus/Kconfig b/drivers/staging/otus/Kconfig
index f6cc2625e34..e9181340bef 100644
--- a/drivers/staging/otus/Kconfig
+++ b/drivers/staging/otus/Kconfig
@@ -1,6 +1,8 @@
config OTUS
tristate "Atheros OTUS 802.11n USB wireless support"
depends on USB && WLAN && MAC80211
+ select WIRELESS_EXT
+ select WEXT_PRIV
default N
---help---
Enable support for Atheros 802.11n USB hardware:
diff --git a/drivers/staging/otus/apdbg.c b/drivers/staging/otus/apdbg.c
index 0eb93f19958..b59028e7e33 100644
--- a/drivers/staging/otus/apdbg.c
+++ b/drivers/staging/otus/apdbg.c
@@ -90,8 +90,27 @@ struct zdap_ioctl {
#endif
-char hex(char);
-unsigned char asctohex(char *str);
+static char hex(char v)
+{
+ if (isdigit(v))
+ return v - '0';
+ else if (isxdigit(v))
+ return tolower(v) - 'a' + 10;
+ else
+ return 0;
+}
+
+static unsigned char asctohex(char *str)
+{
+ unsigned char value;
+
+ value = hex(*str) & 0x0f;
+ value = value << 4;
+ str++;
+ value |= hex(*str) & 0x0f;
+
+ return value;
+}
char *prgname;
@@ -109,10 +128,10 @@ int set_ioctl(int sock, struct ifreq *req)
int read_reg(int sock, struct ifreq *req)
{
- struct zdap_ioctl *zdreq = 0;
+ struct zdap_ioctl *zdreq = NULL;
if (!set_ioctl(sock, req))
- return -1;
+ return -1;
/*
* zdreq = (struct zdap_ioctl *)req->ifr_data;
@@ -125,7 +144,7 @@ int read_reg(int sock, struct ifreq *req)
int read_mem(int sock, struct ifreq *req)
{
- struct zdap_ioctl *zdreq = 0;
+ struct zdap_ioctl *zdreq = NULL;
int i;
if (!set_ioctl(sock, req))
@@ -368,7 +387,7 @@ int main(int argc, char **argv)
zdreq.addr = addr;
zdreq.cmd = ZM_IOCTL_SET_PIBSS_MODE;
- } else {
+ } else {
fprintf(stderr, "error action\n");
exit(1);
}
@@ -380,25 +399,3 @@ fail:
exit(0);
}
-unsigned char asctohex(char *str)
-{
- unsigned char value;
-
- value = hex(*str) & 0x0f;
- value = value << 4;
- str++;
- value |= hex(*str) & 0x0f;
-
- return value;
-}
-
-char hex(char v)
-{
- if (isdigit(v))
- return v - '0';
- else if (isxdigit(v))
- return tolower(v) - 'a' + 10;
- else
- return 0;
-}
-
diff --git a/drivers/staging/otus/hal/hpmain.c b/drivers/staging/otus/hal/hpmain.c
index 94f9cbbbdef..8dff5b97dfe 100644
--- a/drivers/staging/otus/hal/hpmain.c
+++ b/drivers/staging/otus/hal/hpmain.c
@@ -1316,7 +1316,6 @@ void zfHpSetFrequencyEx(zdev_t* dev, u32_t frequency, u8_t bw40,
u8_t extOffset, u8_t initRF)
{
u32_t cmd[9];
- u32_t cmdB[3];
u16_t ret;
u8_t old_band;
u8_t new_band;
@@ -3434,7 +3433,6 @@ void zfSetPowerCalTable(zdev_t* dev, u32_t frequency, u8_t bw40, u8_t extOffset)
/* Write PHY regs 672-703 */
for (i=0; i<128; i+=4)
{
- u32_t regAddr = 0x9800 + (672 * 4);
u32_t val;
val = ((u32_t)vpd_chain1[i+3]<<24) |
@@ -3485,7 +3483,6 @@ void zfSetPowerCalTable(zdev_t* dev, u32_t frequency, u8_t bw40, u8_t extOffset)
/* Write PHY regs 672-703 + 0x1000 */
for (i=0; i<128; i+=4)
{
- u32_t regAddr = 0x9800 + (672 * 4) + 0x1000;
u32_t val;
val = ((u32_t)vpd_chain3[i+3]<<24) |
@@ -4584,7 +4581,6 @@ void zfHpSetRollCallTable(zdev_t* dev)
void zfHpSetTTSIFSTime(zdev_t* dev, u8_t sifs_time)
{
u32_t reg_value = 0;
- zmw_get_wlan_dev(dev);
sifs_time &= 0x3f;
reg_value = 0x14400b | (((u32_t)sifs_time)<<24);
diff --git a/drivers/staging/otus/hal/hpreg.c b/drivers/staging/otus/hal/hpreg.c
index d9894fe5f4e..178777c09db 100644
--- a/drivers/staging/otus/hal/hpreg.c
+++ b/drivers/staging/otus/hal/hpreg.c
@@ -786,45 +786,6 @@ enum {
WT1_5760_5800,
};
-static REG_DMN_FREQ_BAND regDmn5GhzTurboFreq[] = {
- { 5130, 5210, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_5130_5210 */
- { 5250, 5330, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0, 0}, /* T1_5250_5330 */
- { 5370, 5490, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_5370_5490 */
- { 5530, 5650, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0, 0}, /* T1_5530_5650 */
-
- { 5150, 5190, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_5150_5190 */
- { 5230, 5310, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0, 0}, /* T1_5230_5310 */
- { 5350, 5470, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_5350_5470 */
- { 5510, 5670, 5, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0, 0}, /* T1_5510_5670 */
-
- { 5200, 5240, 17, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_5200_5240 */
- { 5200, 5240, 23, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T2_5200_5240 */
- { 5210, 5210, 17, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_5210_5210 */
- { 5210, 5210, 23, 0, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T2_5210_5210 */
-
- { 5280, 5280, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0}, /* T1_5280_5280 */
- { 5280, 5280, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0}, /* T2_5280_5280 */
- { 5250, 5250, 17, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0}, /* T1_5250_5250 */
- { 5290, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0}, /* T1_5290_5290 */
- { 5250, 5290, 20, 0, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0}, /* T1_5250_5290 */
- { 5250, 5290, 23, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0}, /* T2_5250_5290 */
-
- { 5540, 5660, 20, 6, 40, 40, DFS_FCC3, PSCAN_FCC_T, 0, 0}, /* T1_5540_5660 */
- { 5760, 5800, 20, 0, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_5760_5800 */
- { 5760, 5800, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T2_5760_5800 */
-
- { 5765, 5805, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_5765_5805 */
-
- /*
- * Below are the WWR frequencies
- */
-
- { 5210, 5250, 15, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0, 0}, /* WT1_5210_5250 */
- { 5290, 5290, 18, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0, 0}, /* WT1_5290_5290 */
- { 5540, 5660, 20, 0, 40, 40, DFS_FCC3 | DFS_ETSI, PSCAN_WWR, 0, 0}, /* WT1_5540_5660 */
- { 5760, 5800, 20, 0, 40, 40, NO_DFS, PSCAN_WWR, 0, 0}, /* WT1_5760_5800 */
-};
-
/*
* 2GHz 11b channel tags
*/
@@ -864,45 +825,6 @@ enum {
W2_2484_2484,
};
-static REG_DMN_FREQ_BAND regDmn2GhzFreq[] = {
- { 2312, 2372, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* F1_2312_2372 */
- { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* F2_2312_2372 */
-
- { 2412, 2472, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* F1_2412_2472 */
- { 2412, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0, 0}, /* F2_2412_2472 */
- { 2412, 2472, 30, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* F3_2412_2472 */
-
- { 2412, 2462, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* F1_2412_2462 */
- { 2412, 2462, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA, 0, 0}, /* F2_2412_2462 */
- { 2432, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* F1_2432_2442 */
-
- { 2457, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* F1_2457_2472 */
-
- { 2467, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA2 | PSCAN_MKKA, 0, 0}, /* F1_2467_2472 */
-
- { 2484, 2484, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* F1_2484_2484 */
- { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_MKKA | PSCAN_MKKA1 | PSCAN_MKKA2, 0, 0}, /* F2_2484_2484 */
-
- { 2512, 2732, 5, 6, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* F1_2512_2732 */
-
- /*
- * WWR have powers opened up to 20dBm. Limits should often come from CTL/Max powers
- */
-
- { 2312, 2372, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* W1_2312_2372 */
- { 2412, 2412, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* W1_2412_2412 */
- { 2417, 2432, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* W1_2417_2432 */
- { 2437, 2442, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* W1_2437_2442 */
- { 2447, 2457, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* W1_2447_2457 */
- { 2462, 2462, 20, 0, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* W1_2462_2462 */
- { 2467, 2467, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0, 0}, /* W1_2467_2467 */
- { 2467, 2467, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0, 0}, /* W2_2467_2467 */
- { 2472, 2472, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0, 0}, /* W1_2472_2472 */
- { 2472, 2472, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0, 0}, /* W2_2472_2472 */
- { 2484, 2484, 20, 0, 20, 5, NO_DFS, PSCAN_WWR | IS_ECM_CHAN, 0, 0}, /* W1_2484_2484 */
- { 2484, 2484, 20, 0, 20, 5, NO_DFS, NO_PSCAN | IS_ECM_CHAN, 0, 0}, /* W2_2484_2484 */
-};
-
/*
* 2GHz 11g channel tags
@@ -984,16 +906,6 @@ enum {
T1_2512_2732
};
-static REG_DMN_FREQ_BAND regDmn2Ghz11gTurboFreq[] = {
- { 2312, 2372, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_2312_2372 */
- { 2437, 2437, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_2437_2437 */
- { 2437, 2437, 20, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T2_2437_2437 */
- { 2437, 2437, 18, 6, 40, 40, NO_DFS, PSCAN_WWR, 0, 0}, /* T3_2437_2437 */
- { 2512, 2732, 5, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* T1_2512_2732 */
-};
-
-
-
/*
* 2GHz 11n frequency tags
*/
@@ -1005,15 +917,6 @@ enum {
NG_DEMO_ALL_CHANNELS,
};
-static REG_DMN_FREQ_BAND regDmn2Ghz11ngFreq[] = {
- { 2422, 2452, 20, 0, 40, 5, NO_DFS, NO_PSCAN, 0, 0}, /* NG1_2422_2452 */
- { 2422, 2452, 27, 0, 40, 5, NO_DFS, NO_PSCAN, 0, 0}, /* NG2_2422_2452 */
- { 2422, 2452, 30, 0, 40, 5, NO_DFS, NO_PSCAN, 0, 0}, /* NG3_2422_2452 */
-
- { 2312, 2732, 27, 6, 20, 5, NO_DFS, NO_PSCAN, 0, 0}, /* NG_DEMO_ALL_CHANNELS */
-};
-
-
/*
* 5GHz 11n frequency tags
*/
@@ -1050,42 +953,6 @@ enum {
NA_DEMO_ALL_CHANNELS,
};
-static REG_DMN_FREQ_BAND regDmn5Ghz11naFreq[] = {
- /*
- * ToDo: This table needs to be completely populated with 5GHz 11n properties
- */
- { 5190, 5230, 15, 0, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA1_5190_5230 */
- { 5190, 5230, 17, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA2_5190_5230 */
- { 5190, 5230, 18, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA3_5190_5230 */
- { 5190, 5230, 20, 0, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA4_5190_5230 */
- { 5190, 5230, 23, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA5_5190_5230 */
-
- { 5270, 5270, 23, 6, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1}, /* NA1_5270_5270 */
-
- { 5270, 5310, 18, 6, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1}, /* NA1_5270_5310 */
- { 5270, 5310, 20, 0, 40, 40, DFS_FCC3|DFS_ETSI|DFS_MKK4, NO_PSCAN, 0, 1}, /* NA2_5270_5310 */
- { 5270, 5310, 23, 6, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1}, /* NA3_5270_5310 */
- { 5270, 5310, 30, 6, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1}, /* NA4_5270_5310 */
-
- { 5310, 5310, 17, 6, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1}, /* NA1_5310_5310 */
-
- { 5510, 5630, 30, 6, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1}, /* NA1_5510_5630 */
-
- { 5510, 5670, 20, 6, 40, 40, DFS_FCC3|DFS_ETSI|DFS_MKK4, NO_PSCAN, 0, 1}, /* NA1_5510_5670 */
- { 5510, 5670, 27, 0, 40, 40, DFS_FCC3|DFS_ETSI, NO_PSCAN, 0, 1}, /* NA2_5510_5670 */
- { 5510, 5670, 30, 6, 40, 40, DFS_FCC3, NO_PSCAN, 0, 1}, /* NA3_5510_5670 */
-
- { 5755, 5795, 17, 0, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA1_5755_5795 */
- { 5755, 5795, 20, 6, 40, 40, DFS_ETSI, NO_PSCAN, 0, 0}, /* NA2_5755_5795 */
- { 5755, 5795, 23, 0, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA3_5755_5795 */
- { 5755, 5795, 30, 0, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA4_5755_5795 */
- { 5755, 5795, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA5_5755_5795 */
-
- { 5795, 5795, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA1_5795_5795 */
-
- { 4920, 6100, 30, 6, 40, 40, NO_DFS, NO_PSCAN, 0, 0}, /* NA_DEMO_ALL_CHANNELS */
-};
-
typedef struct regDomain {
u16_t regDmnEnum; /* value from EnumRd table */
u8_t conformanceTestLimit;
diff --git a/drivers/staging/otus/hal/hprw.c b/drivers/staging/otus/hal/hprw.c
index d9fad47d5d5..4dbd5fb44b0 100644
--- a/drivers/staging/otus/hal/hprw.c
+++ b/drivers/staging/otus/hal/hprw.c
@@ -282,7 +282,6 @@ void zfIdlRsp(zdev_t* dev, u32_t* rsp, u16_t rspLen)
else if (src == ZM_OID_FLASH_READ)
{
u32_t datalen;
- u16_t i;
datalen = (rsp[0] & 255);
diff --git a/drivers/staging/otus/ioctl.c b/drivers/staging/otus/ioctl.c
index 6808e69fb35..8c47b1a6862 100644
--- a/drivers/staging/otus/ioctl.c
+++ b/drivers/staging/otus/ioctl.c
@@ -866,15 +866,15 @@ int usbdrvwext_giwscan(struct net_device *dev,
char *current_ev = extra;
char *end_buf;
int i;
- /* struct zsBssList BssList; */
- struct zsBssListV1 *pBssList = kmalloc(sizeof(struct zsBssListV1),
- GFP_KERNEL);
/* BssList = wd->sta.pBssList; */
/* zmw_get_wlan_dev(dev); */
if (macp->DeviceOpened != 1)
return 0;
+ /* struct zsBssList BssList; */
+ struct zsBssListV1 *pBssList = kmalloc(sizeof(struct zsBssListV1),
+ GFP_KERNEL);
if (data->length == 0)
end_buf = extra + IW_SCAN_MAX_DATA;
else
@@ -930,7 +930,7 @@ int usbdrvwext_siwessid(struct net_device *dev,
return -EINVAL;
if (essid->flags == 1) {
- if (essid->length > (IW_ESSID_MAX_SIZE + 1))
+ if (essid->length > IW_ESSID_MAX_SIZE)
return -E2BIG;
if (copy_from_user(&EssidBuf, essid->pointer, essid->length))
@@ -2227,7 +2227,8 @@ int usbdrv_wpa_ioctl(struct net_device *dev, struct athr_wlan_param *zdparm)
case ZD_CMD_SCAN_REQ:
printk(KERN_ERR "usbdrv_wpa_ioctl: ZD_CMD_SCAN_REQ\n");
break;
- case ZD_CMD_SET_GENERIC_ELEMENT:
+ case ZD_CMD_SET_GENERIC_ELEMENT: {
+ u8_t len, *wpaie;
printk(KERN_ERR "usbdrv_wpa_ioctl:"
" ZD_CMD_SET_GENERIC_ELEMENT\n");
@@ -2250,8 +2251,8 @@ int usbdrv_wpa_ioctl(struct net_device *dev, struct athr_wlan_param *zdparm)
/* zfiWlanSetWpaIe(dev, zdparm->u.generic_elem.data,
* zdparm->u.generic_elem.len);
*/
- u8_t len = zdparm->u.generic_elem.len;
- u8_t *wpaie = (u8_t *)zdparm->u.generic_elem.data;
+ len = zdparm->u.generic_elem.len;
+ wpaie = zdparm->u.generic_elem.data;
printk(KERN_ERR "wd->ap.wpaLen : % d\n", len);
@@ -2273,6 +2274,7 @@ int usbdrv_wpa_ioctl(struct net_device *dev, struct athr_wlan_param *zdparm)
* #endif
*/
break;
+ }
/* #ifdef ZM_HOSTAPD_SUPPORT */
case ZD_CMD_GET_TSC:
diff --git a/drivers/staging/otus/usbdrv.c b/drivers/staging/otus/usbdrv.c
index b0adbc8b2dc..5e6a12037b1 100644
--- a/drivers/staging/otus/usbdrv.c
+++ b/drivers/staging/otus/usbdrv.c
@@ -829,7 +829,7 @@ int zfLnxRegisterVapDev(struct net_device* parentDev, u16_t vapId)
{
/* Allocate net device structure */
vap[vapId].dev = alloc_etherdev(0);
- printk("Register vap dev=%x\n", (u32_t)vap[vapId].dev);
+ printk("Register vap dev=%p\n", vap[vapId].dev);
if(vap[vapId].dev == NULL) {
printk("alloc_etherdev fail\n");
@@ -883,7 +883,7 @@ int zfLnxUnregisterVapDev(struct net_device* parentDev, u16_t vapId)
printk("Unregister VAP dev : %s\n", vap[vapId].dev->name);
if(vap[vapId].dev != NULL) {
- printk("Unregister vap dev=%x\n", (u32_t)vap[vapId].dev);
+ printk("Unregister vap dev=%p\n", vap[vapId].dev);
//
//unregister_netdevice(wds[wdsId].dev);
unregister_netdev(vap[vapId].dev);
diff --git a/drivers/staging/otus/wrap_pkt.c b/drivers/staging/otus/wrap_pkt.c
index 75bb952fd0a..a2f5cb1f529 100644
--- a/drivers/staging/otus/wrap_pkt.c
+++ b/drivers/staging/otus/wrap_pkt.c
@@ -58,7 +58,7 @@ void zfLnxRecv80211(zdev_t *dev, zbuf_t *buf, struct zsAdditionInfo *addInfo)
skb1 = skb_copy(buf, GFP_ATOMIC);
if (skb1 != NULL) {
skb1->dev = dev;
- skb1->mac_header = skb1->data;
+ skb_reset_mac_header(skb1);
skb1->ip_summed = CHECKSUM_NONE;
skb1->pkt_type = PACKET_OTHERHOST;
/* ETH_P_80211_RAW */
@@ -85,13 +85,7 @@ void zfLnxRecvEth(zdev_t *dev, zbuf_t *buf, u16_t port)
/* new_buf = dev_alloc_skb(2048); */
new_buf = dev_alloc_skb(buf->len);
-#ifdef NET_SKBUFF_DATA_USES_OFFSET
- new_buf->tail = 0;
- new_buf->len = 0;
-#else
- new_buf->tail = new_buf->data;
- new_buf->len = 0;
-#endif
+ skb_reset_tail_pointer(new_buf);
skb_put(new_buf, buf->len);
memcpy(new_buf->data, buf->data, buf->len);
diff --git a/drivers/staging/otus/zdusb.c b/drivers/staging/otus/zdusb.c
index 2a6d937ba5e..4cd9b7f5a88 100644
--- a/drivers/staging/otus/zdusb.c
+++ b/drivers/staging/otus/zdusb.c
@@ -45,7 +45,7 @@ MODULE_LICENSE("Dual BSD/GPL");
static const char driver_name[] = "Otus";
/* table of devices that work with this driver */
-static struct usb_device_id zd1221_ids [] = {
+static const struct usb_device_id zd1221_ids[] = {
{ USB_DEVICE(VENDOR_ATHR, PRODUCT_AR9170) },
{ USB_DEVICE(VENDOR_DLINK, PRODUCT_DWA160A) },
{ USB_DEVICE(VENDOR_NETGEAR, PRODUCT_WNDA3100) },
diff --git a/drivers/staging/p9auth/Kconfig b/drivers/staging/p9auth/Kconfig
deleted file mode 100644
index d1c66d26202..00000000000
--- a/drivers/staging/p9auth/Kconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-config PLAN9AUTH
- tristate "Plan 9 style capability device implementation"
- default n
- depends on CRYPTO
- help
- This module implements the Plan 9 style capability device.
-
- To compile this driver as a module, choose
- M here: the module will be called p9auth.
diff --git a/drivers/staging/p9auth/Makefile b/drivers/staging/p9auth/Makefile
deleted file mode 100644
index 3ebf6ff0eef..00000000000
--- a/drivers/staging/p9auth/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_PLAN9AUTH) += p9auth.o
diff --git a/drivers/staging/p9auth/p9auth.c b/drivers/staging/p9auth/p9auth.c
deleted file mode 100644
index db796262121..00000000000
--- a/drivers/staging/p9auth/p9auth.c
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * Plan 9 style capability device implementation for the Linux Kernel
- *
- * Copyright 2008, 2009 Ashwin Ganti <ashwin.ganti@gmail.com>
- *
- * Released under the GPLv2
- *
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/moduleparam.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/cdev.h>
-#include <linux/uaccess.h>
-#include <linux/list.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/crypto.h>
-#include <linux/highmem.h>
-#include <linux/scatterlist.h>
-#include <linux/sched.h>
-#include <linux/cred.h>
-
-#ifndef CAP_MAJOR
-#define CAP_MAJOR 0
-#endif
-
-#ifndef CAP_NR_DEVS
-#define CAP_NR_DEVS 2 /* caphash and capuse */
-#endif
-
-#ifndef CAP_NODE_SIZE
-#define CAP_NODE_SIZE 20
-#endif
-
-#define MAX_DIGEST_SIZE 20
-
-struct cap_node {
- char data[CAP_NODE_SIZE];
- struct list_head list;
-};
-
-struct cap_dev {
- struct cap_node *head;
- int node_size;
- unsigned long size;
- struct semaphore sem;
- struct cdev cdev;
-};
-
-static int cap_major = CAP_MAJOR;
-static int cap_minor;
-static int cap_nr_devs = CAP_NR_DEVS;
-static int cap_node_size = CAP_NODE_SIZE;
-
-module_param(cap_major, int, S_IRUGO);
-module_param(cap_minor, int, S_IRUGO);
-module_param(cap_nr_devs, int, S_IRUGO);
-
-MODULE_AUTHOR("Ashwin Ganti");
-MODULE_LICENSE("GPL");
-
-static struct cap_dev *cap_devices;
-
-static void hexdump(unsigned char *buf, unsigned int len)
-{
- while (len--)
- printk("%02x", *buf++);
- printk("\n");
-}
-
-static char *cap_hash(char *plain_text, unsigned int plain_text_size,
- char *key, unsigned int key_size)
-{
- struct scatterlist sg;
- char *result;
- struct crypto_hash *tfm;
- struct hash_desc desc;
- int ret;
-
- tfm = crypto_alloc_hash("hmac(sha1)", 0, CRYPTO_ALG_ASYNC);
- if (IS_ERR(tfm)) {
- printk(KERN_ERR
- "failed to load transform for hmac(sha1): %ld\n",
- PTR_ERR(tfm));
- return NULL;
- }
-
- desc.tfm = tfm;
- desc.flags = 0;
-
- result = kzalloc(MAX_DIGEST_SIZE, GFP_KERNEL);
- if (!result) {
- printk(KERN_ERR "out of memory!\n");
- goto out;
- }
-
- sg_set_buf(&sg, plain_text, plain_text_size);
-
- ret = crypto_hash_setkey(tfm, key, key_size);
- if (ret) {
- printk(KERN_ERR "setkey() failed ret=%d\n", ret);
- kfree(result);
- result = NULL;
- goto out;
- }
-
- ret = crypto_hash_digest(&desc, &sg, plain_text_size, result);
- if (ret) {
- printk(KERN_ERR "digest () failed ret=%d\n", ret);
- kfree(result);
- result = NULL;
- goto out;
- }
-
- printk(KERN_DEBUG "crypto hash digest size %d\n",
- crypto_hash_digestsize(tfm));
- hexdump(result, MAX_DIGEST_SIZE);
-
-out:
- crypto_free_hash(tfm);
- return result;
-}
-
-static int cap_trim(struct cap_dev *dev)
-{
- struct cap_node *tmp;
- struct list_head *pos, *q;
- if (dev->head != NULL) {
- list_for_each_safe(pos, q, &(dev->head->list)) {
- tmp = list_entry(pos, struct cap_node, list);
- list_del(pos);
- kfree(tmp);
- }
- }
- return 0;
-}
-
-static int cap_open(struct inode *inode, struct file *filp)
-{
- struct cap_dev *dev;
- dev = container_of(inode->i_cdev, struct cap_dev, cdev);
- filp->private_data = dev;
-
- /* trim to 0 the length of the device if open was write-only */
- if ((filp->f_flags & O_ACCMODE) == O_WRONLY) {
- if (down_interruptible(&dev->sem))
- return -ERESTARTSYS;
- cap_trim(dev);
- up(&dev->sem);
- }
- /* initialise the head if it is NULL */
- if (dev->head == NULL) {
- dev->head = kmalloc(sizeof(struct cap_node), GFP_KERNEL);
- INIT_LIST_HEAD(&(dev->head->list));
- }
- return 0;
-}
-
-static int cap_release(struct inode *inode, struct file *filp)
-{
- return 0;
-}
-
-static ssize_t cap_write(struct file *filp, const char __user *buf,
- size_t count, loff_t *f_pos)
-{
- struct cap_node *node_ptr, *tmp;
- struct list_head *pos;
- struct cap_dev *dev = filp->private_data;
- ssize_t retval = -ENOMEM;
- struct cred *new;
- int len, target_int, source_int, flag = 0;
- char *user_buf, *user_buf_running, *source_user, *target_user,
- *rand_str, *hash_str, *result;
-
- if (down_interruptible(&dev->sem))
- return -ERESTARTSYS;
-
- user_buf_running = NULL;
- hash_str = NULL;
- node_ptr = kmalloc(sizeof(struct cap_node), GFP_KERNEL);
- user_buf = kzalloc(count+1, GFP_KERNEL);
- if (!node_ptr || !user_buf)
- goto out;
-
- if (copy_from_user(user_buf, buf, count)) {
- retval = -EFAULT;
- goto out;
- }
-
- /*
- * If the minor number is 0 ( /dev/caphash ) then simply add the
- * hashed capability supplied by the user to the list of hashes
- */
- if (0 == iminor(filp->f_dentry->d_inode)) {
- if (count > CAP_NODE_SIZE) {
- retval = -EINVAL;
- goto out;
- }
- printk(KERN_INFO "Capability being written to /dev/caphash : \n");
- hexdump(user_buf, count);
- memcpy(node_ptr->data, user_buf, count);
- list_add(&(node_ptr->list), &(dev->head->list));
- node_ptr = NULL;
- } else {
- char *tmpu;
- if (!cap_devices[0].head ||
- list_empty(&(cap_devices[0].head->list))) {
- retval = -EINVAL;
- goto out;
- }
- /*
- * break the supplied string into tokens with @ as the
- * delimiter If the string is "user1@user2@randomstring" we
- * need to split it and hash 'user1@user2' using 'randomstring'
- * as the key.
- */
- tmpu = user_buf_running = kstrdup(user_buf, GFP_KERNEL);
- source_user = strsep(&tmpu, "@");
- target_user = strsep(&tmpu, "@");
- rand_str = tmpu;
- if (!source_user || !target_user || !rand_str) {
- retval = -EINVAL;
- goto out;
- }
-
- /* hash the string user1@user2 with rand_str as the key */
- len = strlen(source_user) + strlen(target_user) + 1;
- /* src, @, len, \0 */
- hash_str = kzalloc(len+1, GFP_KERNEL);
- strcat(hash_str, source_user);
- strcat(hash_str, "@");
- strcat(hash_str, target_user);
-
- printk(KERN_ALERT "the source user is %s \n", source_user);
- printk(KERN_ALERT "the target user is %s \n", target_user);
-
- result = cap_hash(hash_str, len, rand_str, strlen(rand_str));
- if (NULL == result) {
- retval = -EFAULT;
- goto out;
- }
- memcpy(node_ptr->data, result, CAP_NODE_SIZE); /* why? */
- /* Change the process's uid if the hash is present in the
- * list of hashes
- */
- list_for_each(pos, &(cap_devices->head->list)) {
- /*
- * Change the user id of the process if the hashes
- * match
- */
- if (0 ==
- memcmp(result,
- list_entry(pos, struct cap_node,
- list)->data,
- CAP_NODE_SIZE)) {
- target_int = (unsigned int)
- simple_strtol(target_user, NULL, 0);
- source_int = (unsigned int)
- simple_strtol(source_user, NULL, 0);
- flag = 1;
-
- /*
- * Check whether the process writing to capuse
- * is actually owned by the source owner
- */
- if (source_int != current_uid()) {
- printk(KERN_ALERT
- "Process is not owned by the source user of the capability.\n");
- retval = -EFAULT;
- goto out;
- }
- /*
- * What all id's need to be changed here? uid,
- * euid, fsid, savedids ?? Currently I am
- * changing the effective user id since most of
- * the authorisation decisions are based on it
- */
- new = prepare_creds();
- if (!new) {
- retval = -ENOMEM;
- goto out;
- }
- new->uid = (uid_t) target_int;
- new->euid = (uid_t) target_int;
- retval = commit_creds(new);
- if (retval)
- goto out;
-
- /*
- * Remove the capability from the list and
- * break
- */
- tmp = list_entry(pos, struct cap_node, list);
- list_del(pos);
- kfree(tmp);
- break;
- }
- }
- if (0 == flag) {
- /*
- * The capability is not present in the list of the
- * hashes stored, hence return failure
- */
- printk(KERN_ALERT
- "Invalid capabiliy written to /dev/capuse \n");
- retval = -EFAULT;
- goto out;
- }
- }
- *f_pos += count;
- retval = count;
- /* update the size */
- if (dev->size < *f_pos)
- dev->size = *f_pos;
-
-out:
- kfree(node_ptr);
- kfree(user_buf);
- kfree(user_buf_running);
- kfree(hash_str);
- up(&dev->sem);
- return retval;
-}
-
-static const struct file_operations cap_fops = {
- .owner = THIS_MODULE,
- .write = cap_write,
- .open = cap_open,
- .release = cap_release,
-};
-
-/* no __exit here because it can be called by the init function */
-static void cap_cleanup_module(void)
-{
- int i;
- dev_t devno = MKDEV(cap_major, cap_minor);
- if (cap_devices) {
- for (i = 0; i < cap_nr_devs; i++) {
- cap_trim(cap_devices + i);
- cdev_del(&cap_devices[i].cdev);
- }
- kfree(cap_devices);
- }
- unregister_chrdev_region(devno, cap_nr_devs);
-
-}
-
-static void cap_setup_cdev(struct cap_dev *dev, int index)
-{
- int err, devno = MKDEV(cap_major, cap_minor + index);
- cdev_init(&dev->cdev, &cap_fops);
- dev->cdev.owner = THIS_MODULE;
- dev->cdev.ops = &cap_fops;
- err = cdev_add(&dev->cdev, devno, 1);
- if (err)
- printk(KERN_NOTICE "Error %d adding cap%d", err, index);
-}
-
-static int __init cap_init_module(void)
-{
- int result, i;
- dev_t dev = 0;
-
- if (cap_major) {
- dev = MKDEV(cap_major, cap_minor);
- result = register_chrdev_region(dev, cap_nr_devs, "cap");
- } else {
- result = alloc_chrdev_region(&dev, cap_minor, cap_nr_devs,
- "cap");
- cap_major = MAJOR(dev);
- }
-
- if (result < 0) {
- printk(KERN_WARNING "cap: can't get major %d\n",
- cap_major);
- return result;
- }
-
- cap_devices = kzalloc(cap_nr_devs * sizeof(struct cap_dev),
- GFP_KERNEL);
- if (!cap_devices) {
- result = -ENOMEM;
- goto fail;
- }
-
- /* Initialize each device. */
- for (i = 0; i < cap_nr_devs; i++) {
- cap_devices[i].node_size = cap_node_size;
- init_MUTEX(&cap_devices[i].sem);
- cap_setup_cdev(&cap_devices[i], i);
- }
-
- return 0;
-
-fail:
- cap_cleanup_module();
- return result;
-}
-
-module_init(cap_init_module);
-module_exit(cap_cleanup_module);
-
-
diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c
index 95c93e82cce..377884f3480 100644
--- a/drivers/staging/panel/panel.c
+++ b/drivers/staging/panel/panel.c
@@ -41,7 +41,6 @@
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
diff --git a/drivers/staging/phison/phison.c b/drivers/staging/phison/phison.c
index fcba78d2163..0c495eacb75 100644
--- a/drivers/staging/phison/phison.c
+++ b/drivers/staging/phison/phison.c
@@ -69,7 +69,7 @@ static int phison_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
return ret;
}
-static struct pci_device_id phison_pci_tbl[] = {
+static const struct pci_device_id phison_pci_tbl[] = {
{ PCI_VENDOR_ID_PHISON, PCI_DEVICE_ID_PS5000, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 0 },
{ 0, },
diff --git a/drivers/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c
index 11fc4d5c43e..63275529ff5 100644
--- a/drivers/staging/pohmelfs/inode.c
+++ b/drivers/staging/pohmelfs/inode.c
@@ -36,6 +36,7 @@
#define POHMELFS_MAGIC_NUM 0x504f482e
static struct kmem_cache *pohmelfs_inode_cache;
+static atomic_t psb_bdi_num = ATOMIC_INIT(0);
/*
* Removes inode from all trees, drops local name cache and removes all queued
@@ -322,7 +323,7 @@ int pohmelfs_write_create_inode(struct pohmelfs_inode *pi)
t = netfs_trans_alloc(psb, err + 1, 0, 0);
if (!t) {
err = -ENOMEM;
- goto err_out_put;
+ goto err_out_exit;
}
t->complete = pohmelfs_write_inode_complete;
t->private = igrab(inode);
@@ -395,7 +396,8 @@ int pohmelfs_remove_child(struct pohmelfs_inode *pi, struct pohmelfs_name *n)
/*
* Writeback for given inode.
*/
-static int pohmelfs_write_inode(struct inode *inode, int sync)
+static int pohmelfs_write_inode(struct inode *inode,
+ struct writeback_control *wbc)
{
struct pohmelfs_inode *pi = POHMELFS_I(inode);
@@ -1331,6 +1333,8 @@ static void pohmelfs_put_super(struct super_block *sb)
pohmelfs_crypto_exit(psb);
pohmelfs_state_exit(psb);
+ bdi_destroy(&psb->bdi);
+
kfree(psb);
sb->s_fs_info = NULL;
}
@@ -1767,8 +1771,7 @@ static int pohmelfs_show_stats(struct seq_file *m, struct vfsmount *mnt)
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));
+ seq_printf(m, "%pI4:%u", &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));
@@ -1815,11 +1818,22 @@ static int pohmelfs_fill_super(struct super_block *sb, void *data, int silent)
if (!psb)
goto err_out_exit;
+ err = bdi_init(&psb->bdi);
+ if (err)
+ goto err_out_free_sb;
+
+ err = bdi_register(&psb->bdi, NULL, "pfs-%d", atomic_inc_return(&psb_bdi_num));
+ if (err) {
+ bdi_destroy(&psb->bdi);
+ goto err_out_free_sb;
+ }
+
sb->s_fs_info = psb;
sb->s_op = &pohmelfs_sb_ops;
sb->s_magic = POHMELFS_MAGIC_NUM;
sb->s_maxbytes = MAX_LFS_FILESIZE;
sb->s_blocksize = PAGE_SIZE;
+ sb->s_bdi = &psb->bdi;
psb->sb = sb;
@@ -1863,11 +1877,11 @@ static int pohmelfs_fill_super(struct super_block *sb, void *data, int silent)
err = pohmelfs_parse_options((char *) data, psb, 0);
if (err)
- goto err_out_free_sb;
+ goto err_out_free_bdi;
err = pohmelfs_copy_crypto(psb);
if (err)
- goto err_out_free_sb;
+ goto err_out_free_bdi;
err = pohmelfs_state_init(psb);
if (err)
@@ -1916,6 +1930,8 @@ err_out_state_exit:
err_out_free_strings:
kfree(psb->cipher_string);
kfree(psb->hash_string);
+err_out_free_bdi:
+ bdi_destroy(&psb->bdi);
err_out_free_sb:
kfree(psb);
err_out_exit:
diff --git a/drivers/staging/pohmelfs/netfs.h b/drivers/staging/pohmelfs/netfs.h
index 623a07d29de..01cba006e07 100644
--- a/drivers/staging/pohmelfs/netfs.h
+++ b/drivers/staging/pohmelfs/netfs.h
@@ -18,6 +18,7 @@
#include <linux/types.h>
#include <linux/connector.h>
+#include <linux/backing-dev.h>
#define POHMELFS_CN_IDX 5
#define POHMELFS_CN_VAL 0
@@ -624,6 +625,8 @@ struct pohmelfs_sb {
struct super_block *sb;
+ struct backing_dev_info bdi;
+
/*
* Algorithm strings.
*/
diff --git a/drivers/staging/quatech_usb2/quatech_usb2.c b/drivers/staging/quatech_usb2/quatech_usb2.c
index f7726f1d364..1561f74a413 100644
--- a/drivers/staging/quatech_usb2/quatech_usb2.c
+++ b/drivers/staging/quatech_usb2/quatech_usb2.c
@@ -116,7 +116,7 @@ static int debug;
#define FOURTHCHAR ((unsigned char *)(urb->transfer_buffer))[i + 3]
#define FIFTHCHAR ((unsigned char *)(urb->transfer_buffer))[i + 4]
-static struct usb_device_id quausb2_id_table[] = {
+static const struct usb_device_id quausb2_id_table[] = {
{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU2_100)},
{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU2_100)},
{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU2_400)},
diff --git a/drivers/staging/ramzswap/Kconfig b/drivers/staging/ramzswap/Kconfig
index 24e25691fae..127b3c6c959 100644
--- a/drivers/staging/ramzswap/Kconfig
+++ b/drivers/staging/ramzswap/Kconfig
@@ -5,7 +5,7 @@ config RAMZSWAP
select LZO_DECOMPRESS
default n
help
- Creates virtual block devices which can be used (only) as a swap
+ Creates virtual block devices which can (only) be used as swap
disks. Pages swapped to these disks are compressed and stored in
memory itself.
diff --git a/drivers/staging/ramzswap/ramzswap.txt b/drivers/staging/ramzswap/ramzswap.txt
index e9f1619505a..9694acfeb43 100644
--- a/drivers/staging/ramzswap/ramzswap.txt
+++ b/drivers/staging/ramzswap/ramzswap.txt
@@ -5,9 +5,9 @@ Project home: http://compcache.googlecode.com/
* Introduction
-It creates RAM based block devices which can be used (only) as swap disks.
-Pages swapped to these devices are compressed and stored in memory itself.
-See project home for use cases, performance numbers and a lot more.
+The ramzswap module creates RAM based block devices which can (only) be used as
+swap disks. Pages swapped to these devices are compressed and stored in memory
+itself. See project home for use cases, performance numbers and a lot more.
Individual ramzswap devices are configured and initialized using rzscontrol
userspace utility as shown in examples below. See rzscontrol man page for more
diff --git a/drivers/staging/ramzswap/ramzswap_drv.c b/drivers/staging/ramzswap/ramzswap_drv.c
index 989fac5b01b..5e422e254ee 100644
--- a/drivers/staging/ramzswap/ramzswap_drv.c
+++ b/drivers/staging/ramzswap/ramzswap_drv.c
@@ -1,7 +1,7 @@
/*
* Compressed RAM based swap device
*
- * Copyright (C) 2008, 2009 Nitin Gupta
+ * Copyright (C) 2008, 2009, 2010 Nitin Gupta
*
* This code is released using a dual license strategy: BSD/GPL
* You can choose the licence that better fits your requirements.
@@ -24,12 +24,10 @@
#include <linux/genhd.h>
#include <linux/highmem.h>
#include <linux/lzo.h>
-#include <linux/mutex.h>
#include <linux/string.h>
#include <linux/swap.h>
#include <linux/swapops.h>
#include <linux/vmalloc.h>
-#include <linux/version.h>
#include "ramzswap_drv.h"
@@ -222,7 +220,7 @@ out:
return ret;
}
-void ramzswap_ioctl_get_stats(struct ramzswap *rzs,
+static void ramzswap_ioctl_get_stats(struct ramzswap *rzs,
struct ramzswap_ioctl_stats *s)
{
strncpy(s->backing_swap_name, rzs->backing_swap_name,
@@ -240,7 +238,8 @@ void ramzswap_ioctl_get_stats(struct ramzswap *rzs,
mem_used = xv_get_total_size_bytes(rzs->mem_pool)
+ (rs->pages_expand << PAGE_SHIFT);
- succ_writes = rs->num_writes - rs->failed_writes;
+ succ_writes = rzs_stat64_read(rzs, &rs->num_writes) -
+ rzs_stat64_read(rzs, &rs->failed_writes);
if (succ_writes && rs->pages_stored) {
good_compress_perc = rs->good_compress * 100
@@ -249,11 +248,12 @@ void ramzswap_ioctl_get_stats(struct ramzswap *rzs,
/ rs->pages_stored;
}
- s->num_reads = rs->num_reads;
- s->num_writes = rs->num_writes;
- s->failed_reads = rs->failed_reads;
- s->failed_writes = rs->failed_writes;
- s->invalid_io = rs->invalid_io;
+ s->num_reads = rzs_stat64_read(rzs, &rs->num_reads);
+ s->num_writes = rzs_stat64_read(rzs, &rs->num_writes);
+ s->failed_reads = rzs_stat64_read(rzs, &rs->failed_reads);
+ s->failed_writes = rzs_stat64_read(rzs, &rs->failed_writes);
+ s->invalid_io = rzs_stat64_read(rzs, &rs->invalid_io);
+ s->notify_free = rzs_stat64_read(rzs, &rs->notify_free);
s->pages_zero = rs->pages_zero;
s->good_compress_pct = good_compress_perc;
@@ -265,8 +265,8 @@ void ramzswap_ioctl_get_stats(struct ramzswap *rzs,
s->compr_data_size = rs->compr_size;
s->mem_used_total = mem_used;
- s->bdev_num_reads = rs->bdev_num_reads;
- s->bdev_num_writes = rs->bdev_num_writes;
+ s->bdev_num_reads = rzs_stat64_read(rzs, &rs->bdev_num_reads);
+ s->bdev_num_writes = rzs_stat64_read(rzs, &rs->bdev_num_writes);
}
#endif /* CONFIG_RAMZSWAP_STATS */
}
@@ -502,6 +502,14 @@ static int setup_backing_swap(struct ramzswap *rzs)
goto bad_param;
}
disksize = i_size_read(inode);
+ /*
+ * Can happen if user gives an extended partition as
+ * backing swap or simply a bad disk.
+ */
+ if (!disksize) {
+ pr_err("Error reading backing swap size.\n");
+ goto bad_param;
+ }
} else if (S_ISREG(inode->i_mode)) {
bdev = inode->i_sb->s_bdev;
if (IS_SWAPFILE(inode)) {
@@ -519,7 +527,6 @@ static int setup_backing_swap(struct ramzswap *rzs)
rzs->swap_file = swap_file;
rzs->backing_swap = bdev;
rzs->disksize = disksize;
- BUG_ON(!rzs->disksize);
return 0;
@@ -537,7 +544,7 @@ out:
* Map logical page number 'pagenum' to physical page number
* on backing swap device. For block device, this is a nop.
*/
-u32 map_backing_swap_page(struct ramzswap *rzs, u32 pagenum)
+static u32 map_backing_swap_page(struct ramzswap *rzs, u32 pagenum)
{
u32 skip_pages, entries_per_page;
size_t delta, se_offset, skipped;
@@ -593,9 +600,13 @@ static void ramzswap_free_page(struct ramzswap *rzs, size_t index)
u32 offset = rzs->table[index].offset;
if (unlikely(!page)) {
+ /*
+ * No memory is allocated for zero filled pages.
+ * Simply clear zero page flag.
+ */
if (rzs_test_flag(rzs, index, RZS_ZERO)) {
rzs_clear_flag(rzs, index, RZS_ZERO);
- stat_dec(rzs->stats.pages_zero);
+ rzs_stat_dec(&rzs->stats.pages_zero);
}
return;
}
@@ -604,7 +615,7 @@ static void ramzswap_free_page(struct ramzswap *rzs, size_t index)
clen = PAGE_SIZE;
__free_page(page);
rzs_clear_flag(rzs, index, RZS_UNCOMPRESSED);
- stat_dec(rzs->stats.pages_expand);
+ rzs_stat_dec(&rzs->stats.pages_expand);
goto out;
}
@@ -614,11 +625,11 @@ static void ramzswap_free_page(struct ramzswap *rzs, size_t index)
xv_free(rzs->mem_pool, page, offset);
if (clen <= PAGE_SIZE / 2)
- stat_dec(rzs->stats.good_compress);
+ rzs_stat_dec(&rzs->stats.good_compress);
out:
rzs->stats.compr_size -= clen;
- stat_dec(rzs->stats.pages_stored);
+ rzs_stat_dec(&rzs->stats.pages_stored);
rzs->table[index].page = NULL;
rzs->table[index].offset = 0;
@@ -664,7 +675,6 @@ static int handle_uncompressed_page(struct ramzswap *rzs, struct bio *bio)
return 0;
}
-
/*
* Called when request page is not present in ramzswap.
* Its either in backing swap device (if present) or
@@ -680,8 +690,8 @@ static int handle_ramzswap_fault(struct ramzswap *rzs, struct bio *bio)
*/
if (rzs->backing_swap) {
u32 pagenum;
- stat_dec(rzs->stats.num_reads);
- stat_inc(rzs->stats.bdev_num_reads);
+ rzs_stat64_dec(rzs, &rzs->stats.num_reads);
+ rzs_stat64_inc(rzs, &rzs->stats.bdev_num_reads);
bio->bi_bdev = rzs->backing_swap;
/*
@@ -719,7 +729,7 @@ static int ramzswap_read(struct ramzswap *rzs, struct bio *bio)
struct zobj_header *zheader;
unsigned char *user_mem, *cmem;
- stat_inc(rzs->stats.num_reads);
+ rzs_stat64_inc(rzs, &rzs->stats.num_reads);
page = bio->bi_io_vec[0].bv_page;
index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
@@ -731,7 +741,7 @@ static int ramzswap_read(struct ramzswap *rzs, struct bio *bio)
if (!rzs->table[index].page)
return handle_ramzswap_fault(rzs, bio);
- /* Page is stored uncompressed since its incompressible */
+ /* Page is stored uncompressed since it's incompressible */
if (unlikely(rzs_test_flag(rzs, index, RZS_UNCOMPRESSED)))
return handle_uncompressed_page(rzs, bio);
@@ -753,7 +763,7 @@ static int ramzswap_read(struct ramzswap *rzs, struct bio *bio)
if (unlikely(ret != LZO_E_OK)) {
pr_err("Decompression failed! err=%d, page=%u\n",
ret, index);
- stat_inc(rzs->stats.failed_reads);
+ rzs_stat64_inc(rzs, &rzs->stats.failed_reads);
goto out;
}
@@ -777,7 +787,7 @@ static int ramzswap_write(struct ramzswap *rzs, struct bio *bio)
struct page *page, *page_store;
unsigned char *user_mem, *cmem, *src;
- stat_inc(rzs->stats.num_writes);
+ rzs_stat64_inc(rzs, &rzs->stats.num_writes);
page = bio->bi_io_vec[0].bv_page;
index = bio->bi_sector >> SECTORS_PER_PAGE_SHIFT;
@@ -789,25 +799,16 @@ static int ramzswap_write(struct ramzswap *rzs, struct bio *bio)
* is no longer referenced by any process. So, its now safe
* to free the memory that was allocated for this page.
*/
- if (rzs->table[index].page)
+ if (rzs->table[index].page || rzs_test_flag(rzs, index, RZS_ZERO))
ramzswap_free_page(rzs, index);
- /*
- * No memory ia allocated for zero filled pages.
- * Simply clear zero page flag.
- */
- if (rzs_test_flag(rzs, index, RZS_ZERO)) {
- stat_dec(rzs->stats.pages_zero);
- rzs_clear_flag(rzs, index, RZS_ZERO);
- }
-
mutex_lock(&rzs->lock);
user_mem = kmap_atomic(page, KM_USER0);
if (page_zero_filled(user_mem)) {
kunmap_atomic(user_mem, KM_USER0);
mutex_unlock(&rzs->lock);
- stat_inc(rzs->stats.pages_zero);
+ rzs_stat_inc(&rzs->stats.pages_zero);
rzs_set_flag(rzs, index, RZS_ZERO);
set_bit(BIO_UPTODATE, &bio->bi_flags);
@@ -831,7 +832,7 @@ static int ramzswap_write(struct ramzswap *rzs, struct bio *bio)
if (unlikely(ret != LZO_E_OK)) {
mutex_unlock(&rzs->lock);
pr_err("Compression failed! err=%d\n", ret);
- stat_inc(rzs->stats.failed_writes);
+ rzs_stat64_inc(rzs, &rzs->stats.failed_writes);
goto out;
}
@@ -854,13 +855,13 @@ static int ramzswap_write(struct ramzswap *rzs, struct bio *bio)
mutex_unlock(&rzs->lock);
pr_info("Error allocating memory for incompressible "
"page: %u\n", index);
- stat_inc(rzs->stats.failed_writes);
+ rzs_stat64_inc(rzs, &rzs->stats.failed_writes);
goto out;
}
offset = 0;
rzs_set_flag(rzs, index, RZS_UNCOMPRESSED);
- stat_inc(rzs->stats.pages_expand);
+ rzs_stat_inc(&rzs->stats.pages_expand);
rzs->table[index].page = page_store;
src = kmap_atomic(page, KM_USER0);
goto memstore;
@@ -872,7 +873,7 @@ static int ramzswap_write(struct ramzswap *rzs, struct bio *bio)
mutex_unlock(&rzs->lock);
pr_info("Error allocating memory for compressed "
"page: %u, size=%zu\n", index, clen);
- stat_inc(rzs->stats.failed_writes);
+ rzs_stat64_inc(rzs, &rzs->stats.failed_writes);
if (rzs->backing_swap)
fwd_write_request = 1;
goto out;
@@ -901,9 +902,9 @@ memstore:
/* Update stats */
rzs->stats.compr_size += clen;
- stat_inc(rzs->stats.pages_stored);
+ rzs_stat_inc(&rzs->stats.pages_stored);
if (clen <= PAGE_SIZE / 2)
- stat_inc(rzs->stats.good_compress);
+ rzs_stat_inc(&rzs->stats.good_compress);
mutex_unlock(&rzs->lock);
@@ -913,7 +914,7 @@ memstore:
out:
if (fwd_write_request) {
- stat_inc(rzs->stats.bdev_num_writes);
+ rzs_stat64_inc(rzs, &rzs->stats.bdev_num_writes);
bio->bi_bdev = rzs->backing_swap;
#if 0
/*
@@ -941,7 +942,6 @@ out:
return 0;
}
-
/*
* Check if request is within bounds and page aligned.
*/
@@ -975,7 +975,7 @@ static int ramzswap_make_request(struct request_queue *queue, struct bio *bio)
}
if (!valid_swap_request(rzs, bio)) {
- stat_inc(rzs->stats.invalid_io);
+ rzs_stat64_inc(rzs, &rzs->stats.invalid_io);
bio_io_error(bio);
return 0;
}
@@ -1000,6 +1000,9 @@ static void reset_device(struct ramzswap *rzs)
unsigned entries_per_page;
unsigned long num_table_pages, entry = 0;
+ /* Do not accept any new I/O request */
+ rzs->init_done = 0;
+
if (rzs->backing_swap && !rzs->num_extents)
is_backing_blkdev = 1;
@@ -1066,6 +1069,7 @@ static void reset_device(struct ramzswap *rzs)
bd_release(rzs->backing_swap);
filp_close(rzs->swap_file, NULL);
rzs->backing_swap = NULL;
+ memset(rzs->backing_swap_name, 0, MAX_SWAP_NAME_LEN);
}
/* Reset stats */
@@ -1073,9 +1077,6 @@ static void reset_device(struct ramzswap *rzs)
rzs->disksize = 0;
rzs->memlimit = 0;
-
- /* Back to uninitialized state */
- rzs->init_done = 0;
}
static int ramzswap_ioctl_init_device(struct ramzswap *rzs)
@@ -1276,6 +1277,11 @@ static int ramzswap_ioctl(struct block_device *bdev, fmode_t mode,
ret = -EBUSY;
goto out;
}
+
+ /* Make sure all pending I/O is finished */
+ if (bdev)
+ fsync_bdev(bdev);
+
ret = ramzswap_ioctl_reset_device(rzs);
break;
@@ -1293,16 +1299,20 @@ static struct block_device_operations ramzswap_devops = {
.owner = THIS_MODULE,
};
-static void create_device(struct ramzswap *rzs, int device_id)
+static int create_device(struct ramzswap *rzs, int device_id)
{
+ int ret = 0;
+
mutex_init(&rzs->lock);
+ spin_lock_init(&rzs->stat64_lock);
INIT_LIST_HEAD(&rzs->backing_swap_extent_list);
rzs->queue = blk_alloc_queue(GFP_KERNEL);
if (!rzs->queue) {
pr_err("Error allocating disk queue for device %d\n",
device_id);
- return;
+ ret = -ENOMEM;
+ goto out;
}
blk_queue_make_request(rzs->queue, ramzswap_make_request);
@@ -1314,7 +1324,8 @@ static void create_device(struct ramzswap *rzs, int device_id)
blk_cleanup_queue(rzs->queue);
pr_warning("Error allocating disk structure for device %d\n",
device_id);
- return;
+ ret = -ENOMEM;
+ goto out;
}
rzs->disk->major = ramzswap_major;
@@ -1329,9 +1340,16 @@ static void create_device(struct ramzswap *rzs, int device_id)
* or set equal to backing swap device (if provided)
*/
set_capacity(rzs->disk, 0);
+
+ blk_queue_physical_block_size(rzs->disk->queue, PAGE_SIZE);
+ blk_queue_logical_block_size(rzs->disk->queue, PAGE_SIZE);
+
add_disk(rzs->disk);
rzs->init_done = 0;
+
+out:
+ return ret;
}
static void destroy_device(struct ramzswap *rzs)
@@ -1347,18 +1365,20 @@ static void destroy_device(struct ramzswap *rzs)
static int __init ramzswap_init(void)
{
- int i, ret;
+ int ret, dev_id;
if (num_devices > max_num_devices) {
pr_warning("Invalid value for num_devices: %u\n",
num_devices);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
ramzswap_major = register_blkdev(0, "ramzswap");
if (ramzswap_major <= 0) {
pr_warning("Unable to get major number\n");
- return -EBUSY;
+ ret = -EBUSY;
+ goto out;
}
if (!num_devices) {
@@ -1371,15 +1391,23 @@ static int __init ramzswap_init(void)
devices = kzalloc(num_devices * sizeof(struct ramzswap), GFP_KERNEL);
if (!devices) {
ret = -ENOMEM;
- goto out;
+ goto unregister;
}
- for (i = 0; i < num_devices; i++)
- create_device(&devices[i], i);
+ for (dev_id = 0; dev_id < num_devices; dev_id++) {
+ ret = create_device(&devices[dev_id], dev_id);
+ if (ret)
+ goto free_devices;
+ }
return 0;
-out:
+
+free_devices:
+ while (dev_id)
+ destroy_device(&devices[--dev_id]);
+unregister:
unregister_blkdev(ramzswap_major, "ramzswap");
+out:
return ret;
}
diff --git a/drivers/staging/ramzswap/ramzswap_drv.h b/drivers/staging/ramzswap/ramzswap_drv.h
index a6ea240935b..c7e0e767c22 100644
--- a/drivers/staging/ramzswap/ramzswap_drv.h
+++ b/drivers/staging/ramzswap/ramzswap_drv.h
@@ -1,7 +1,7 @@
/*
* Compressed RAM based swap device
*
- * Copyright (C) 2008, 2009 Nitin Gupta
+ * Copyright (C) 2008, 2009, 2010 Nitin Gupta
*
* This code is released using a dual license strategy: BSD/GPL
* You can choose the licence that better fits your requirements.
@@ -15,6 +15,9 @@
#ifndef _RAMZSWAP_DRV_H_
#define _RAMZSWAP_DRV_H_
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+
#include "ramzswap_ioctl.h"
#include "xvmalloc.h"
@@ -71,15 +74,6 @@ static const unsigned max_zpage_size_nobdev = PAGE_SIZE / 4 * 3;
#define SECTORS_PER_PAGE_SHIFT (PAGE_SHIFT - SECTOR_SHIFT)
#define SECTORS_PER_PAGE (1 << SECTORS_PER_PAGE_SHIFT)
-/* Debugging and Stats */
-#if defined(CONFIG_RAMZSWAP_STATS)
-#define stat_inc(stat) ((stat)++)
-#define stat_dec(stat) ((stat)--)
-#else
-#define stat_inc(x)
-#define stat_dec(x)
-#endif
-
/* Flags for ramzswap pages (table[page_no].flags) */
enum rzs_pageflags {
/* Page is stored uncompressed */
@@ -102,7 +96,7 @@ struct table {
u16 offset;
u8 count; /* object ref count (not yet used) */
u8 flags;
-} __attribute__((aligned(4)));;
+} __attribute__((aligned(4)));
/*
* Swap extent information in case backing swap is a regular
@@ -121,9 +115,10 @@ struct ramzswap_stats {
#if defined(CONFIG_RAMZSWAP_STATS)
u64 num_reads; /* failed + successful */
u64 num_writes; /* --do-- */
- u64 failed_reads; /* can happen when memory is too low */
- u64 failed_writes; /* should NEVER! happen */
+ u64 failed_reads; /* should NEVER! happen */
+ u64 failed_writes; /* can happen when memory is too low */
u64 invalid_io; /* non-swap I/O requests */
+ u64 notify_free; /* no. of swap slot free notifications */
u32 pages_zero; /* no. of zero filled pages */
u32 pages_stored; /* no. of pages currently stored */
u32 good_compress; /* % of pages with compression ratio<=50% */
@@ -138,6 +133,7 @@ struct ramzswap {
void *compress_workmem;
void *compress_buffer;
struct table *table;
+ spinlock_t stat64_lock; /* protect 64-bit stats */
struct mutex lock;
struct request_queue *queue;
struct gendisk *disk;
@@ -167,5 +163,48 @@ struct ramzswap {
/*-- */
-#endif
+/* Debugging and Stats */
+#if defined(CONFIG_RAMZSWAP_STATS)
+static void rzs_stat_inc(u32 *v)
+{
+ *v = *v + 1;
+}
+
+static void rzs_stat_dec(u32 *v)
+{
+ *v = *v - 1;
+}
+
+static void rzs_stat64_inc(struct ramzswap *rzs, u64 *v)
+{
+ spin_lock(&rzs->stat64_lock);
+ *v = *v + 1;
+ spin_unlock(&rzs->stat64_lock);
+}
+
+static void rzs_stat64_dec(struct ramzswap *rzs, u64 *v)
+{
+ spin_lock(&rzs->stat64_lock);
+ *v = *v - 1;
+ spin_unlock(&rzs->stat64_lock);
+}
+
+static u64 rzs_stat64_read(struct ramzswap *rzs, u64 *v)
+{
+ u64 val;
+
+ spin_lock(&rzs->stat64_lock);
+ val = *v;
+ spin_unlock(&rzs->stat64_lock);
+
+ return val;
+}
+#else
+#define rzs_stat_inc(v)
+#define rzs_stat_dec(v)
+#define rzs_stat64_inc(r, v)
+#define rzs_stat64_dec(r, v)
+#define rzs_stat64_read(r, v)
+#endif /* CONFIG_RAMZSWAP_STATS */
+#endif
diff --git a/drivers/staging/ramzswap/ramzswap_ioctl.h b/drivers/staging/ramzswap/ramzswap_ioctl.h
index c713a09af58..d26076d41bd 100644
--- a/drivers/staging/ramzswap/ramzswap_ioctl.h
+++ b/drivers/staging/ramzswap/ramzswap_ioctl.h
@@ -1,7 +1,7 @@
/*
* Compressed RAM based swap device
*
- * Copyright (C) 2008, 2009 Nitin Gupta
+ * Copyright (C) 2008, 2009, 2010 Nitin Gupta
*
* This code is released using a dual license strategy: BSD/GPL
* You can choose the licence that better fits your requirements.
@@ -24,9 +24,10 @@ struct ramzswap_ioctl_stats {
* size (if present) */
u64 num_reads; /* failed + successful */
u64 num_writes; /* --do-- */
- u64 failed_reads; /* can happen when memory is too low */
- u64 failed_writes; /* should NEVER! happen */
+ u64 failed_reads; /* should NEVER! happen */
+ u64 failed_writes; /* can happen when memory is too low */
u64 invalid_io; /* non-swap I/O requests */
+ u64 notify_free; /* no. of swap slot free notifications */
u32 pages_zero; /* no. of zero filled pages */
u32 good_compress_pct; /* no. of pages with compression ratio<=50% */
u32 pages_expand_pct; /* no. of incompressible pages */
diff --git a/drivers/staging/ramzswap/xvmalloc.c b/drivers/staging/ramzswap/xvmalloc.c
index b3e986c3314..3fdbb8ada82 100644
--- a/drivers/staging/ramzswap/xvmalloc.c
+++ b/drivers/staging/ramzswap/xvmalloc.c
@@ -1,7 +1,7 @@
/*
* xvmalloc memory allocator
*
- * Copyright (C) 2008, 2009 Nitin Gupta
+ * Copyright (C) 2008, 2009, 2010 Nitin Gupta
*
* This code is released using a dual license strategy: BSD/GPL
* You can choose the licence that better fits your requirements.
@@ -273,7 +273,7 @@ static void remove_block(struct xv_pool *pool, struct page *page, u32 offset,
}
/*
- * Allocate a page and add it freelist of given pool.
+ * Allocate a page and add it to freelist of given pool.
*/
static int grow_pool(struct xv_pool *pool, gfp_t flags)
{
diff --git a/drivers/staging/ramzswap/xvmalloc.h b/drivers/staging/ramzswap/xvmalloc.h
index 010c6fe5e17..5b1a81aa5fa 100644
--- a/drivers/staging/ramzswap/xvmalloc.h
+++ b/drivers/staging/ramzswap/xvmalloc.h
@@ -1,7 +1,7 @@
/*
* xvmalloc memory allocator
*
- * Copyright (C) 2008, 2009 Nitin Gupta
+ * Copyright (C) 2008, 2009, 2010 Nitin Gupta
*
* This code is released using a dual license strategy: BSD/GPL
* You can choose the licence that better fits your requirements.
diff --git a/drivers/staging/ramzswap/xvmalloc_int.h b/drivers/staging/ramzswap/xvmalloc_int.h
index 03c1a652a3a..e23ed5c8b8e 100644
--- a/drivers/staging/ramzswap/xvmalloc_int.h
+++ b/drivers/staging/ramzswap/xvmalloc_int.h
@@ -1,7 +1,7 @@
/*
* xvmalloc memory allocator
*
- * Copyright (C) 2008, 2009 Nitin Gupta
+ * Copyright (C) 2008, 2009, 2010 Nitin Gupta
*
* This code is released using a dual license strategy: BSD/GPL
* You can choose the licence that better fits your requirements.
@@ -62,7 +62,7 @@ struct link_free {
struct block_header {
union {
- /* This common header must be ALIGN bytes */
+ /* This common header must be XV_ALIGN bytes */
u8 common[XV_ALIGN];
struct {
u16 size;
diff --git a/drivers/staging/rar/Kconfig b/drivers/staging/rar/Kconfig
deleted file mode 100644
index 17f8bf3bb41..00000000000
--- a/drivers/staging/rar/Kconfig
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# RAR device configuration
-#
-
-menu "RAR Register Driver"
-#
-# Restricted Access Register Manager
-#
-config RAR_REGISTER
- tristate "Restricted Access Region Register Driver"
- default n
- ---help---
- This driver allows other kernel drivers access to the
- contents of the restricted access region control
- registers.
-
-endmenu
diff --git a/drivers/staging/rar/Makefile b/drivers/staging/rar/Makefile
deleted file mode 100644
index 5422ed04ccf..00000000000
--- a/drivers/staging/rar/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-EXTRA_CFLAGS += -DLITTLE__ENDIAN
-obj-$(CONFIG_RAR_REGISTER) += rar_driver.o
diff --git a/drivers/staging/rar/rar_driver.c b/drivers/staging/rar/rar_driver.c
deleted file mode 100644
index d85d1890e81..00000000000
--- a/drivers/staging/rar/rar_driver.c
+++ /dev/null
@@ -1,444 +0,0 @@
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/cdev.h>
-#include <linux/kdev_t.h>
-#include <linux/semaphore.h>
-#include <linux/mm.h>
-#include <linux/poll.h>
-#include <linux/wait.h>
-#include <linux/ioctl.h>
-#include <linux/ioport.h>
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/pagemap.h>
-#include <linux/pci.h>
-#include <linux/firmware.h>
-#include <linux/sched.h>
-#include "rar_driver.h"
-
-/* The following defines are for the IPC process to retrieve RAR in */
-
-/* === Lincroft Message Bus Interface === */
-/* Message Control Register */
-#define LNC_MCR_OFFSET 0xD0
-
-/* Message Data Register */
-#define LNC_MDR_OFFSET 0xD4
-
-/* Message Opcodes */
-#define LNC_MESSAGE_READ_OPCODE 0xD0
-#define LNC_MESSAGE_WRITE_OPCODE 0xE0
-
-/* Message Write Byte Enables */
-#define LNC_MESSAGE_BYTE_WRITE_ENABLES 0xF
-
-/* B-unit Port */
-#define LNC_BUNIT_PORT 0x3
-
-/* === Lincroft B-Unit Registers - Programmed by IA32 firmware === */
-#define LNC_BRAR0L 0x10
-#define LNC_BRAR0H 0x11
-#define LNC_BRAR1L 0x12
-#define LNC_BRAR1H 0x13
-
-/* Reserved for SeP */
-#define LNC_BRAR2L 0x14
-#define LNC_BRAR2H 0x15
-
-
-/* This structure is only used during module initialization. */
-struct RAR_offsets {
- int low; /* Register offset for low RAR physical address. */
- int high; /* Register offset for high RAR physical address. */
-};
-
-struct pci_dev *rar_dev;
-static uint32_t registered;
-
-/* Moorestown supports three restricted access regions. */
-#define MRST_NUM_RAR 3
-
-struct RAR_address_struct rar_addr[MRST_NUM_RAR];
-
-/* prototype for init */
-static int __init rar_init_handler(void);
-static void __exit rar_exit_handler(void);
-
-/*
- function that is activated on the successfull probe of the RAR device
-*/
-static int __devinit rar_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
-
-static struct pci_device_id rar_pci_id_tbl[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4110) },
- { 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, rar_pci_id_tbl);
-
-/* field for registering driver to PCI device */
-static struct pci_driver rar_pci_driver = {
- .name = "rar_driver",
- .id_table = rar_pci_id_tbl,
- .probe = rar_probe
-};
-
-/* This function is used to retrieved RAR info using the IPC message
- bus interface */
-static int memrar_get_rar_addr(struct pci_dev* pdev,
- int offset,
- u32 *addr)
-{
- /*
- * ======== The Lincroft Message Bus Interface ========
- * Lincroft registers may be obtained from the PCI
- * (the Host Bridge) using the Lincroft Message Bus
- * Interface. That message bus interface is generally
- * comprised of two registers: a control register (MCR, 0xDO)
- * and a data register (MDR, 0xD4).
- *
- * The MCR (message control register) format is the following:
- * 1. [31:24]: Opcode
- * 2. [23:16]: Port
- * 3. [15:8]: Register Offset
- * 4. [7:4]: Byte Enables (use 0xF to set all of these bits
- * to 1)
- * 5. [3:0]: reserved
- *
- * Read (0xD0) and write (0xE0) opcodes are written to the
- * control register when reading and writing to Lincroft
- * registers, respectively.
- *
- * We're interested in registers found in the Lincroft
- * B-unit. The B-unit port is 0x3.
- *
- * The six B-unit RAR register offsets we use are listed
- * earlier in this file.
- *
- * Lastly writing to the MCR register requires the "Byte
- * enables" bits to be set to 1. This may be achieved by
- * writing 0xF at bit 4.
- *
- * The MDR (message data register) format is the following:
- * 1. [31:0]: Read/Write Data
- *
- * Data being read from this register is only available after
- * writing the appropriate control message to the MCR
- * register.
- *
- * Data being written to this register must be written before
- * writing the appropriate control message to the MCR
- * register.
- */
-
- int result = 0; /* result */
- /* Construct control message */
- u32 const message =
- (LNC_MESSAGE_READ_OPCODE << 24)
- | (LNC_BUNIT_PORT << 16)
- | (offset << 8)
- | (LNC_MESSAGE_BYTE_WRITE_ENABLES << 4);
-
- printk(KERN_WARNING "rar- offset to LNC MSG is %x\n",offset);
-
- if (addr == 0)
- return -EINVAL;
-
- /* Send the control message */
- result = pci_write_config_dword(pdev,
- LNC_MCR_OFFSET,
- message);
-
- printk(KERN_WARNING "rar- result from send ctl register is %x\n"
- ,result);
-
- if (!result)
- result = pci_read_config_dword(pdev,
- LNC_MDR_OFFSET,
- addr);
-
- printk(KERN_WARNING "rar- result from read data register is %x\n",
- result);
-
- printk(KERN_WARNING "rar- value read from data register is %x\n",
- *addr);
-
- if (result)
- return -1;
- else
- return 0;
-}
-
-static int memrar_set_rar_addr(struct pci_dev* pdev,
- int offset,
- u32 addr)
-{
- /*
- * ======== The Lincroft Message Bus Interface ========
- * Lincroft registers may be obtained from the PCI
- * (the Host Bridge) using the Lincroft Message Bus
- * Interface. That message bus interface is generally
- * comprised of two registers: a control register (MCR, 0xDO)
- * and a data register (MDR, 0xD4).
- *
- * The MCR (message control register) format is the following:
- * 1. [31:24]: Opcode
- * 2. [23:16]: Port
- * 3. [15:8]: Register Offset
- * 4. [7:4]: Byte Enables (use 0xF to set all of these bits
- * to 1)
- * 5. [3:0]: reserved
- *
- * Read (0xD0) and write (0xE0) opcodes are written to the
- * control register when reading and writing to Lincroft
- * registers, respectively.
- *
- * We're interested in registers found in the Lincroft
- * B-unit. The B-unit port is 0x3.
- *
- * The six B-unit RAR register offsets we use are listed
- * earlier in this file.
- *
- * Lastly writing to the MCR register requires the "Byte
- * enables" bits to be set to 1. This may be achieved by
- * writing 0xF at bit 4.
- *
- * The MDR (message data register) format is the following:
- * 1. [31:0]: Read/Write Data
- *
- * Data being read from this register is only available after
- * writing the appropriate control message to the MCR
- * register.
- *
- * Data being written to this register must be written before
- * writing the appropriate control message to the MCR
- * register.
- */
-
- int result = 0; /* result */
-
- /* Construct control message */
- u32 const message =
- (LNC_MESSAGE_WRITE_OPCODE << 24)
- | (LNC_BUNIT_PORT << 16)
- | (offset << 8)
- | (LNC_MESSAGE_BYTE_WRITE_ENABLES << 4);
-
- printk(KERN_WARNING "rar- offset to LNC MSG is %x\n",offset);
-
- if (addr == 0)
- return -EINVAL;
-
- /* Send the control message */
- result = pci_write_config_dword(pdev,
- LNC_MDR_OFFSET,
- addr);
-
- printk(KERN_WARNING "rar- result from send ctl register is %x\n"
- ,result);
-
- if (!result)
- result = pci_write_config_dword(pdev,
- LNC_MCR_OFFSET,
- message);
-
- printk(KERN_WARNING "rar- result from write data register is %x\n",
- result);
-
- printk(KERN_WARNING "rar- value read to data register is %x\n",
- addr);
-
- if (result)
- return -1;
- else
- return 0;
-}
-
-/*
-
- * Initialize RAR parameters, such as physical addresses, etc.
-
- */
-static int memrar_init_rar_params(struct pci_dev *pdev)
-{
- struct RAR_offsets const offsets[] = {
- { LNC_BRAR0L, LNC_BRAR0H },
- { LNC_BRAR1L, LNC_BRAR1H },
- { LNC_BRAR2L, LNC_BRAR2H }
- };
-
- size_t const num_offsets = sizeof(offsets) / sizeof(offsets[0]);
- struct RAR_offsets const *end = offsets + num_offsets;
- struct RAR_offsets const *i;
- unsigned int n = 0;
- int result = 0;
-
- /* Retrieve RAR start and end physical addresses. */
-
- /*
- * Access the RAR registers through the Lincroft Message Bus
- * Interface on PCI device: 00:00.0 Host bridge.
- */
-
- /* struct pci_dev *pdev = pci_get_bus_and_slot(0, PCI_DEVFN(0,0)); */
-
- if (pdev == NULL)
- return -ENODEV;
-
- for (i = offsets; i != end; ++i, ++n) {
- if (memrar_get_rar_addr (pdev,
- (*i).low,
- &(rar_addr[n].low)) != 0
- || memrar_get_rar_addr (pdev,
- (*i).high,
- &(rar_addr[n].high)) != 0) {
- result = -1;
- break;
- }
- }
-
- /* Done accessing the device. */
- /* pci_dev_put(pdev); */
-
- if (result == 0) {
- if(1) {
- size_t z;
- for (z = 0; z != MRST_NUM_RAR; ++z) {
- printk(KERN_WARNING "rar - BRAR[%Zd] physical address low\n"
- "\tlow: 0x%08x\n"
- "\thigh: 0x%08x\n",
- z,
- rar_addr[z].low,
- rar_addr[z].high);
- }
- }
- }
-
- return result;
-}
-
-/*
- function that is activated on the successfull probe of the RAR device
-*/
-static int __devinit rar_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
- /* error */
- int error;
-
- /*------------------------
- CODE
- ---------------------------*/
-
- DEBUG_PRINT_0(RAR_DEBUG_LEVEL_EXTENDED,
- "Rar pci probe starting\n");
- error = 0;
-
- /* enable the device */
- error = pci_enable_device(pdev);
- if (error) {
- DEBUG_PRINT_0(RAR_DEBUG_LEVEL_EXTENDED,
- "error enabling pci device\n");
- goto end_function;
- }
-
- rar_dev = pdev;
- registered = 1;
-
- /* Initialize the RAR parameters, which have to be retrieved */
- /* via the message bus service */
- error=memrar_init_rar_params(rar_dev);
-
- if (error) {
- DEBUG_PRINT_0(RAR_DEBUG_LEVEL_EXTENDED,
- "error getting RAR addresses device\n");
- registered = 0;
- goto end_function;
- }
-
-end_function:
-
- return error;
-}
-
-/*
- this function registers th driver to
- the device subsystem( either PCI, USB, etc)
-*/
-static int __init rar_init_handler(void)
-{
- return pci_register_driver(&rar_pci_driver);
-}
-
-static void __exit rar_exit_handler(void)
-{
- pci_unregister_driver(&rar_pci_driver);
-}
-
-module_init(rar_init_handler);
-module_exit(rar_exit_handler);
-
-MODULE_LICENSE("GPL");
-
-
-/* The get_rar_address function is used by other device drivers
- * to obtain RAR address information on a RAR. It takes two
- * parameter:
- *
- * int rar_index
- * The rar_index is an index to the rar for which you wish to retrieve
- * the address information.
- * Values can be 0,1, or 2.
- *
- * struct RAR_address_struct is a pointer to a place to which the function
- * can return the address structure for the RAR.
- *
- * The function returns a 0 upon success or a -1 if there is no RAR
- * facility on this system.
- */
-int get_rar_address(int rar_index,struct RAR_address_struct *addresses)
-{
- if (registered && (rar_index < 3) && (rar_index >= 0)) {
- *addresses=rar_addr[rar_index];
- /* strip off lock bit information */
- addresses->low = addresses->low & 0xfffffff0;
- addresses->high = addresses->high & 0xfffffff0;
- return 0;
- }
-
- else {
- return -ENODEV;
- }
-}
-
-
-EXPORT_SYMBOL(get_rar_address);
-
-/* The lock_rar function is ued by other device drivers to lock an RAR.
- * once an RAR is locked, it stays locked until the next system reboot.
- * The function takes one parameter:
- *
- * int rar_index
- * The rar_index is an index to the rar that you want to lock.
- * Values can be 0,1, or 2.
- *
- * The function returns a 0 upon success or a -1 if there is no RAR
- * facility on this system.
- */
-int lock_rar(int rar_index)
-{
- u32 working_addr;
- int result;
-if (registered && (rar_index < 3) && (rar_index >= 0)) {
- /* first make sure that lock bits are clear (this does lock) */
- working_addr=rar_addr[rar_index].low & 0xfffffff0;
-
- /* now send that value to the register using the IPC */
- result=memrar_set_rar_addr(rar_dev,rar_index,working_addr);
- return result;
- }
-
-else {
- return -ENODEV;
- }
-}
diff --git a/drivers/staging/rar/rar_driver.h b/drivers/staging/rar/rar_driver.h
deleted file mode 100644
index 3690f984ff5..00000000000
--- a/drivers/staging/rar/rar_driver.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* === RAR Physical Addresses === */
-struct RAR_address_struct {
- u32 low;
- u32 high;
-};
-
-/* The get_rar_address function is used by other device drivers
- * to obtain RAR address information on a RAR. It takes two
- * parameter:
- *
- * int rar_index
- * The rar_index is an index to the rar for which you wish to retrieve
- * the address information.
- * Values can be 0,1, or 2.
- *
- * struct RAR_address_struct is a pointer to a place to which the function
- * can return the address structure for the RAR.
- *
- * The function returns a 0 upon success or a -1 if there is no RAR
- * facility on this system.
- */
-int get_rar_address(int rar_index,struct RAR_address_struct *addresses);
-
-
-/* The lock_rar function is ued by other device drivers to lock an RAR.
- * once an RAR is locked, it stays locked until the next system reboot.
- * The function takes one parameter:
- *
- * int rar_index
- * The rar_index is an index to the rar that you want to lock.
- * Values can be 0,1, or 2.
- *
- * The function returns a 0 upon success or a -1 if there is no RAR
- * facility on this system.
- */
-int lock_rar(int rar_index);
-
-
-/* DEBUG LEVEL MASKS */
-#define RAR_DEBUG_LEVEL_BASIC 0x1
-
-#define RAR_DEBUG_LEVEL_REGISTERS 0x2
-
-#define RAR_DEBUG_LEVEL_EXTENDED 0x4
-
-#define DEBUG_LEVEL 0x7
-
-/* FUNCTIONAL MACROS */
-
-/* debug macro without paramaters */
-#define DEBUG_PRINT_0(DEBUG_LEVEL , info) \
-do \
-{ \
- if(DEBUG_LEVEL) \
- { \
- printk(KERN_WARNING info); \
- } \
-}while(0)
-
-/* debug macro with 1 paramater */
-#define DEBUG_PRINT_1(DEBUG_LEVEL , info , param1) \
-do \
-{ \
- if(DEBUG_LEVEL) \
- { \
- printk(KERN_WARNING info , param1); \
- } \
-}while(0)
-
-/* debug macro with 2 paramaters */
-#define DEBUG_PRINT_2(DEBUG_LEVEL , info , param1, param2) \
-do \
-{ \
- if(DEBUG_LEVEL) \
- { \
- printk(KERN_WARNING info , param1, param2); \
- } \
-}while(0)
-
-/* debug macro with 3 paramaters */
-#define DEBUG_PRINT_3(DEBUG_LEVEL , info , param1, param2 , param3) \
-do \
-{ \
- if(DEBUG_LEVEL) \
- { \
- printk(KERN_WARNING info , param1, param2 , param3); \
- } \
-}while(0)
-
-/* debug macro with 4 paramaters */
-#define DEBUG_PRINT_4(DEBUG_LEVEL , info , param1, param2 , param3 , param4) \
-do \
-{ \
- if(DEBUG_LEVEL) \
- { \
- printk(KERN_WARNING info , param1, param2 , param3 , param4); \
- } \
-}while(0)
-
diff --git a/drivers/staging/rar_register/Kconfig b/drivers/staging/rar_register/Kconfig
new file mode 100644
index 00000000000..3f73839643e
--- /dev/null
+++ b/drivers/staging/rar_register/Kconfig
@@ -0,0 +1,30 @@
+#
+# RAR device configuration
+#
+
+menu "RAR Register Driver"
+#
+# Restricted Access Register Manager
+#
+config RAR_REGISTER
+ tristate "Restricted Access Region Register Driver"
+ default n
+ ---help---
+ This driver allows other kernel drivers access to the
+ contents of the restricted access region control
+ registers.
+
+ The restricted access region control registers
+ (rar_registers) are used to pass address and
+ locking information on restricted access regions
+ to other drivers that use restricted access regions
+
+ The restricted access regions are regions of memory
+ on the Intel MID Platform that are not accessible to
+ the x86 processor, but are accessible to dedicated
+ processors on board peripheral devices.
+
+ The purpose of the restricted access regions is to
+ protect sensitive data from compromise by unauthorized
+ programs running on the x86 processor.
+endmenu
diff --git a/drivers/staging/rar_register/Makefile b/drivers/staging/rar_register/Makefile
new file mode 100644
index 00000000000..d5954ccc16c
--- /dev/null
+++ b/drivers/staging/rar_register/Makefile
@@ -0,0 +1,2 @@
+EXTRA_CFLAGS += -DLITTLE__ENDIAN
+obj-$(CONFIG_RAR_REGISTER) += rar_register.o
diff --git a/drivers/staging/rar_register/rar_register.c b/drivers/staging/rar_register/rar_register.c
new file mode 100644
index 00000000000..bfc0e31f1a6
--- /dev/null
+++ b/drivers/staging/rar_register/rar_register.c
@@ -0,0 +1,615 @@
+/*
+ * rar_register.c - An Intel Restricted Access Region register driver
+ *
+ * Copyright(c) 2009 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * -------------------------------------------------------------------
+ * 20091204 Mark Allyn <mark.a.allyn@intel.com>
+ * Ossama Othman <ossama.othman@intel.com>
+ * Cleanup per feedback from Alan Cox and Arjan Van De Ven
+ *
+ * 20090806 Ossama Othman <ossama.othman@intel.com>
+ * Return zero high address if upper 22 bits is zero.
+ * Cleaned up checkpatch errors.
+ * Clarified that driver is dealing with bus addresses.
+ *
+ * 20090702 Ossama Othman <ossama.othman@intel.com>
+ * Removed unnecessary include directives
+ * Cleaned up spinlocks.
+ * Cleaned up logging.
+ * Improved invalid parameter checks.
+ * Fixed and simplified RAR address retrieval and RAR locking
+ * code.
+ *
+ * 20090626 Mark Allyn <mark.a.allyn@intel.com>
+ * Initial publish
+ */
+
+#define DEBUG 1
+
+#include "rar_register.h"
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+
+/* === Lincroft Message Bus Interface === */
+/* Message Control Register */
+#define LNC_MCR_OFFSET 0xD0
+
+/* Maximum number of clients (other drivers using this driver) */
+#define MAX_RAR_CLIENTS 10
+
+/* Message Data Register */
+#define LNC_MDR_OFFSET 0xD4
+
+/* Message Opcodes */
+#define LNC_MESSAGE_READ_OPCODE 0xD0
+#define LNC_MESSAGE_WRITE_OPCODE 0xE0
+
+/* Message Write Byte Enables */
+#define LNC_MESSAGE_BYTE_WRITE_ENABLES 0xF
+
+/* B-unit Port */
+#define LNC_BUNIT_PORT 0x3
+
+/* === Lincroft B-Unit Registers - Programmed by IA32 firmware === */
+#define LNC_BRAR0L 0x10
+#define LNC_BRAR0H 0x11
+#define LNC_BRAR1L 0x12
+#define LNC_BRAR1H 0x13
+
+/* Reserved for SeP */
+#define LNC_BRAR2L 0x14
+#define LNC_BRAR2H 0x15
+
+/* Moorestown supports three restricted access regions. */
+#define MRST_NUM_RAR 3
+
+
+/* RAR Bus Address Range */
+struct RAR_address_range {
+ dma_addr_t low;
+ dma_addr_t high;
+};
+
+/* Structure containing low and high RAR register offsets. */
+struct RAR_offsets {
+ u32 low; /* Register offset for low RAR bus address. */
+ u32 high; /* Register offset for high RAR bus address. */
+};
+
+struct client {
+ int (*client_callback)(void *client_data);
+ void *customer_data;
+ int client_called;
+ };
+
+static DEFINE_MUTEX(rar_mutex);
+static DEFINE_MUTEX(lnc_reg_mutex);
+
+struct RAR_device {
+ struct RAR_offsets const rar_offsets[MRST_NUM_RAR];
+ struct RAR_address_range rar_addr[MRST_NUM_RAR];
+ struct pci_dev *rar_dev;
+ bool registered;
+ };
+
+/* this platform has only one rar_device for 3 rar regions */
+static struct RAR_device my_rar_device = {
+ .rar_offsets = {
+ [0].low = LNC_BRAR0L,
+ [0].high = LNC_BRAR0H,
+ [1].low = LNC_BRAR1L,
+ [1].high = LNC_BRAR1H,
+ [2].low = LNC_BRAR2L,
+ [2].high = LNC_BRAR2H
+ }
+};
+
+/* this data is for handling requests from other drivers which arrive
+ * prior to this driver initializing
+ */
+
+static struct client clients[MAX_RAR_CLIENTS];
+static int num_clients;
+
+/*
+ * This function is used to retrieved RAR info using the Lincroft
+ * message bus interface.
+ */
+static int retrieve_rar_addr(struct pci_dev *pdev,
+ int offset,
+ dma_addr_t *addr)
+{
+ /*
+ * ======== The Lincroft Message Bus Interface ========
+ * Lincroft registers may be obtained from the PCI
+ * (the Host Bridge) using the Lincroft Message Bus
+ * Interface. That message bus interface is generally
+ * comprised of two registers: a control register (MCR, 0xDO)
+ * and a data register (MDR, 0xD4).
+ *
+ * The MCR (message control register) format is the following:
+ * 1. [31:24]: Opcode
+ * 2. [23:16]: Port
+ * 3. [15:8]: Register Offset
+ * 4. [7:4]: Byte Enables (use 0xF to set all of these bits
+ * to 1)
+ * 5. [3:0]: reserved
+ *
+ * Read (0xD0) and write (0xE0) opcodes are written to the
+ * control register when reading and writing to Lincroft
+ * registers, respectively.
+ *
+ * We're interested in registers found in the Lincroft
+ * B-unit. The B-unit port is 0x3.
+ *
+ * The six B-unit RAR register offsets we use are listed
+ * earlier in this file.
+ *
+ * Lastly writing to the MCR register requires the "Byte
+ * enables" bits to be set to 1. This may be achieved by
+ * writing 0xF at bit 4.
+ *
+ * The MDR (message data register) format is the following:
+ * 1. [31:0]: Read/Write Data
+ *
+ * Data being read from this register is only available after
+ * writing the appropriate control message to the MCR
+ * register.
+ *
+ * Data being written to this register must be written before
+ * writing the appropriate control message to the MCR
+ * register.
+ */
+
+ int result;
+
+ /* Construct control message */
+ u32 const message =
+ (LNC_MESSAGE_READ_OPCODE << 24)
+ | (LNC_BUNIT_PORT << 16)
+ | (offset << 8)
+ | (LNC_MESSAGE_BYTE_WRITE_ENABLES << 4);
+
+ dev_dbg(&pdev->dev, "Offset for 'get' LNC MSG is %x\n", offset);
+
+ if (addr == 0) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ /*
+ * We synchronize access to the Lincroft MCR and MDR registers
+ * until BOTH the command is issued through the MCR register
+ * and the corresponding data is read from the MDR register.
+ * Otherwise a race condition would exist between accesses to
+ * both registers.
+ */
+
+ mutex_lock(&lnc_reg_mutex);
+
+ /* Send the control message */
+ result = pci_write_config_dword(pdev, LNC_MCR_OFFSET, message);
+
+ dev_dbg(&pdev->dev, "Result from send ctl register is %x\n", result);
+
+ if (!result) {
+ result = pci_read_config_dword(pdev, LNC_MDR_OFFSET,
+ (u32 *)addr);
+ dev_dbg(&pdev->dev,
+ "Result from read data register is %x\n", result);
+
+ dev_dbg(&pdev->dev,
+ "Value read from data register is %lx\n",
+ (unsigned long)*addr);
+ }
+
+ mutex_unlock(&lnc_reg_mutex);
+
+ return result;
+}
+
+static int set_rar_address(struct pci_dev *pdev,
+ int offset,
+ dma_addr_t addr)
+{
+ /*
+ * Data being written to this register must be written before
+ * writing the appropriate control message to the MCR
+ * register.
+ * @note See rar_get_address() for a description of the
+ * message bus interface being used here.
+ */
+
+ int result = 0;
+
+ /* Construct control message */
+ u32 const message = (LNC_MESSAGE_WRITE_OPCODE << 24)
+ | (LNC_BUNIT_PORT << 16)
+ | (offset << 8)
+ | (LNC_MESSAGE_BYTE_WRITE_ENABLES << 4);
+
+ if (addr == 0) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ dev_dbg(&pdev->dev, "Offset for 'set' LNC MSG is %x\n", offset);
+
+ /*
+ * We synchronize access to the Lincroft MCR and MDR registers
+ * until BOTH the command is issued through the MCR register
+ * and the corresponding data is read from the MDR register.
+ * Otherwise a race condition would exist between accesses to
+ * both registers.
+ */
+
+ mutex_lock(&lnc_reg_mutex);
+
+ /* Send the control message */
+ result = pci_write_config_dword(pdev, LNC_MDR_OFFSET, addr);
+
+ dev_dbg(&pdev->dev, "Result from write data register is %x\n", result);
+
+ if (!result) {
+ dev_dbg(&pdev->dev,
+ "Value written to data register is %lx\n",
+ (unsigned long)addr);
+
+ result = pci_write_config_dword(pdev, LNC_MCR_OFFSET, message);
+
+ dev_dbg(&pdev->dev, "Result from send ctl register is %x\n",
+ result);
+ }
+
+ mutex_unlock(&lnc_reg_mutex);
+
+ return result;
+}
+
+/*
+* Initialize RAR parameters, such as bus addresses, etc.
+*/
+static int init_rar_params(struct pci_dev *pdev)
+{
+ unsigned int i;
+ int result = 0;
+
+ /* Retrieve RAR start and end bus addresses.
+ * Access the RAR registers through the Lincroft Message Bus
+ * Interface on PCI device: 00:00.0 Host bridge.
+ */
+
+ for (i = 0; i < MRST_NUM_RAR; ++i) {
+ struct RAR_offsets const *offset =
+ &my_rar_device.rar_offsets[i];
+ struct RAR_address_range *addr = &my_rar_device.rar_addr[i];
+
+ if ((retrieve_rar_addr(pdev, offset->low, &addr->low) != 0)
+ || (retrieve_rar_addr(pdev, offset->high, &addr->high) != 0)) {
+ result = -1;
+ break;
+ }
+
+ /*
+ * Only the upper 22 bits of the RAR addresses are
+ * stored in their corresponding RAR registers so we
+ * must set the lower 10 bits accordingly.
+
+ * The low address has its lower 10 bits cleared, and
+ * the high address has all its lower 10 bits set,
+ * e.g.:
+ * low = 0x2ffffc00
+ */
+
+ addr->low &= (dma_addr_t)0xfffffc00u;
+
+ /*
+ * Set bits 9:0 on uppser address if bits 31:10 are non
+ * zero; otherwize clear all bits
+ */
+
+ if ((addr->high & 0xfffffc00u) == 0)
+ addr->high = 0;
+ else
+ addr->high |= 0x3ffu;
+ }
+ /* Done accessing the device. */
+
+ if (result == 0) {
+ int z;
+ for (z = 0; z != MRST_NUM_RAR; ++z) {
+ /*
+ * "BRAR" refers to the RAR registers in the
+ * Lincroft B-unit.
+ */
+ dev_info(&pdev->dev, "BRAR[%u] bus address range = "
+ "[%lx, %lx]\n", z,
+ (unsigned long)my_rar_device.rar_addr[z].low,
+ (unsigned long)my_rar_device.rar_addr[z].high);
+ }
+ }
+
+ return result;
+}
+
+/*
+ * The rar_get_address function is used by other device drivers
+ * to obtain RAR address information on a RAR. It takes three
+ * parameters:
+ *
+ * int rar_index
+ * The rar_index is an index to the rar for which you wish to retrieve
+ * the address information.
+ * Values can be 0,1, or 2.
+ *
+ * The function returns a 0 upon success or a -1 if there is no RAR
+ * facility on this system.
+ */
+int rar_get_address(int rar_index,
+ dma_addr_t *start_address,
+ dma_addr_t *end_address)
+{
+ int result = -ENODEV;
+
+ if (my_rar_device.registered) {
+ if (start_address == 0 || end_address == 0
+ || rar_index >= MRST_NUM_RAR || rar_index < 0) {
+ result = -EINVAL;
+ } else {
+ *start_address =
+ my_rar_device.rar_addr[rar_index].low;
+ *end_address =
+ my_rar_device.rar_addr[rar_index].high;
+
+ result = 0;
+ }
+ }
+
+ return result;
+}
+EXPORT_SYMBOL(rar_get_address);
+
+/*
+ * The rar_lock function is ued by other device drivers to lock an RAR.
+ * once an RAR is locked, it stays locked until the next system reboot.
+ * The function takes one parameter:
+ *
+ * int rar_index
+ * The rar_index is an index to the rar that you want to lock.
+ * Values can be 0,1, or 2.
+ *
+ * The function returns a 0 upon success or a -1 if there is no RAR
+ * facility on this system.
+ */
+int rar_lock(int rar_index)
+{
+ int result = -ENODEV;
+
+ if (rar_index >= MRST_NUM_RAR || rar_index < 0) {
+ result = -EINVAL;
+ return result;
+ }
+
+ dev_dbg(&my_rar_device.rar_dev->dev, "rar_lock mutex locking\n");
+ mutex_lock(&rar_mutex);
+
+ if (my_rar_device.registered) {
+
+ dma_addr_t low = my_rar_device.rar_addr[rar_index].low &
+ 0xfffffc00u;
+
+ dma_addr_t high = my_rar_device.rar_addr[rar_index].high &
+ 0xfffffc00u;
+
+ /*
+ * Only allow I/O from the graphics and Langwell;
+ * Not from the x96 processor
+ */
+ if (rar_index == (int)RAR_TYPE_VIDEO) {
+ low |= 0x00000009;
+ high |= 0x00000015;
+ }
+
+ else if (rar_index == (int)RAR_TYPE_AUDIO) {
+ /* Only allow I/O from Langwell; nothing from x86 */
+ low |= 0x00000008;
+ high |= 0x00000018;
+ }
+
+ else
+ /* Read-only from all agents */
+ high |= 0x00000018;
+
+ /*
+ * Now program the register using the Lincroft message
+ * bus interface.
+ */
+ result = set_rar_address(my_rar_device.rar_dev,
+ my_rar_device.rar_offsets[rar_index].low,
+ low);
+
+ if (result == 0)
+ result = set_rar_address(
+ my_rar_device.rar_dev,
+ my_rar_device.rar_offsets[rar_index].high,
+ high);
+ }
+
+ dev_dbg(&my_rar_device.rar_dev->dev, "rar_lock mutex unlocking\n");
+ mutex_unlock(&rar_mutex);
+ return result;
+}
+EXPORT_SYMBOL(rar_lock);
+
+/* The register_rar function is to used by other device drivers
+ * to ensure that this driver is ready. As we cannot be sure of
+ * the compile/execute order of dirvers in ther kernel, it is
+ * best to give this driver a callback function to call when
+ * it is ready to give out addresses. The callback function
+ * would have those steps that continue the initialization of
+ * a driver that do require a valid RAR address. One of those
+ * steps would be to call rar_get_address()
+ * This function return 0 on success an -1 on failure.
+*/
+int register_rar(int (*callback)(void *yourparameter), void *yourparameter)
+{
+
+ int result = -ENODEV;
+
+ if (callback == NULL)
+ return -EINVAL;
+
+ mutex_lock(&rar_mutex);
+
+ if (my_rar_device.registered) {
+
+ mutex_unlock(&rar_mutex);
+ /*
+ * if the driver already registered, then we can simply
+ * call the callback right now
+ */
+
+ return (*callback)(yourparameter);
+ }
+
+ if (num_clients < MRST_NUM_RAR) {
+
+ clients[num_clients].client_callback = callback;
+ clients[num_clients].customer_data = yourparameter;
+ num_clients += 1;
+ result = 0;
+ }
+
+ mutex_unlock(&rar_mutex);
+ return result;
+
+}
+EXPORT_SYMBOL(register_rar);
+
+/* Suspend - returns -ENOSYS */
+static int rar_suspend(struct pci_dev *dev, pm_message_t state)
+{
+ return -ENOSYS;
+}
+
+static int rar_resume(struct pci_dev *dev)
+{
+ return -ENOSYS;
+}
+
+/*
+ * This function registers the driver with the device subsystem (
+ * either PCI, USB, etc).
+ * Function that is activaed on the succesful probe of the RAR device
+ * (Moorestown host controller).
+ */
+static int rar_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ int error;
+ int counter;
+
+ dev_dbg(&dev->dev, "PCI probe starting\n");
+
+ /* enable the device */
+ error = pci_enable_device(dev);
+ if (error) {
+ dev_err(&dev->dev,
+ "Error enabling RAR register PCI device\n");
+ goto end_function;
+ }
+
+ /* we have only one device; fill in the rar_device structure */
+ my_rar_device.rar_dev = dev;
+
+ /*
+ * Initialize the RAR parameters, which have to be retrieved
+ * via the message bus interface.
+ */
+ error = init_rar_params(dev);
+ if (error) {
+ pci_disable_device(dev);
+
+ dev_err(&dev->dev,
+ "Error retrieving RAR addresses\n");
+
+ goto end_function;
+ }
+
+ dev_dbg(&dev->dev, "PCI probe locking\n");
+ mutex_lock(&rar_mutex);
+ my_rar_device.registered = 1;
+
+ /* now call anyone who has registered (using callbacks) */
+ for (counter = 0; counter < num_clients; counter += 1) {
+ if (clients[counter].client_callback) {
+ error = (*clients[counter].client_callback)(
+ clients[counter].customer_data);
+ /* set callback to NULL to indicate it has been done */
+ clients[counter].client_callback = NULL;
+ dev_dbg(&my_rar_device.rar_dev->dev,
+ "Callback called for %d\n",
+ counter);
+ }
+ }
+
+ dev_dbg(&dev->dev, "PCI probe unlocking\n");
+ mutex_unlock(&rar_mutex);
+
+end_function:
+
+ return error;
+}
+
+const struct pci_device_id rar_pci_id_tbl[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_RAR_DEVICE_ID) },
+ { 0 }
+};
+
+MODULE_DEVICE_TABLE(pci, rar_pci_id_tbl);
+
+const struct pci_device_id *my_id_table = rar_pci_id_tbl;
+
+/* field for registering driver to PCI device */
+static struct pci_driver rar_pci_driver = {
+ .name = "rar_register_driver",
+ .id_table = rar_pci_id_tbl,
+ .probe = rar_probe,
+ .suspend = rar_suspend,
+ .resume = rar_resume
+};
+
+static int __init rar_init_handler(void)
+{
+ return pci_register_driver(&rar_pci_driver);
+}
+
+static void __exit rar_exit_handler(void)
+{
+ pci_unregister_driver(&rar_pci_driver);
+}
+
+module_init(rar_init_handler);
+module_exit(rar_exit_handler);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Intel Restricted Access Region Register Driver");
diff --git a/drivers/staging/rar_register/rar_register.h b/drivers/staging/rar_register/rar_register.h
new file mode 100644
index 00000000000..29ade0f361d
--- /dev/null
+++ b/drivers/staging/rar_register/rar_register.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2010 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General
+ * Public License as 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.
+ * The full GNU General Public License is included in this
+ * distribution in the file called COPYING.
+ */
+
+
+#ifndef _RAR_REGISTER_H
+#define _RAR_REGISTER_H
+
+# include <linux/types.h>
+
+/* following are used both in drivers as well as user space apps */
+enum RAR_type {
+ RAR_TYPE_VIDEO = 0,
+ RAR_TYPE_AUDIO,
+ RAR_TYPE_IMAGE,
+ RAR_TYPE_DATA
+};
+
+#ifdef __KERNEL__
+
+/* PCI device id for controller */
+#define PCI_RAR_DEVICE_ID 0x4110
+
+/* The register_rar function is to used by other device drivers
+ * to ensure that this driver is ready. As we cannot be sure of
+ * the compile/execute order of dirvers in ther kernel, it is
+ * best to give this driver a callback function to call when
+ * it is ready to give out addresses. The callback function
+ * would have those steps that continue the initialization of
+ * a driver that do require a valid RAR address. One of those
+ * steps would be to call get_rar_address()
+ * This function return 0 on success an -1 on failure.
+ */
+int register_rar(int (*callback)(void *yourparameter), void *yourparameter);
+
+/* The get_rar_address function is used by other device drivers
+ * to obtain RAR address information on a RAR. It takes two
+ * parameter:
+ *
+ * int rar_index
+ * The rar_index is an index to the rar for which you wish to retrieve
+ * the address information.
+ * Values can be 0,1, or 2.
+ *
+ * struct RAR_address_struct is a pointer to a place to which the function
+ * can return the address structure for the RAR.
+ *
+ * The function returns a 0 upon success or a -1 if there is no RAR
+ * facility on this system.
+ */
+int rar_get_address(int rar_index,
+ dma_addr_t *start_address,
+ dma_addr_t *end_address);
+
+/* The lock_rar function is ued by other device drivers to lock an RAR.
+ * once an RAR is locked, it stays locked until the next system reboot.
+ * The function takes one parameter:
+ *
+ * int rar_index
+ * The rar_index is an index to the rar that you want to lock.
+ * Values can be 0,1, or 2.
+ *
+ * The function returns a 0 upon success or a -1 if there is no RAR
+ * facility on this system.
+ */
+int rar_lock(int rar_index);
+
+#endif /* __KERNEL__ */
+#endif /* _RAR_REGISTER_H */
diff --git a/drivers/staging/rt2860/Kconfig b/drivers/staging/rt2860/Kconfig
index f9962b69312..f3a7e47df5e 100644
--- a/drivers/staging/rt2860/Kconfig
+++ b/drivers/staging/rt2860/Kconfig
@@ -3,6 +3,8 @@ config RT2860
depends on PCI && X86 && WLAN
select WIRELESS_EXT
select WEXT_PRIV
+ select CRC_CCITT
+ select FW_LOADER
---help---
This is an experimental driver for the Ralink 2860 and 3090
wireless chips.
diff --git a/drivers/staging/rt2860/common/firmware.h b/drivers/staging/rt2860/common/firmware.h
deleted file mode 100644
index 2fecd32f760..00000000000
--- a/drivers/staging/rt2860/common/firmware.h
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- Copyright (c) 2007, Ralink Technology Corporation
- All rights reserved.
-
- Redistribution. Redistribution and use in binary form, without
- modification, are permitted provided that the following conditions are
- met:
-
- * Redistributions must reproduce the above copyright notice and the
- following disclaimer in the documentation and/or other materials
- provided with the distribution.
- * Neither the name of Ralink Technology Corporation nor the names of its
- suppliers may be used to endorse or promote products derived from this
- software without specific prior written permission.
- * No reverse engineering, decompilation, or disassembly of this software
- is permitted.
-
- Limited patent license. Ralink Technology Corporation grants a world-wide,
- royalty-free, non-exclusive license under patents it now or hereafter
- owns or controls to make, have made, use, import, offer to sell and
- sell ("Utilize") this software, but solely to the extent that any
- such patent is necessary to Utilize the software alone, or in
- combination with an operating system licensed under an approved Open
- Source license as listed by the Open Source Initiative at
- http://opensource.org/licenses. The patent license shall not apply to
- any other combinations which include this software. No hardware per
- se is licensed hereunder.
-
- DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- DAMAGE.
-*/
-/* AUTO GEN PLEASE DO NOT MODIFY IT */
-/* AUTO GEN PLEASE DO NOT MODIFY IT */
-
-
-u8 FirmwareImage_2860 [] = {
-0x02, 0x03, 0x5e, 0x02, 0x02, 0xb1, 0x22, 0x22, 0xff, 0xff, 0xff, 0x02, 0x01, 0x82, 0xff, 0xff,
-0xff, 0xff, 0xff, 0x02, 0x00, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x01, 0x33, 0xc0, 0xe0,
-0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x18, 0xc2, 0xaf, 0x30, 0x45, 0x03,
-0x12, 0x10, 0x09, 0x90, 0x04, 0x16, 0xe0, 0x30, 0xe3, 0x03, 0x74, 0x08, 0xf0, 0x90, 0x04, 0x14,
-0xe0, 0x20, 0xe7, 0x03, 0x02, 0x00, 0xcb, 0x74, 0x80, 0xf0, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x2f,
-0x90, 0x04, 0x04, 0xe0, 0x24, 0xcf, 0x60, 0x30, 0x14, 0x60, 0x42, 0x24, 0xe2, 0x60, 0x47, 0x14,
-0x60, 0x55, 0x24, 0x21, 0x70, 0x60, 0xe5, 0x55, 0x24, 0xfe, 0x60, 0x07, 0x14, 0x60, 0x08, 0x24,
-0x02, 0x70, 0x08, 0x7d, 0x01, 0x80, 0x28, 0x7d, 0x02, 0x80, 0x24, 0x90, 0x70, 0x10, 0xe0, 0xf5,
-0x50, 0x85, 0x2f, 0x40, 0xd2, 0x01, 0x80, 0x3e, 0xe5, 0x55, 0x64, 0x03, 0x60, 0x04, 0xe5, 0x55,
-0x70, 0x04, 0x7d, 0x02, 0x80, 0x09, 0x85, 0x2f, 0x41, 0xd2, 0x02, 0x80, 0x29, 0xad, 0x55, 0xaf,
-0x2f, 0x12, 0x02, 0x8d, 0x80, 0x20, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x47, 0x90, 0x70, 0x11, 0xe0,
-0xf5, 0x44, 0x12, 0x10, 0x25, 0x80, 0x06, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x45, 0xe4, 0xfd, 0xaf,
-0x2f, 0x12, 0x02, 0x8d, 0xd2, 0x04, 0x90, 0x70, 0x13, 0xe4, 0xf0, 0xd2, 0xaf, 0xd0, 0xd0, 0xd0,
-0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1, 0x53, 0xc2,
-0xaf, 0x90, 0x70, 0x28, 0xe0, 0x90, 0x10, 0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90, 0x10, 0x1d,
-0xf0, 0x90, 0x70, 0x2a, 0xe0, 0x90, 0x10, 0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x30, 0x90,
-0x10, 0x1e, 0xe0, 0x20, 0xe1, 0xf3, 0x90, 0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0, 0x90, 0x10,
-0x1d, 0xe0, 0x90, 0x70, 0x29, 0xf0, 0x90, 0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0, 0x30, 0x4a,
-0x0d, 0x90, 0x70, 0x24, 0xe0, 0x44, 0x01, 0xf0, 0x90, 0x02, 0x2c, 0x74, 0xff, 0xf0, 0xc2, 0x05,
-0xd2, 0xaf, 0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0xe8, 0xc0, 0xe0,
-0xe9, 0xc0, 0xe0, 0xea, 0xc0, 0xe0, 0xeb, 0xc0, 0xe0, 0xec, 0xc0, 0xe0, 0xed, 0xc0, 0xe0, 0xee,
-0xc0, 0xe0, 0xef, 0xc0, 0xe0, 0xc2, 0xaf, 0x30, 0x45, 0x03, 0x12, 0x10, 0x12, 0xd2, 0xaf, 0xd0,
-0xe0, 0xff, 0xd0, 0xe0, 0xfe, 0xd0, 0xe0, 0xfd, 0xd0, 0xe0, 0xfc, 0xd0, 0xe0, 0xfb, 0xd0, 0xe0,
-0xfa, 0xd0, 0xe0, 0xf9, 0xd0, 0xe0, 0xf8, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0,
-0xe0, 0x32, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x10, 0xc2,
-0xaf, 0x30, 0x45, 0x03, 0x12, 0x10, 0x0c, 0x30, 0x58, 0x0a, 0xe5, 0x54, 0x60, 0x04, 0x15, 0x54,
-0x80, 0x02, 0xc2, 0x58, 0x30, 0x59, 0x0a, 0xe5, 0x50, 0x60, 0x04, 0x15, 0x50, 0x80, 0x02, 0xc2,
-0x59, 0xd5, 0x53, 0x07, 0x30, 0x60, 0x04, 0x15, 0x46, 0xd2, 0x04, 0x30, 0x45, 0x03, 0x12, 0x10,
-0x0f, 0xc2, 0x8d, 0xd2, 0xaf, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32,
-0x12, 0x02, 0xd3, 0x30, 0x45, 0x03, 0x12, 0x10, 0x03, 0x30, 0x01, 0x06, 0x20, 0x09, 0x03, 0x12,
-0x10, 0x1c, 0x30, 0x02, 0x06, 0x20, 0x0a, 0x03, 0x12, 0x10, 0x1f, 0x30, 0x03, 0x06, 0x20, 0x0b,
-0x03, 0x12, 0x10, 0x1f, 0x30, 0x04, 0x06, 0x20, 0x0c, 0x03, 0x12, 0x10, 0x22, 0x20, 0x13, 0x09,
-0x20, 0x11, 0x06, 0xe5, 0x2b, 0x45, 0x2c, 0x60, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0xa9, 0x12,
-0x02, 0xec, 0x80, 0xbf, 0xc2, 0x43, 0xd2, 0x45, 0xe4, 0xf5, 0x20, 0xf5, 0x21, 0xf5, 0x53, 0xf5,
-0x46, 0xf5, 0x2b, 0xf5, 0x2c, 0xc2, 0x42, 0xf5, 0x51, 0xf5, 0x52, 0xf5, 0x55, 0x90, 0x04, 0x18,
-0x74, 0x80, 0xf0, 0x90, 0x04, 0x1a, 0x74, 0x08, 0xf0, 0xc2, 0x19, 0xc2, 0x18, 0xc2, 0x1a, 0x22,
-0xc8, 0xef, 0xc8, 0xe6, 0xfa, 0x08, 0xe6, 0x4a, 0x60, 0x0c, 0xc8, 0xef, 0xc8, 0x08, 0xe6, 0x16,
-0x18, 0x70, 0x01, 0x16, 0xc3, 0x22, 0xed, 0x24, 0xff, 0xfd, 0xec, 0x34, 0xff, 0xc8, 0xef, 0xc8,
-0xf6, 0x08, 0xc6, 0xed, 0xc6, 0xd3, 0x22, 0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12,
-0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83,
-0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0xef, 0xf4, 0x60,
-0x1f, 0xe4, 0xfe, 0x12, 0x03, 0x6a, 0xe0, 0xb4, 0xff, 0x12, 0x12, 0x03, 0x6a, 0xef, 0xf0, 0x74,
-0x1c, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xe3,
-0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x08, 0xc2, 0xaf,
-0x30, 0x45, 0x03, 0x12, 0x10, 0x06, 0xd2, 0xaf, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0,
-0xd0, 0xe0, 0x32, 0xc2, 0xaf, 0x12, 0x00, 0x06, 0x12, 0x02, 0x14, 0x12, 0x03, 0x1c, 0xe4, 0xf5,
-0x22, 0xf5, 0x47, 0x90, 0x04, 0x00, 0x74, 0x80, 0xf0, 0xd2, 0xaf, 0x22, 0x30, 0x45, 0x03, 0x12,
-0x10, 0x15, 0xe5, 0x20, 0x70, 0x03, 0x20, 0x10, 0x03, 0x30, 0x11, 0x03, 0x43, 0x87, 0x01, 0x22,
-0xc0, 0x2a, 0x74, 0x03, 0xc0, 0xe0, 0xc0, 0x82, 0xc0, 0x83, 0x75, 0x2a, 0x0a, 0x22, 0xc0, 0x2a,
-0x74, 0x03, 0xc0, 0xe0, 0xc0, 0x82, 0xc0, 0x83, 0x75, 0x2a, 0x18, 0x22, 0x75, 0x89, 0x02, 0xe4,
-0xf5, 0x8c, 0xf5, 0x8a, 0xf5, 0x88, 0xf5, 0xb8, 0xf5, 0xe8, 0x75, 0x90, 0x18, 0xd2, 0x8c, 0x75,
-0xa8, 0x05, 0x22, 0xce, 0xef, 0xce, 0xee, 0x60, 0x08, 0x7f, 0xff, 0x12, 0x03, 0x80, 0x1e, 0x80,
-0xf5, 0x22, 0xc8, 0xef, 0xc8, 0xe6, 0x60, 0x03, 0x16, 0xc3, 0x22, 0xed, 0x14, 0xf6, 0xd3, 0x22,
-0xc8, 0xef, 0xc8, 0xe6, 0x60, 0x06, 0x16, 0xe6, 0x24, 0xff, 0xb3, 0x22, 0xc3, 0x22, 0x78, 0x7f,
-0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x5f, 0x02, 0x01, 0xd0, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4,
-0x34, 0x70, 0xf5, 0x83, 0x22, 0xef, 0x90, 0x03, 0x7e, 0x93, 0x90, 0x03, 0x00, 0x73, 0x0a, 0x18,
-0xef, 0x60, 0x03, 0x1f, 0x80, 0xfa, 0x22, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x3b, 0x02, 0x10, 0x3c, 0x02, 0x12, 0xb8, 0x02,
-0x12, 0xb9, 0x02, 0x13, 0x3e, 0x02, 0x13, 0x3f, 0xc3, 0x22, 0xff, 0xff, 0x02, 0x16, 0x56, 0x02,
-0x17, 0x6b, 0x02, 0x14, 0x2a, 0x02, 0x13, 0x40, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x00,
-0xd8, 0x30, 0x06, 0x06, 0x20, 0x0e, 0x03, 0x12, 0x18, 0x5e, 0x22, 0x22, 0x90, 0x04, 0x14, 0xe0,
-0x20, 0xe7, 0x03, 0x02, 0x12, 0xb7, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0,
-0x12, 0x02, 0x67, 0x11, 0x4e, 0x30, 0x11, 0x25, 0x31, 0x10, 0x87, 0x33, 0x10, 0xaa, 0x34, 0x10,
-0xc3, 0x35, 0x11, 0x57, 0x50, 0x11, 0x7b, 0x51, 0x11, 0x84, 0x52, 0x11, 0x84, 0x53, 0x11, 0x84,
-0x54, 0x11, 0xc5, 0x55, 0x11, 0xdc, 0x70, 0x12, 0x07, 0x71, 0x12, 0x34, 0x72, 0x12, 0x5e, 0x80,
-0x12, 0x81, 0x83, 0x00, 0x00, 0x12, 0xb7, 0x75, 0x24, 0x05, 0x75, 0x25, 0xdc, 0x90, 0x70, 0x9f,
-0x74, 0x12, 0xf0, 0xd2, 0x18, 0xd2, 0x61, 0x75, 0x35, 0x0d, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5,
-0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0xb7, 0x02, 0x12, 0xaa, 0xc2, 0x18, 0x90, 0x01, 0x14, 0xe0,
-0x54, 0xfd, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0xb7,
-0x02, 0x12, 0xaa, 0xe5, 0x55, 0x64, 0x02, 0x70, 0x37, 0x90, 0x70, 0x10, 0xe0, 0x60, 0x08, 0x90,
-0x01, 0x0d, 0x74, 0x09, 0xf0, 0x80, 0x25, 0xe5, 0x34, 0x14, 0x60, 0x0a, 0x14, 0x60, 0x0f, 0x14,
-0x60, 0x14, 0x24, 0x03, 0x70, 0x16, 0x90, 0x01, 0x0d, 0x74, 0x08, 0xf0, 0x80, 0x0e, 0x90, 0x01,
-0x0d, 0x74, 0x0b, 0xf0, 0x80, 0x06, 0x90, 0x01, 0x0d, 0x74, 0x1b, 0xf0, 0x7d, 0x01, 0x80, 0x02,
-0x7d, 0x02, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, 0x92, 0x1b, 0x90,
-0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02,
-0x12, 0xb7, 0x02, 0x12, 0xaa, 0x20, 0x02, 0x03, 0x30, 0x03, 0x1d, 0x7d, 0x02, 0xaf, 0x56, 0x12,
-0x02, 0x8d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4,
-0x70, 0x03, 0x02, 0x12, 0xb7, 0x02, 0x12, 0xaa, 0x85, 0x56, 0x41, 0xd2, 0x02, 0x22, 0x90, 0x70,
-0x11, 0xe0, 0x24, 0xff, 0x92, 0x1b, 0x22, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0x64, 0x02, 0x60,
-0x03, 0x02, 0x12, 0xb7, 0x90, 0x70, 0x11, 0xe0, 0x64, 0x08, 0x60, 0x08, 0xe0, 0x64, 0x20, 0x60,
-0x03, 0x02, 0x12, 0xb7, 0x75, 0x4e, 0x03, 0x75, 0x4f, 0x20, 0x22, 0x90, 0x70, 0x11, 0xe0, 0x24,
-0xff, 0x92, 0x47, 0x22, 0x90, 0x04, 0x04, 0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70,
-0x10, 0xe0, 0xff, 0x74, 0x47, 0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff,
-0x74, 0x48, 0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90,
-0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02,
-0x12, 0xb7, 0x02, 0x12, 0xaa, 0xe5, 0x47, 0xb4, 0x07, 0x08, 0x90, 0x70, 0x11, 0xe0, 0x54, 0x07,
-0xf5, 0x26, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0xd2, 0x04, 0x22, 0x90, 0x70, 0x10, 0xe0,
-0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf8, 0xe6, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x02,
-0x8d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70,
-0x03, 0x02, 0x12, 0xb7, 0x02, 0x12, 0xaa, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0,
-0xfd, 0xed, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90,
-0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02,
-0x12, 0xb7, 0x80, 0x76, 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x75, 0x26, 0xff, 0xc2, 0x19, 0xc2, 0x18,
-0xc2, 0x1a, 0x75, 0x34, 0xff, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90, 0x04, 0x14, 0x74,
-0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x5b, 0x80, 0x4c, 0x90, 0x70,
-0x10, 0xe0, 0x24, 0xff, 0x92, 0x4a, 0xd2, 0x05, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90,
-0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x38, 0x80,
-0x29, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x34, 0xd3, 0x94, 0x00, 0x40, 0x07, 0x90, 0x01, 0x0d, 0xe0,
-0x54, 0xfb, 0xf0, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x8d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0,
-0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x0d, 0x90, 0x70, 0x25, 0xe0, 0x44, 0x01,
-0xf0, 0x90, 0x02, 0x2c, 0x74, 0xff, 0xf0, 0x22, 0x22, 0xe5, 0x53, 0x60, 0x03, 0x02, 0x13, 0x3d,
-0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08, 0xe5, 0x4f, 0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e, 0xa2, 0x19,
-0xe4, 0x33, 0x90, 0x70, 0x90, 0xf0, 0xa2, 0x18, 0xe4, 0x33, 0xa3, 0xf0, 0x30, 0x19, 0x4d, 0x90,
-0x70, 0x98, 0x74, 0x23, 0xf0, 0xa3, 0xe5, 0x25, 0xf0, 0xe5, 0x24, 0xa3, 0xf0, 0x7f, 0x35, 0x7d,
-0x32, 0x12, 0x03, 0x42, 0x50, 0x09, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf7, 0xf0, 0xd2, 0x06, 0xe5,
-0x35, 0xd3, 0x94, 0x10, 0x40, 0x1e, 0x30, 0x1a, 0x1b, 0xc2, 0x1a, 0xa2, 0x18, 0x92, 0x19, 0x20,
-0x19, 0x12, 0x90, 0x04, 0x09, 0xe0, 0x54, 0xdd, 0xf0, 0x90, 0x10, 0x04, 0xe0, 0x44, 0x08, 0xf0,
-0xc2, 0x61, 0xd2, 0x03, 0xe5, 0x35, 0xb4, 0x0b, 0x14, 0xd2, 0x03, 0x22, 0xe4, 0xf5, 0x35, 0xa2,
-0x18, 0x92, 0x19, 0x30, 0x19, 0x07, 0x90, 0x04, 0x09, 0xe0, 0x44, 0x22, 0xf0, 0x22, 0x22, 0x22,
-0xc2, 0x4b, 0xc2, 0x4c, 0xe5, 0x44, 0x12, 0x02, 0x67, 0x13, 0x62, 0x00, 0x13, 0xf5, 0x04, 0x13,
-0xf1, 0x08, 0x13, 0xcc, 0x10, 0x13, 0x76, 0x20, 0x13, 0x96, 0x60, 0x13, 0xa7, 0xa0, 0x00, 0x00,
-0x13, 0xf7, 0x85, 0x48, 0x43, 0x85, 0x4a, 0x42, 0x85, 0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60,
-0x03, 0x02, 0x13, 0xf7, 0x80, 0x1b, 0xe5, 0x48, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4,
-0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4c, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70,
-0x66, 0x53, 0x43, 0x0f, 0x80, 0x61, 0x85, 0x49, 0x43, 0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5,
-0x47, 0x64, 0x06, 0x70, 0x52, 0x80, 0x1b, 0xe5, 0x49, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b,
-0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4d, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06,
-0x70, 0x35, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x10, 0xf5, 0x43, 0x80, 0x2b, 0xe5, 0x47, 0xb4, 0x04,
-0x06, 0x53, 0x5e, 0xfb, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43, 0x5e, 0x04, 0x75,
-0x42, 0x09, 0xe5, 0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30, 0xf5, 0x43, 0x80,
-0x06, 0xd2, 0x4b, 0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x38, 0xe5, 0x42, 0xc4, 0x54, 0xf0, 0xff,
-0xe5, 0x43, 0x54, 0x0f, 0x4f, 0xf5, 0x5f, 0x90, 0x70, 0x44, 0xf0, 0xa3, 0xe5, 0x5e, 0xf0, 0xa3,
-0xe5, 0x4a, 0xf0, 0xa3, 0xe5, 0x48, 0xf0, 0xa3, 0xe5, 0x4c, 0xf0, 0xa3, 0xe5, 0x44, 0xf0, 0xa3,
-0xe5, 0x42, 0xf0, 0xa3, 0xe5, 0x43, 0xf0, 0xd2, 0x60, 0x22, 0xe5, 0x47, 0x60, 0x10, 0x24, 0xc0,
-0x70, 0x03, 0x12, 0x16, 0x36, 0x12, 0x14, 0x3f, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2,
-0xaf, 0x90, 0x04, 0x14, 0xe0, 0x54, 0x0e, 0x60, 0x04, 0xd2, 0x1c, 0x80, 0x08, 0xe5, 0x4e, 0x45,
-0x4f, 0x24, 0xff, 0x92, 0x1c, 0xd2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x1d, 0x74,
-0x1e, 0xf0, 0xe5, 0x5f, 0x54, 0x0f, 0xf5, 0x2d, 0xe5, 0x38, 0x70, 0x13, 0x30, 0x1c, 0x05, 0xe5,
-0x5f, 0x20, 0xe5, 0x0b, 0x30, 0x1d, 0x19, 0xe5, 0x5f, 0x54, 0x30, 0xff, 0xbf, 0x30, 0x11, 0xe5,
-0x38, 0x70, 0x05, 0x75, 0x38, 0x0c, 0x80, 0x02, 0x15, 0x38, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f,
-0xe5, 0x5f, 0x30, 0xe6, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5,
-0x47, 0x64, 0x03, 0x70, 0x21, 0x30, 0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x38,
-0x70, 0x03, 0x30, 0x4c, 0x11, 0xc2, 0x4c, 0xe5, 0x38, 0x70, 0x05, 0x75, 0x38, 0x07, 0x80, 0x02,
-0x15, 0x38, 0xd2, 0x6c, 0xd2, 0x6d, 0x90, 0x70, 0x46, 0xe5, 0x2d, 0xf0, 0x20, 0x69, 0x07, 0xe5,
-0x5e, 0x20, 0xe0, 0x02, 0xb2, 0x68, 0x20, 0x6b, 0x07, 0xe5, 0x5e, 0x20, 0xe1, 0x02, 0xb2, 0x6a,
-0x20, 0x6d, 0x07, 0xe5, 0x5e, 0x20, 0xe2, 0x02, 0xb2, 0x6c, 0x90, 0x70, 0x47, 0xe5, 0x2d, 0xf0,
-0x75, 0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x15, 0x30, 0x68, 0x06, 0xe5, 0x46, 0xa2,
-0xe3, 0x80, 0x0c, 0xe5, 0x46, 0x54, 0xf0, 0xff, 0xbf, 0xf0, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92,
-0x73, 0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80, 0x15, 0x30, 0x6a, 0x06, 0xe5, 0x46, 0xa2,
-0xe3, 0x80, 0x0c, 0xe5, 0x46, 0x54, 0xf0, 0xff, 0xbf, 0xf0, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92,
-0x75, 0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c, 0x80, 0x15, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2,
-0xe3, 0x80, 0x0c, 0xe5, 0x46, 0x54, 0xf0, 0xff, 0xbf, 0xf0, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92,
-0x71, 0x92, 0x70, 0x90, 0x10, 0x2f, 0xe5, 0x2e, 0xf0, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x46, 0x90,
-0x02, 0x29, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, 0x54, 0x0f, 0x14, 0x60, 0x14, 0x24, 0xfe,
-0x60, 0x1f, 0x24, 0x03, 0x60, 0x03, 0x02, 0x16, 0x35, 0x90, 0x02, 0x28, 0xe0, 0x30, 0x47, 0x0d,
-0x80, 0x07, 0x90, 0x02, 0x28, 0xe0, 0x20, 0x47, 0x04, 0x54, 0xfe, 0xf0, 0x22, 0x44, 0x01, 0xf0,
-0x22, 0xe5, 0x46, 0x30, 0xe3, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x90, 0x02, 0x28, 0xe0,
-0x54, 0xfe, 0x4f, 0xf0, 0x22, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x03, 0x02, 0x16, 0x35, 0xf5, 0x27,
-0x90, 0x02, 0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x26, 0x14, 0x60, 0x26, 0x14, 0x60, 0x2e, 0x14,
-0x60, 0x36, 0x24, 0x03, 0x70, 0x5f, 0xe5, 0x46, 0x13, 0x13, 0x13, 0x54, 0x1f, 0x75, 0xf0, 0x03,
-0x84, 0xaf, 0xf0, 0x20, 0x47, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xef, 0x6e, 0x24, 0xff,
-0x80, 0x02, 0xa2, 0x47, 0x92, 0x39, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x80, 0x3f, 0xe5, 0x46, 0x30,
-0xe3, 0x03, 0xd3, 0x80, 0x27, 0xc3, 0x80, 0x24, 0xe5, 0x46, 0x30, 0xe3, 0x0d, 0x54, 0x70, 0xc3,
-0x94, 0x60, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x20, 0x47,
-0x04, 0x7d, 0x01, 0x80, 0x02, 0x7d, 0x00, 0xef, 0x6d, 0x4e, 0x24, 0xff, 0x92, 0x38, 0xa2, 0x47,
-0xb3, 0x92, 0x39, 0x80, 0x07, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x92, 0x39, 0x90, 0x02, 0x28, 0xe0,
-0x54, 0xfc, 0x45, 0x27, 0xf0, 0x22, 0xe4, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x45,
-0x80, 0x04, 0xe5, 0x45, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0x8f, 0x50, 0xd2, 0x59,
-0x22, 0x8f, 0x54, 0xd2, 0x58, 0x22, 0xe4, 0xf5, 0x30, 0xc2, 0xaf, 0xe5, 0x51, 0x14, 0x60, 0x4a,
-0x14, 0x60, 0x6a, 0x24, 0x02, 0x60, 0x03, 0x02, 0x17, 0x4c, 0xd2, 0x59, 0x75, 0x55, 0x01, 0x20,
-0x19, 0x1c, 0x90, 0x02, 0x08, 0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x20, 0xe1, 0x23, 0x90, 0x04, 0x34,
-0xe0, 0xb4, 0x02, 0x1c, 0xa3, 0xe0, 0xb4, 0x02, 0x17, 0xa3, 0xe0, 0xb4, 0x02, 0x12, 0x7f, 0x20,
-0x12, 0x16, 0x4c, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf3, 0xf0, 0x75, 0x51, 0x01, 0x02, 0x17, 0x4c,
-0xe5, 0x50, 0x70, 0x06, 0x75, 0x30, 0x03, 0x02, 0x17, 0x4c, 0x90, 0x12, 0x00, 0xe0, 0x54, 0x03,
-0x70, 0x15, 0x7f, 0x20, 0x12, 0x16, 0x4c, 0x20, 0x19, 0x07, 0x90, 0x02, 0x08, 0xe0, 0x54, 0xfb,
-0xf0, 0x75, 0x51, 0x02, 0x02, 0x17, 0x4c, 0xe5, 0x50, 0x70, 0x02, 0x80, 0x7a, 0x20, 0x19, 0x0f,
-0x90, 0x02, 0x08, 0xe0, 0x20, 0xe3, 0x6c, 0x90, 0x04, 0x37, 0xe0, 0x64, 0x22, 0x70, 0x64, 0x90,
-0x12, 0x04, 0x74, 0x0a, 0xf0, 0x30, 0x1b, 0x11, 0x90, 0x13, 0x28, 0xe0, 0x54, 0xf0, 0xf0, 0xa3,
-0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xfa, 0xf0, 0x20, 0x19, 0x07, 0x90, 0x04, 0x01, 0xe0,
-0x44, 0x10, 0xf0, 0xe5, 0x34, 0xf4, 0x90, 0x04, 0x01, 0x60, 0x06, 0xe0, 0x54, 0xfb, 0xf0, 0x80,
-0x04, 0xe0, 0x54, 0xf9, 0xf0, 0x20, 0x19, 0x07, 0x90, 0x12, 0x04, 0xe0, 0x44, 0x04, 0xf0, 0xe5,
-0x34, 0xf4, 0x60, 0x14, 0x90, 0x01, 0x0d, 0xe0, 0xf5, 0x33, 0xe5, 0x34, 0xd3, 0x94, 0x02, 0x40,
-0x07, 0x90, 0x12, 0x04, 0xe0, 0x54, 0xfd, 0xf0, 0x75, 0x30, 0x01, 0x75, 0x55, 0x02, 0xe4, 0xf5,
-0x51, 0x80, 0x09, 0xe5, 0x50, 0x70, 0x05, 0x75, 0x30, 0x03, 0xf5, 0x51, 0xe5, 0x30, 0x60, 0x18,
-0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2, 0x59, 0x20, 0x19, 0x0e, 0xad, 0x30, 0xaf, 0x40, 0x12, 0x18,
-0x2a, 0xe5, 0x30, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0x30, 0x01, 0x0e,
-0xe4, 0xf5, 0x51, 0xc2, 0x59, 0xc2, 0x01, 0x7d, 0x02, 0xaf, 0x40, 0x12, 0x18, 0x2a, 0xe5, 0x52,
-0x14, 0x60, 0x55, 0x14, 0x60, 0x2f, 0x24, 0x02, 0x60, 0x03, 0x02, 0x18, 0x27, 0xe5, 0x34, 0xf4,
-0x60, 0x23, 0xe5, 0x34, 0xd3, 0x94, 0x02, 0x40, 0x16, 0x90, 0x12, 0x04, 0xe0, 0x44, 0x02, 0xf0,
-0x90, 0x01, 0x0d, 0xe0, 0x20, 0xe3, 0x03, 0x02, 0x18, 0x27, 0x7f, 0x50, 0x12, 0x16, 0x51, 0x75,
-0x52, 0x02, 0x75, 0x55, 0x03, 0xe5, 0x34, 0xf4, 0x60, 0x0a, 0xe5, 0x54, 0x70, 0x69, 0x90, 0x01,
-0x0d, 0xe5, 0x33, 0xf0, 0x90, 0x12, 0x04, 0xe0, 0x54, 0xfb, 0xf0, 0x7f, 0x20, 0x12, 0x16, 0x51,
-0x75, 0x52, 0x01, 0x75, 0x55, 0x03, 0x80, 0x4f, 0xe5, 0x54, 0x70, 0x4b, 0x90, 0x04, 0x01, 0xe0,
-0x44, 0x0e, 0xf0, 0x20, 0x19, 0x04, 0xe0, 0x54, 0xef, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x44, 0x0f,
-0xf0, 0xa3, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x12, 0x04, 0x74, 0x03,
-0xf0, 0x20, 0x19, 0x07, 0x90, 0x02, 0x08, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x10, 0x04, 0xe0, 0x44,
-0x0c, 0xf0, 0xe4, 0xf5, 0x52, 0xf5, 0x55, 0x30, 0x02, 0x0b, 0xc2, 0x02, 0x7d, 0x01, 0xaf, 0x41,
-0x12, 0x18, 0x2a, 0x80, 0x02, 0xc2, 0x03, 0xd2, 0xaf, 0x22, 0xef, 0xf4, 0x60, 0x2d, 0xe4, 0xfe,
-0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xe0, 0xb4, 0xff, 0x19, 0x74, 0x14,
-0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xef, 0xf0, 0x74, 0x1c, 0x2e, 0xf5, 0x82, 0xe4,
-0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xd5, 0x22, 0x22, 0x22, 0x20, 0x19,
-0x03, 0x02, 0x19, 0x0f, 0x90, 0x70, 0x80, 0xe0, 0x04, 0xf0, 0x90, 0x04, 0x37, 0xe0, 0x30, 0xe5,
-0x03, 0x02, 0x19, 0x0b, 0x90, 0x04, 0x28, 0xe0, 0xf5, 0x31, 0xa3, 0xe0, 0xf5, 0x30, 0xf5, 0x32,
-0xe4, 0xf5, 0x37, 0x90, 0x70, 0x81, 0xe0, 0x04, 0xf0, 0x90, 0x70, 0x82, 0xe0, 0x04, 0xf0, 0xe5,
-0x32, 0x75, 0xf0, 0x80, 0xa4, 0x24, 0x00, 0xff, 0xe5, 0xf0, 0x34, 0x80, 0xfe, 0xe5, 0x30, 0x65,
-0x32, 0x70, 0x05, 0xfc, 0x7d, 0x18, 0x80, 0x04, 0x7c, 0x00, 0x7d, 0x00, 0xef, 0x2d, 0xff, 0xee,
-0x3c, 0xfe, 0x12, 0x19, 0x10, 0x50, 0x25, 0x90, 0x70, 0x83, 0xe0, 0x04, 0xf0, 0x90, 0x01, 0x14,
-0xe0, 0x44, 0x02, 0xf0, 0xe0, 0x30, 0xe1, 0x06, 0x90, 0x70, 0x92, 0x74, 0x45, 0xf0, 0x90, 0x70,
-0x93, 0xe0, 0x04, 0xf0, 0x90, 0x04, 0x01, 0xe0, 0x90, 0x70, 0x94, 0xf0, 0xe5, 0x32, 0x65, 0x31,
-0x60, 0x10, 0xe4, 0x25, 0x32, 0xff, 0xe4, 0x34, 0x80, 0x8f, 0x82, 0xf5, 0x83, 0xe0, 0xf5, 0x32,
-0x80, 0x97, 0x90, 0x04, 0x10, 0x74, 0x01, 0xf0, 0x90, 0x04, 0x28, 0xe5, 0x31, 0xf0, 0xa3, 0xe5,
-0x30, 0xf0, 0x90, 0x04, 0x11, 0x74, 0x01, 0xf0, 0x02, 0x18, 0x6a, 0xc2, 0x06, 0xd2, 0x1a, 0x22,
-0x90, 0x70, 0x84, 0xe5, 0x37, 0xf0, 0xc3, 0x94, 0x06, 0x50, 0x19, 0x8f, 0x82, 0x8e, 0x83, 0xe0,
-0xb4, 0xff, 0x07, 0x05, 0x37, 0xe4, 0xf5, 0x36, 0x80, 0x59, 0xe4, 0xf5, 0x37, 0x8f, 0x82, 0x8e,
-0x83, 0xf0, 0x80, 0x4f, 0xe5, 0x36, 0x75, 0xf0, 0x06, 0x84, 0x74, 0x08, 0x25, 0xf0, 0xf5, 0x82,
-0xe4, 0x34, 0x10, 0xf5, 0x83, 0xe0, 0xfd, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xfc, 0x6d, 0x70, 0x30,
-0x90, 0x70, 0x88, 0xe0, 0x04, 0xf0, 0xa3, 0xe0, 0xfd, 0xd3, 0x95, 0x37, 0x40, 0x02, 0x80, 0x02,
-0xad, 0x37, 0x90, 0x70, 0x89, 0xed, 0xf0, 0x05, 0x37, 0x05, 0x36, 0xe5, 0x36, 0x75, 0xf0, 0x06,
-0x84, 0x74, 0x8a, 0x25, 0xf0, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xec, 0xf0, 0x80, 0x03,
-0xe4, 0xf5, 0x37, 0x0f, 0xbf, 0x00, 0x01, 0x0e, 0xef, 0x54, 0x7f, 0x60, 0x0a, 0xe5, 0x37, 0xc3,
-0x94, 0x4e, 0x50, 0x03, 0x02, 0x19, 0x10, 0xe5, 0x37, 0xb4, 0x4e, 0x03, 0xd3, 0x80, 0x01, 0xc3,
-0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x94, 0xeb, } ;
diff --git a/drivers/staging/rt2860/common/firmware_3070.h b/drivers/staging/rt2860/common/firmware_3070.h
deleted file mode 100644
index b710d40bc04..00000000000
--- a/drivers/staging/rt2860/common/firmware_3070.h
+++ /dev/null
@@ -1,517 +0,0 @@
-/* AUTO GEN PLEASE DO NOT MODIFY IT */
-/* AUTO GEN PLEASE DO NOT MODIFY IT */
-
-
-u8 FirmwareImage_3070 [] = {
-0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x32, 0x02, 0x10, 0x78, 0x02, 0x13, 0x1f, 0x02,
-0x13, 0x20, 0x02, 0x13, 0x3f, 0x02, 0x13, 0x44, 0x12, 0x13, 0x40, 0x22, 0x02, 0x17, 0xae, 0x02,
-0x18, 0xd2, 0x02, 0x14, 0x3d, 0x02, 0x13, 0x78, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x19,
-0x95, 0x22, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe3, 0x1b, 0xe5, 0x4c, 0x30, 0xe0, 0x04, 0x7f, 0x40,
-0x80, 0x02, 0x7f, 0x00, 0x90, 0x10, 0x2f, 0xef, 0xf0, 0x90, 0x01, 0x8c, 0x74, 0x08, 0xf0, 0xe4,
-0x90, 0x01, 0xa7, 0xf0, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe0, 0x1c, 0x90, 0x01, 0x80, 0xe0, 0xb4,
-0x02, 0x15, 0xa3, 0xe0, 0xb4, 0x01, 0x10, 0x90, 0x01, 0x84, 0xe0, 0xb4, 0x81, 0x09, 0x90, 0x01,
-0x8c, 0x74, 0x01, 0xf0, 0x12, 0x0d, 0xc8, 0x22, 0x90, 0x04, 0x14, 0xe0, 0x20, 0xe7, 0x03, 0x02,
-0x13, 0x1e, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0, 0x12, 0x0a, 0x9d, 0x10,
-0xd9, 0x31, 0x10, 0xbd, 0x36, 0x11, 0x02, 0x50, 0x11, 0x39, 0x51, 0x11, 0x42, 0x52, 0x11, 0x42,
-0x53, 0x11, 0x42, 0x54, 0x11, 0x83, 0x55, 0x11, 0xd2, 0x56, 0x12, 0x25, 0x70, 0x12, 0x50, 0x71,
-0x12, 0x7e, 0x72, 0x12, 0xd5, 0x73, 0x12, 0xf6, 0x80, 0x00, 0x00, 0x13, 0x1e, 0x90, 0x70, 0x11,
-0xe0, 0xf5, 0x3c, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe5, 0x56,
-0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17, 0x20, 0x02, 0x03, 0x30, 0x03, 0x1d, 0x7d,
-0x02, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13,
-0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17, 0x85, 0x56, 0x41, 0xd2,
-0x02, 0x22, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0xff, 0xbf, 0x0a, 0x0d, 0x90, 0x70, 0x11, 0xe0,
-0xb4, 0x08, 0x06, 0x75, 0x4e, 0x01, 0x75, 0x4f, 0x84, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0xff,
-0xbf, 0x02, 0x12, 0x90, 0x70, 0x11, 0xe0, 0x64, 0x08, 0x60, 0x04, 0xe0, 0xb4, 0x20, 0x06, 0x75,
-0x4e, 0x03, 0x75, 0x4f, 0x20, 0xe4, 0xf5, 0x27, 0x22, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, 0x92,
-0x47, 0x22, 0x90, 0x04, 0x04, 0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70, 0x10, 0xe0,
-0xff, 0x74, 0x47, 0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff, 0x74, 0x48,
-0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14,
-0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e,
-0x02, 0x13, 0x17, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x1d, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x17, 0xe5,
-0x47, 0x64, 0x09, 0x60, 0x11, 0xe5, 0x47, 0x64, 0x0a, 0x60, 0x0b, 0xe5, 0x47, 0x64, 0x0b, 0x60,
-0x05, 0xe5, 0x47, 0xb4, 0x0c, 0x08, 0x90, 0x70, 0x11, 0xe0, 0x54, 0x0f, 0xf5, 0x3a, 0xe5, 0x47,
-0xb4, 0x09, 0x08, 0xe5, 0x3a, 0xb4, 0x03, 0x03, 0xe4, 0xf5, 0x46, 0xe5, 0x47, 0xb4, 0x0a, 0x08,
-0xe5, 0x3a, 0xb4, 0x01, 0x03, 0xe4, 0xf5, 0x46, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0xd2,
-0x04, 0x22, 0x90, 0x70, 0x11, 0xe0, 0xf4, 0xff, 0x90, 0x70, 0x10, 0xe0, 0x5f, 0xff, 0x90, 0x70,
-0x11, 0xe0, 0x55, 0x27, 0x4f, 0x90, 0x70, 0x18, 0xf0, 0x90, 0x70, 0x11, 0xe0, 0x90, 0x70, 0x19,
-0xf0, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x30, 0x15, 0x03, 0xd2, 0x14, 0x22, 0x90, 0x70,
-0x18, 0xe0, 0xf5, 0x27, 0x90, 0x02, 0x29, 0xe0, 0xff, 0x90, 0x70, 0x19, 0xe0, 0xfe, 0xef, 0x5e,
-0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5, 0x27, 0xf4, 0xff, 0x90,
-0x02, 0x28, 0xef, 0xf0, 0x22, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed,
-0xf8, 0xe6, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0,
-0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17,
-0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf5, 0x82, 0x8e, 0x83, 0xe0,
-0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90,
-0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17, 0x90, 0x10,
-0x00, 0xe0, 0xf5, 0x57, 0x90, 0x10, 0x02, 0xe0, 0xf5, 0x58, 0xa3, 0xe0, 0xf5, 0x59, 0xe5, 0x58,
-0xb4, 0x70, 0x1e, 0xe5, 0x59, 0xb4, 0x30, 0x19, 0x90, 0x05, 0x08, 0xe0, 0x44, 0x01, 0xf0, 0xfd,
-0x90, 0x05, 0x05, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x04, 0xf0, 0xed, 0x54, 0xfe, 0x90, 0x05, 0x08,
-0xf0, 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x75, 0x3a, 0xff, 0x75, 0x3c, 0xff, 0xad, 0x57, 0xaf, 0x56,
-0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56,
-0xf4, 0x60, 0x4b, 0x80, 0x42, 0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x93, 0xe4, 0xfd, 0xaf,
-0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5,
-0x56, 0xf4, 0x60, 0x2a, 0x80, 0x21, 0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x4a, 0xd2, 0x05,
-0xad, 0x57, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70,
-0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x07, 0x90, 0x70, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x22, 0x22,
-0xe5, 0x53, 0x70, 0x1a, 0x30, 0x60, 0x09, 0xb2, 0x4d, 0x30, 0x4d, 0x04, 0x05, 0x46, 0xc2, 0x04,
-0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08, 0xe5, 0x4f, 0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e, 0x22, 0x22,
-0xc2, 0x42, 0xd3, 0x22, 0x30, 0x14, 0x30, 0x90, 0x70, 0x19, 0xe0, 0x55, 0x27, 0xff, 0x90, 0x70,
-0x18, 0xe0, 0x4f, 0xf5, 0x27, 0x90, 0x02, 0x29, 0xe0, 0xff, 0x90, 0x70, 0x19, 0xe0, 0xfe, 0xef,
-0x5e, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5, 0x27, 0xf4, 0xff,
-0x90, 0x02, 0x28, 0xef, 0xf0, 0xc2, 0x14, 0x22, 0xc2, 0x4b, 0xc2, 0x4c, 0xe5, 0x44, 0x12, 0x0a,
-0x9d, 0x13, 0x9a, 0x00, 0x14, 0x28, 0x04, 0x14, 0x24, 0x08, 0x14, 0x04, 0x10, 0x13, 0xae, 0x20,
-0x13, 0xce, 0x60, 0x13, 0xdf, 0xa0, 0x00, 0x00, 0x14, 0x2a, 0x85, 0x48, 0x43, 0x85, 0x4a, 0x42,
-0x85, 0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60, 0x03, 0x02, 0x14, 0x2a, 0x80, 0x1b, 0xe5, 0x48,
-0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4c, 0xc4, 0x54,
-0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x61, 0x53, 0x43, 0x0f, 0x80, 0x5c, 0x85, 0x49,
-0x43, 0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x4d, 0x80, 0x1b, 0xe5,
-0x49, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b, 0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4d, 0xc4,
-0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x30, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x10,
-0xf5, 0x43, 0x80, 0x26, 0xe5, 0x47, 0x64, 0x04, 0x60, 0x05, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43,
-0x5e, 0x04, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30,
-0xf5, 0x43, 0x80, 0x06, 0xd2, 0x4b, 0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x25, 0xe5, 0x42, 0xc4,
-0x54, 0xf0, 0xff, 0xe5, 0x43, 0x54, 0x0f, 0x4f, 0xf5, 0x5f, 0xd2, 0x60, 0x22, 0xd2, 0x15, 0xe5,
-0x47, 0x24, 0xf5, 0x60, 0x0b, 0x24, 0xcb, 0x60, 0x07, 0x24, 0x40, 0x70, 0x06, 0xc2, 0x15, 0x22,
-0x12, 0x17, 0x79, 0x12, 0x14, 0x5f, 0xc2, 0x15, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2,
-0xaf, 0x90, 0x04, 0x14, 0xe0, 0x54, 0x0e, 0x60, 0x04, 0xd2, 0x18, 0x80, 0x08, 0xe5, 0x4e, 0x45,
-0x4f, 0x24, 0xff, 0x92, 0x18, 0xd2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x19, 0x74,
-0x1e, 0xf0, 0xe5, 0x5f, 0x54, 0x0f, 0xf5, 0x2d, 0xe5, 0x25, 0x70, 0x13, 0x30, 0x18, 0x05, 0xe5,
-0x5f, 0x20, 0xe5, 0x0b, 0x30, 0x19, 0x19, 0xe5, 0x5f, 0x54, 0x30, 0xff, 0xbf, 0x30, 0x11, 0xe5,
-0x25, 0x70, 0x05, 0x75, 0x25, 0x0c, 0x80, 0x02, 0x15, 0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f,
-0xe5, 0x5f, 0x30, 0xe6, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5,
-0x47, 0x64, 0x03, 0x70, 0x21, 0x30, 0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x25,
-0x70, 0x03, 0x30, 0x4c, 0x11, 0xc2, 0x4c, 0xe5, 0x25, 0x70, 0x05, 0x75, 0x25, 0x07, 0x80, 0x02,
-0x15, 0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0xe5, 0x47, 0xb4, 0x09, 0x14, 0xe5, 0x44, 0x20, 0xe3, 0x0b,
-0xe5, 0x3a, 0x64, 0x02, 0x60, 0x05, 0xe5, 0x3a, 0xb4, 0x03, 0x04, 0xc2, 0x6c, 0xd2, 0x6d, 0xe5,
-0x47, 0xb4, 0x0a, 0x13, 0xe5, 0x3a, 0xb4, 0x01, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x08, 0xe5,
-0x3a, 0x70, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0x20, 0x69, 0x07, 0xe5, 0x5e, 0x20, 0xe0, 0x02, 0xb2,
-0x68, 0x20, 0x6b, 0x07, 0xe5, 0x5e, 0x20, 0xe1, 0x02, 0xb2, 0x6a, 0x20, 0x6d, 0x07, 0xe5, 0x5e,
-0x20, 0xe2, 0x02, 0xb2, 0x6c, 0x75, 0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x26, 0x30,
-0x68, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe2, 0x04, 0x7f, 0x01, 0x80,
-0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e,
-0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x73, 0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80, 0x26,
-0x30, 0x6a, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe0, 0x04, 0x7f, 0x01,
-0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02,
-0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x75, 0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c, 0x80,
-0x26, 0xe5, 0x47, 0x64, 0x0a, 0x70, 0x22, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe3, 0x80, 0x17,
-0xe5, 0x3a, 0xb4, 0x01, 0x06, 0xe5, 0x46, 0xa2, 0xe3, 0x80, 0x34, 0xe5, 0x46, 0x20, 0xe4, 0x03,
-0x30, 0xe5, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x80, 0x26, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe2,
-0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe1, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54,
-0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92,
-0x71, 0x92, 0x70, 0x90, 0x10, 0x00, 0xe0, 0x90, 0x10, 0x2c, 0xf0, 0x90, 0x10, 0x03, 0xe0, 0xc3,
-0x94, 0x30, 0x40, 0x14, 0xa2, 0x71, 0x92, 0x77, 0xa2, 0x70, 0x92, 0x76, 0xe5, 0x2e, 0x13, 0x13,
-0x54, 0x3f, 0xf5, 0x2e, 0xc2, 0x77, 0xd2, 0x76, 0x90, 0x10, 0x2f, 0xe5, 0x2e, 0xf0, 0xe5, 0x47,
-0x64, 0x06, 0x70, 0x39, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, 0x54, 0x0f,
-0x14, 0x60, 0x0c, 0x24, 0xfe, 0x60, 0x0c, 0x24, 0x03, 0x70, 0x13, 0xc2, 0x38, 0x80, 0x0f, 0xd2,
-0x38, 0x80, 0x0b, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x38, 0x30, 0x47,
-0x05, 0xaf, 0x27, 0x02, 0x17, 0x73, 0xe5, 0x27, 0xf4, 0xff, 0x02, 0x17, 0x73, 0xe5, 0x47, 0x64,
-0x07, 0x60, 0x0f, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x09, 0xe5, 0x47, 0x64, 0x09, 0x60, 0x03, 0x02,
-0x16, 0xf2, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x22, 0x14, 0x60,
-0x25, 0x14, 0x60, 0x2d, 0x24, 0xfc, 0x60, 0x49, 0x24, 0xf9, 0x60, 0x14, 0x24, 0x0e, 0x70, 0x50,
-0xe5, 0x46, 0x13, 0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xe5, 0xf0, 0x24, 0xff, 0x80, 0x3a,
-0xd2, 0x39, 0xc2, 0x38, 0x80, 0x3e, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x1d, 0xc3, 0x80,
-0x1a, 0xe5, 0x46, 0x30, 0xe2, 0x0d, 0x54, 0x38, 0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f,
-0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0xee, 0x4f, 0x24, 0xff, 0x92, 0x38, 0xc2, 0x39, 0x80,
-0x13, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x39, 0xc2, 0x38, 0x80, 0x04,
-0xc2, 0x38, 0xc2, 0x39, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5, 0x27, 0xf4, 0xff, 0x02,
-0x17, 0x73, 0xe5, 0x47, 0x64, 0x0c, 0x60, 0x06, 0xe5, 0x47, 0x64, 0x0b, 0x70, 0x7a, 0x90, 0x02,
-0x29, 0xe0, 0x54, 0xfd, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x20, 0x14, 0x60, 0x21, 0x14, 0x60, 0x2b,
-0x24, 0xfc, 0x60, 0x45, 0x24, 0xf9, 0x60, 0x12, 0x24, 0x0e, 0x70, 0x4a, 0xe5, 0x46, 0x13, 0x13,
-0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xe5, 0xf0, 0x80, 0x29, 0xd2, 0x39, 0x80, 0x3a, 0xe5, 0x46,
-0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x39, 0x80, 0x2d, 0xe5, 0x46, 0x30, 0xe2, 0x0d,
-0x54, 0x38, 0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f,
-0x00, 0xee, 0x4f, 0x24, 0xff, 0x92, 0x39, 0x80, 0x0f, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80,
-0x01, 0xc3, 0x92, 0x39, 0x80, 0x02, 0xc2, 0x39, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5,
-0x27, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0xe5, 0x47, 0xb4, 0x0b, 0x10, 0x90, 0x02,
-0x29, 0xe0, 0x54, 0xeb, 0xf0, 0xe5, 0x27, 0x54, 0xeb, 0x45, 0x45, 0xf5, 0x27, 0x22, 0xe4, 0x90,
-0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x45, 0x80, 0x04, 0xe5, 0x45, 0xf4, 0xff, 0x90, 0x02,
-0x28, 0xef, 0xf0, 0x22, 0x8f, 0x50, 0xd2, 0x59, 0x22, 0x8f, 0x54, 0xd2, 0x58, 0x22, 0xe4, 0xf5,
-0x62, 0xc2, 0xaf, 0xe5, 0x51, 0x14, 0x60, 0x48, 0x14, 0x60, 0x66, 0x24, 0x02, 0x60, 0x03, 0x02,
-0x18, 0xb6, 0xd2, 0x59, 0x75, 0x55, 0x01, 0x90, 0x02, 0xa2, 0xe0, 0x54, 0x7f, 0xf0, 0xa3, 0xe0,
-0x20, 0xe7, 0x23, 0x90, 0x04, 0x34, 0xe0, 0xb4, 0x02, 0x1c, 0xa3, 0xe0, 0xb4, 0x02, 0x17, 0xa3,
-0xe0, 0xb4, 0x02, 0x12, 0x7f, 0x20, 0x12, 0x17, 0xa4, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf3, 0xf0,
-0x75, 0x51, 0x01, 0x02, 0x18, 0xb6, 0xe5, 0x50, 0x70, 0x06, 0x75, 0x62, 0x03, 0x02, 0x18, 0xb6,
-0x90, 0x12, 0x00, 0xe0, 0x54, 0x03, 0x70, 0x12, 0x7f, 0x20, 0x12, 0x17, 0xa4, 0x90, 0x02, 0xa2,
-0xe0, 0x54, 0xbf, 0xf0, 0x75, 0x51, 0x02, 0x02, 0x18, 0xb6, 0xe5, 0x50, 0x70, 0x03, 0x02, 0x18,
-0xb1, 0x90, 0x02, 0xa3, 0xe0, 0x30, 0xe6, 0x03, 0x02, 0x18, 0xad, 0x90, 0x04, 0x37, 0xe0, 0x64,
-0x22, 0x70, 0x7a, 0x90, 0x01, 0x8a, 0x74, 0x7e, 0xf0, 0x90, 0x01, 0x96, 0xf0, 0x90, 0x12, 0x04,
-0x74, 0x0a, 0xf0, 0xe5, 0x58, 0xb4, 0x72, 0x15, 0xe5, 0x59, 0xb4, 0x35, 0x10, 0xe4, 0x90, 0x05,
-0x00, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0, 0x7f, 0x01, 0x12,
-0x0d, 0x2a, 0x90, 0x13, 0x28, 0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xf0, 0xf0, 0xe5, 0x59,
-0xb4, 0x35, 0x14, 0xe5, 0x3c, 0xf4, 0x60, 0x06, 0xa3, 0xe0, 0x54, 0xf3, 0x80, 0x14, 0x90, 0x13,
-0x2a, 0xe0, 0x54, 0xfb, 0xf0, 0x80, 0x14, 0xe5, 0x3c, 0xf4, 0x90, 0x13, 0x2a, 0x60, 0x08, 0xe0,
-0x54, 0xf2, 0x45, 0x3c, 0xf0, 0x80, 0x04, 0xe0, 0x54, 0xfa, 0xf0, 0x90, 0x04, 0x01, 0xe0, 0x54,
-0xfd, 0xf0, 0x75, 0x62, 0x01, 0x75, 0x55, 0x02, 0xe4, 0xf5, 0x51, 0x80, 0x09, 0xe5, 0x50, 0x70,
-0x05, 0x75, 0x62, 0x03, 0xf5, 0x51, 0xe5, 0x62, 0x60, 0x15, 0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2,
-0x59, 0xad, 0x62, 0xaf, 0x40, 0x12, 0x19, 0x61, 0xe5, 0x62, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2,
-0xaf, 0x22, 0xc2, 0xaf, 0x30, 0x01, 0x12, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xf5, 0x51, 0xc2, 0x59,
-0xc2, 0x01, 0x7d, 0x02, 0xaf, 0x40, 0x12, 0x19, 0x61, 0xe5, 0x52, 0x14, 0x60, 0x09, 0x04, 0x70,
-0x6d, 0x75, 0x52, 0x01, 0x75, 0x55, 0x03, 0x90, 0x04, 0x01, 0xe0, 0x44, 0x0e, 0xf0, 0x90, 0x13,
-0x28, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90,
-0x12, 0x04, 0x74, 0x03, 0xf0, 0xe5, 0x58, 0xb4, 0x72, 0x16, 0xe5, 0x59, 0xb4, 0x35, 0x11, 0x90,
-0x05, 0x00, 0x74, 0xe2, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0,
-0x7f, 0x01, 0x12, 0x0d, 0x2a, 0x90, 0x02, 0xa2, 0xe0, 0x44, 0xc0, 0xf0, 0x90, 0x10, 0x04, 0xe0,
-0x44, 0x0c, 0xf0, 0xe4, 0xf5, 0x52, 0xf5, 0x55, 0x30, 0x02, 0x09, 0xc2, 0x02, 0x7d, 0x01, 0xaf,
-0x41, 0x12, 0x19, 0x61, 0x30, 0x03, 0x02, 0xc2, 0x03, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xd2, 0xaf,
-0x22, 0xef, 0xf4, 0x60, 0x2d, 0xe4, 0xfe, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5,
-0x83, 0xe0, 0xb4, 0xff, 0x19, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xef,
-0xf0, 0x74, 0x1c, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe,
-0x04, 0xd5, 0x22, 0x22, 0x22, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1, 0x4d, 0xc2, 0xaf, 0x90, 0x70,
-0x28, 0xe0, 0x90, 0x10, 0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90, 0x10, 0x1d, 0xf0, 0x90, 0x70,
-0x2a, 0xe0, 0x90, 0x10, 0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x62, 0x90, 0x10, 0x1e, 0xe0,
-0x20, 0xe1, 0xf3, 0x90, 0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0, 0x90, 0x10, 0x1d, 0xe0, 0x90,
-0x70, 0x29, 0xf0, 0x90, 0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0, 0x30, 0x4a, 0x07, 0x90, 0x70,
-0x24, 0xe0, 0x44, 0x01, 0xf0, 0xc2, 0x05, 0xd2, 0xaf, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x7b, 0xc4,
-0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x32, 0x02, 0x10, 0x78, 0x02, 0x13, 0x1f, 0x02,
-0x13, 0x20, 0x02, 0x13, 0x3f, 0x02, 0x13, 0x44, 0x12, 0x13, 0x40, 0x22, 0x02, 0x17, 0xae, 0x02,
-0x18, 0xd2, 0x02, 0x14, 0x3d, 0x02, 0x13, 0x78, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x19,
-0x95, 0x22, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe3, 0x1b, 0xe5, 0x4c, 0x30, 0xe0, 0x04, 0x7f, 0x40,
-0x80, 0x02, 0x7f, 0x00, 0x90, 0x10, 0x2f, 0xef, 0xf0, 0x90, 0x01, 0x8c, 0x74, 0x08, 0xf0, 0xe4,
-0x90, 0x01, 0xa7, 0xf0, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe0, 0x1c, 0x90, 0x01, 0x80, 0xe0, 0xb4,
-0x02, 0x15, 0xa3, 0xe0, 0xb4, 0x01, 0x10, 0x90, 0x01, 0x84, 0xe0, 0xb4, 0x81, 0x09, 0x90, 0x01,
-0x8c, 0x74, 0x01, 0xf0, 0x12, 0x0d, 0xdd, 0x22, 0x90, 0x04, 0x14, 0xe0, 0x20, 0xe7, 0x03, 0x02,
-0x13, 0x1e, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0, 0x12, 0x0a, 0xb6, 0x10,
-0xd9, 0x31, 0x10, 0xbd, 0x36, 0x11, 0x02, 0x50, 0x11, 0x39, 0x51, 0x11, 0x42, 0x52, 0x11, 0x42,
-0x53, 0x11, 0x42, 0x54, 0x11, 0x83, 0x55, 0x11, 0xd2, 0x56, 0x12, 0x25, 0x70, 0x12, 0x50, 0x71,
-0x12, 0x7e, 0x72, 0x12, 0xd5, 0x73, 0x12, 0xf6, 0x80, 0x00, 0x00, 0x13, 0x1e, 0x90, 0x70, 0x11,
-0xe0, 0xf5, 0x3c, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe5, 0x56,
-0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17, 0x20, 0x02, 0x03, 0x30, 0x03, 0x1d, 0x7d,
-0x02, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13,
-0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17, 0x85, 0x56, 0x41, 0xd2,
-0x02, 0x22, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0xff, 0xbf, 0x0a, 0x0d, 0x90, 0x70, 0x11, 0xe0,
-0xb4, 0x08, 0x06, 0x75, 0x4e, 0x01, 0x75, 0x4f, 0x84, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0xff,
-0xbf, 0x02, 0x12, 0x90, 0x70, 0x11, 0xe0, 0x64, 0x08, 0x60, 0x04, 0xe0, 0xb4, 0x20, 0x06, 0x75,
-0x4e, 0x03, 0x75, 0x4f, 0x20, 0xe4, 0xf5, 0x27, 0x22, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, 0x92,
-0x47, 0x22, 0x90, 0x04, 0x04, 0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70, 0x10, 0xe0,
-0xff, 0x74, 0x47, 0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff, 0x74, 0x48,
-0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14,
-0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e,
-0x02, 0x13, 0x17, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x1d, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x17, 0xe5,
-0x47, 0x64, 0x09, 0x60, 0x11, 0xe5, 0x47, 0x64, 0x0a, 0x60, 0x0b, 0xe5, 0x47, 0x64, 0x0b, 0x60,
-0x05, 0xe5, 0x47, 0xb4, 0x0c, 0x08, 0x90, 0x70, 0x11, 0xe0, 0x54, 0x0f, 0xf5, 0x3a, 0xe5, 0x47,
-0xb4, 0x09, 0x08, 0xe5, 0x3a, 0xb4, 0x03, 0x03, 0xe4, 0xf5, 0x46, 0xe5, 0x47, 0xb4, 0x0a, 0x08,
-0xe5, 0x3a, 0xb4, 0x01, 0x03, 0xe4, 0xf5, 0x46, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0xd2,
-0x04, 0x22, 0x90, 0x70, 0x11, 0xe0, 0xf4, 0xff, 0x90, 0x70, 0x10, 0xe0, 0x5f, 0xff, 0x90, 0x70,
-0x11, 0xe0, 0x55, 0x27, 0x4f, 0x90, 0x70, 0x18, 0xf0, 0x90, 0x70, 0x11, 0xe0, 0x90, 0x70, 0x19,
-0xf0, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x30, 0x15, 0x03, 0xd2, 0x14, 0x22, 0x90, 0x70,
-0x18, 0xe0, 0xf5, 0x27, 0x90, 0x02, 0x29, 0xe0, 0xff, 0x90, 0x70, 0x19, 0xe0, 0xfe, 0xef, 0x5e,
-0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5, 0x27, 0xf4, 0xff, 0x90,
-0x02, 0x28, 0xef, 0xf0, 0x22, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed,
-0xf8, 0xe6, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0,
-0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17,
-0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf5, 0x82, 0x8e, 0x83, 0xe0,
-0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90,
-0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x1e, 0x02, 0x13, 0x17, 0x90, 0x10,
-0x00, 0xe0, 0xf5, 0x57, 0x90, 0x10, 0x02, 0xe0, 0xf5, 0x58, 0xa3, 0xe0, 0xf5, 0x59, 0xe5, 0x58,
-0xb4, 0x70, 0x1e, 0xe5, 0x59, 0xb4, 0x30, 0x19, 0x90, 0x05, 0x08, 0xe0, 0x44, 0x01, 0xf0, 0xfd,
-0x90, 0x05, 0x05, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x04, 0xf0, 0xed, 0x54, 0xfe, 0x90, 0x05, 0x08,
-0xf0, 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x75, 0x3a, 0xff, 0x75, 0x3c, 0xff, 0xad, 0x57, 0xaf, 0x56,
-0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56,
-0xf4, 0x60, 0x4b, 0x80, 0x42, 0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x93, 0xe4, 0xfd, 0xaf,
-0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5,
-0x56, 0xf4, 0x60, 0x2a, 0x80, 0x21, 0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x4a, 0xd2, 0x05,
-0xad, 0x57, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70,
-0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x07, 0x90, 0x70, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x22, 0x22,
-0xe5, 0x53, 0x70, 0x1a, 0x30, 0x60, 0x09, 0xb2, 0x4d, 0x30, 0x4d, 0x04, 0x05, 0x46, 0xc2, 0x04,
-0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08, 0xe5, 0x4f, 0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e, 0x22, 0x22,
-0xc2, 0x42, 0xd3, 0x22, 0x30, 0x14, 0x30, 0x90, 0x70, 0x19, 0xe0, 0x55, 0x27, 0xff, 0x90, 0x70,
-0x18, 0xe0, 0x4f, 0xf5, 0x27, 0x90, 0x02, 0x29, 0xe0, 0xff, 0x90, 0x70, 0x19, 0xe0, 0xfe, 0xef,
-0x5e, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5, 0x27, 0xf4, 0xff,
-0x90, 0x02, 0x28, 0xef, 0xf0, 0xc2, 0x14, 0x22, 0xc2, 0x4b, 0xc2, 0x4c, 0xe5, 0x44, 0x12, 0x0a,
-0xb6, 0x13, 0x9a, 0x00, 0x14, 0x28, 0x04, 0x14, 0x24, 0x08, 0x14, 0x04, 0x10, 0x13, 0xae, 0x20,
-0x13, 0xce, 0x60, 0x13, 0xdf, 0xa0, 0x00, 0x00, 0x14, 0x2a, 0x85, 0x48, 0x43, 0x85, 0x4a, 0x42,
-0x85, 0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60, 0x03, 0x02, 0x14, 0x2a, 0x80, 0x1b, 0xe5, 0x48,
-0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4c, 0xc4, 0x54,
-0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x61, 0x53, 0x43, 0x0f, 0x80, 0x5c, 0x85, 0x49,
-0x43, 0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x4d, 0x80, 0x1b, 0xe5,
-0x49, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b, 0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4d, 0xc4,
-0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x30, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x10,
-0xf5, 0x43, 0x80, 0x26, 0xe5, 0x47, 0x64, 0x04, 0x60, 0x05, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43,
-0x5e, 0x04, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30,
-0xf5, 0x43, 0x80, 0x06, 0xd2, 0x4b, 0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x25, 0xe5, 0x42, 0xc4,
-0x54, 0xf0, 0xff, 0xe5, 0x43, 0x54, 0x0f, 0x4f, 0xf5, 0x5f, 0xd2, 0x60, 0x22, 0xd2, 0x15, 0xe5,
-0x47, 0x24, 0xf5, 0x60, 0x0b, 0x24, 0xcb, 0x60, 0x07, 0x24, 0x40, 0x70, 0x06, 0xc2, 0x15, 0x22,
-0x12, 0x17, 0x79, 0x12, 0x14, 0x5f, 0xc2, 0x15, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2,
-0xaf, 0x90, 0x04, 0x14, 0xe0, 0x54, 0x0e, 0x60, 0x04, 0xd2, 0x18, 0x80, 0x08, 0xe5, 0x4e, 0x45,
-0x4f, 0x24, 0xff, 0x92, 0x18, 0xd2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x19, 0x74,
-0x1e, 0xf0, 0xe5, 0x5f, 0x54, 0x0f, 0xf5, 0x2d, 0xe5, 0x25, 0x70, 0x13, 0x30, 0x18, 0x05, 0xe5,
-0x5f, 0x20, 0xe5, 0x0b, 0x30, 0x19, 0x19, 0xe5, 0x5f, 0x54, 0x30, 0xff, 0xbf, 0x30, 0x11, 0xe5,
-0x25, 0x70, 0x05, 0x75, 0x25, 0x0c, 0x80, 0x02, 0x15, 0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f,
-0xe5, 0x5f, 0x30, 0xe6, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5,
-0x47, 0x64, 0x03, 0x70, 0x21, 0x30, 0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x25,
-0x70, 0x03, 0x30, 0x4c, 0x11, 0xc2, 0x4c, 0xe5, 0x25, 0x70, 0x05, 0x75, 0x25, 0x07, 0x80, 0x02,
-0x15, 0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0xe5, 0x47, 0xb4, 0x09, 0x14, 0xe5, 0x44, 0x20, 0xe3, 0x0b,
-0xe5, 0x3a, 0x64, 0x02, 0x60, 0x05, 0xe5, 0x3a, 0xb4, 0x03, 0x04, 0xc2, 0x6c, 0xd2, 0x6d, 0xe5,
-0x47, 0xb4, 0x0a, 0x13, 0xe5, 0x3a, 0xb4, 0x01, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x08, 0xe5,
-0x3a, 0x70, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0x20, 0x69, 0x07, 0xe5, 0x5e, 0x20, 0xe0, 0x02, 0xb2,
-0x68, 0x20, 0x6b, 0x07, 0xe5, 0x5e, 0x20, 0xe1, 0x02, 0xb2, 0x6a, 0x20, 0x6d, 0x07, 0xe5, 0x5e,
-0x20, 0xe2, 0x02, 0xb2, 0x6c, 0x75, 0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x26, 0x30,
-0x68, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe2, 0x04, 0x7f, 0x01, 0x80,
-0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e,
-0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x73, 0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80, 0x26,
-0x30, 0x6a, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe0, 0x04, 0x7f, 0x01,
-0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02,
-0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x75, 0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c, 0x80,
-0x26, 0xe5, 0x47, 0x64, 0x0a, 0x70, 0x22, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe3, 0x80, 0x17,
-0xe5, 0x3a, 0xb4, 0x01, 0x06, 0xe5, 0x46, 0xa2, 0xe3, 0x80, 0x34, 0xe5, 0x46, 0x20, 0xe4, 0x03,
-0x30, 0xe5, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x80, 0x26, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe2,
-0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe1, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54,
-0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92,
-0x71, 0x92, 0x70, 0x90, 0x10, 0x00, 0xe0, 0x90, 0x10, 0x2c, 0xf0, 0x90, 0x10, 0x03, 0xe0, 0xc3,
-0x94, 0x30, 0x40, 0x14, 0xa2, 0x71, 0x92, 0x77, 0xa2, 0x70, 0x92, 0x76, 0xe5, 0x2e, 0x13, 0x13,
-0x54, 0x3f, 0xf5, 0x2e, 0xc2, 0x77, 0xd2, 0x76, 0x90, 0x10, 0x2f, 0xe5, 0x2e, 0xf0, 0xe5, 0x47,
-0x64, 0x06, 0x70, 0x39, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, 0x54, 0x0f,
-0x14, 0x60, 0x0c, 0x24, 0xfe, 0x60, 0x0c, 0x24, 0x03, 0x70, 0x13, 0xc2, 0x38, 0x80, 0x0f, 0xd2,
-0x38, 0x80, 0x0b, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x38, 0x30, 0x47,
-0x05, 0xaf, 0x27, 0x02, 0x17, 0x73, 0xe5, 0x27, 0xf4, 0xff, 0x02, 0x17, 0x73, 0xe5, 0x47, 0x64,
-0x07, 0x60, 0x0f, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x09, 0xe5, 0x47, 0x64, 0x09, 0x60, 0x03, 0x02,
-0x16, 0xf2, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x22, 0x14, 0x60,
-0x25, 0x14, 0x60, 0x2d, 0x24, 0xfc, 0x60, 0x49, 0x24, 0xf9, 0x60, 0x14, 0x24, 0x0e, 0x70, 0x50,
-0xe5, 0x46, 0x13, 0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xe5, 0xf0, 0x24, 0xff, 0x80, 0x3a,
-0xd2, 0x39, 0xc2, 0x38, 0x80, 0x3e, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x1d, 0xc3, 0x80,
-0x1a, 0xe5, 0x46, 0x30, 0xe2, 0x0d, 0x54, 0x38, 0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f,
-0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0xee, 0x4f, 0x24, 0xff, 0x92, 0x38, 0xc2, 0x39, 0x80,
-0x13, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x39, 0xc2, 0x38, 0x80, 0x04,
-0xc2, 0x38, 0xc2, 0x39, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5, 0x27, 0xf4, 0xff, 0x02,
-0x17, 0x73, 0xe5, 0x47, 0x64, 0x0c, 0x60, 0x06, 0xe5, 0x47, 0x64, 0x0b, 0x70, 0x7a, 0x90, 0x02,
-0x29, 0xe0, 0x54, 0xfd, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x20, 0x14, 0x60, 0x21, 0x14, 0x60, 0x2b,
-0x24, 0xfc, 0x60, 0x45, 0x24, 0xf9, 0x60, 0x12, 0x24, 0x0e, 0x70, 0x4a, 0xe5, 0x46, 0x13, 0x13,
-0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xe5, 0xf0, 0x80, 0x29, 0xd2, 0x39, 0x80, 0x3a, 0xe5, 0x46,
-0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x39, 0x80, 0x2d, 0xe5, 0x46, 0x30, 0xe2, 0x0d,
-0x54, 0x38, 0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f,
-0x00, 0xee, 0x4f, 0x24, 0xff, 0x92, 0x39, 0x80, 0x0f, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80,
-0x01, 0xc3, 0x92, 0x39, 0x80, 0x02, 0xc2, 0x39, 0x30, 0x47, 0x04, 0xaf, 0x27, 0x80, 0x04, 0xe5,
-0x27, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0xe5, 0x47, 0xb4, 0x0b, 0x10, 0x90, 0x02,
-0x29, 0xe0, 0x54, 0xeb, 0xf0, 0xe5, 0x27, 0x54, 0xeb, 0x45, 0x45, 0xf5, 0x27, 0x22, 0xe4, 0x90,
-0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x45, 0x80, 0x04, 0xe5, 0x45, 0xf4, 0xff, 0x90, 0x02,
-0x28, 0xef, 0xf0, 0x22, 0x8f, 0x50, 0xd2, 0x59, 0x22, 0x8f, 0x54, 0xd2, 0x58, 0x22, 0xe4, 0xf5,
-0x62, 0xc2, 0xaf, 0xe5, 0x51, 0x14, 0x60, 0x48, 0x14, 0x60, 0x66, 0x24, 0x02, 0x60, 0x03, 0x02,
-0x18, 0xb6, 0xd2, 0x59, 0x75, 0x55, 0x01, 0x90, 0x02, 0xa2, 0xe0, 0x54, 0x7f, 0xf0, 0xa3, 0xe0,
-0x20, 0xe7, 0x23, 0x90, 0x04, 0x34, 0xe0, 0xb4, 0x02, 0x1c, 0xa3, 0xe0, 0xb4, 0x02, 0x17, 0xa3,
-0xe0, 0xb4, 0x02, 0x12, 0x7f, 0x20, 0x12, 0x17, 0xa4, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf3, 0xf0,
-0x75, 0x51, 0x01, 0x02, 0x18, 0xb6, 0xe5, 0x50, 0x70, 0x06, 0x75, 0x62, 0x03, 0x02, 0x18, 0xb6,
-0x90, 0x12, 0x00, 0xe0, 0x54, 0x03, 0x70, 0x12, 0x7f, 0x20, 0x12, 0x17, 0xa4, 0x90, 0x02, 0xa2,
-0xe0, 0x54, 0xbf, 0xf0, 0x75, 0x51, 0x02, 0x02, 0x18, 0xb6, 0xe5, 0x50, 0x70, 0x03, 0x02, 0x18,
-0xb1, 0x90, 0x02, 0xa3, 0xe0, 0x30, 0xe6, 0x03, 0x02, 0x18, 0xad, 0x90, 0x04, 0x37, 0xe0, 0x64,
-0x22, 0x70, 0x7a, 0x90, 0x01, 0x8a, 0x74, 0x7e, 0xf0, 0x90, 0x01, 0x96, 0xf0, 0x90, 0x12, 0x04,
-0x74, 0x0a, 0xf0, 0xe5, 0x58, 0xb4, 0x72, 0x15, 0xe5, 0x59, 0xb4, 0x35, 0x10, 0xe4, 0x90, 0x05,
-0x00, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0, 0x7f, 0x01, 0x12,
-0x0d, 0x48, 0x90, 0x13, 0x28, 0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xf0, 0xf0, 0xe5, 0x59,
-0xb4, 0x35, 0x14, 0xe5, 0x3c, 0xf4, 0x60, 0x06, 0xa3, 0xe0, 0x54, 0xf3, 0x80, 0x14, 0x90, 0x13,
-0x2a, 0xe0, 0x54, 0xfb, 0xf0, 0x80, 0x14, 0xe5, 0x3c, 0xf4, 0x90, 0x13, 0x2a, 0x60, 0x08, 0xe0,
-0x54, 0xf2, 0x45, 0x3c, 0xf0, 0x80, 0x04, 0xe0, 0x54, 0xfa, 0xf0, 0x90, 0x04, 0x01, 0xe0, 0x54,
-0xfd, 0xf0, 0x75, 0x62, 0x01, 0x75, 0x55, 0x02, 0xe4, 0xf5, 0x51, 0x80, 0x09, 0xe5, 0x50, 0x70,
-0x05, 0x75, 0x62, 0x03, 0xf5, 0x51, 0xe5, 0x62, 0x60, 0x15, 0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2,
-0x59, 0xad, 0x62, 0xaf, 0x40, 0x12, 0x19, 0x61, 0xe5, 0x62, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2,
-0xaf, 0x22, 0xc2, 0xaf, 0x30, 0x01, 0x12, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xf5, 0x51, 0xc2, 0x59,
-0xc2, 0x01, 0x7d, 0x02, 0xaf, 0x40, 0x12, 0x19, 0x61, 0xe5, 0x52, 0x14, 0x60, 0x09, 0x04, 0x70,
-0x6d, 0x75, 0x52, 0x01, 0x75, 0x55, 0x03, 0x90, 0x04, 0x01, 0xe0, 0x44, 0x0e, 0xf0, 0x90, 0x13,
-0x28, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90,
-0x12, 0x04, 0x74, 0x03, 0xf0, 0xe5, 0x58, 0xb4, 0x72, 0x16, 0xe5, 0x59, 0xb4, 0x35, 0x11, 0x90,
-0x05, 0x00, 0x74, 0xe2, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0,
-0x7f, 0x01, 0x12, 0x0d, 0x48, 0x90, 0x02, 0xa2, 0xe0, 0x44, 0xc0, 0xf0, 0x90, 0x10, 0x04, 0xe0,
-0x44, 0x0c, 0xf0, 0xe4, 0xf5, 0x52, 0xf5, 0x55, 0x30, 0x02, 0x09, 0xc2, 0x02, 0x7d, 0x01, 0xaf,
-0x41, 0x12, 0x19, 0x61, 0x30, 0x03, 0x02, 0xc2, 0x03, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xd2, 0xaf,
-0x22, 0xef, 0xf4, 0x60, 0x2d, 0xe4, 0xfe, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5,
-0x83, 0xe0, 0xb4, 0xff, 0x19, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xef,
-0xf0, 0x74, 0x1c, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe,
-0x04, 0xd5, 0x22, 0x22, 0x22, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1, 0x4d, 0xc2, 0xaf, 0x90, 0x70,
-0x28, 0xe0, 0x90, 0x10, 0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90, 0x10, 0x1d, 0xf0, 0x90, 0x70,
-0x2a, 0xe0, 0x90, 0x10, 0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x62, 0x90, 0x10, 0x1e, 0xe0,
-0x20, 0xe1, 0xf3, 0x90, 0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0, 0x90, 0x10, 0x1d, 0xe0, 0x90,
-0x70, 0x29, 0xf0, 0x90, 0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0, 0x30, 0x4a, 0x07, 0x90, 0x70,
-0x24, 0xe0, 0x44, 0x01, 0xf0, 0xc2, 0x05, 0xd2, 0xaf, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x65, 0xd3, } ;
diff --git a/drivers/staging/rt2860/common/rtmp_mcu.c b/drivers/staging/rt2860/common/rtmp_mcu.c
index 9f03901433b..844d4b987b7 100644
--- a/drivers/staging/rt2860/common/rtmp_mcu.c
+++ b/drivers/staging/rt2860/common/rtmp_mcu.c
@@ -37,35 +37,38 @@
#include "../rt_config.h"
-#if defined(RT2860) || defined(RT3090)
-#include "firmware.h"
-#include "../../rt3090/firmware.h"
-#endif
-#ifdef RT2870
-#include "../../rt3070/firmware.h"
-#include "firmware_3070.h"
-#endif
-
-#include <linux/bitrev.h>
+#include <linux/crc-ccitt.h>
+#include <linux/firmware.h>
#ifdef RTMP_MAC_USB
-/* */
-/* RT2870 Firmware Spec only used 1 oct for version expression */
-/* */
-#define FIRMWARE_MINOR_VERSION 7
-#endif /* RTMP_MAC_USB // */
-/* New 8k byte firmware size for RT3071/RT3072 */
-#define FIRMWAREIMAGE_MAX_LENGTH 0x2000
-#define FIRMWAREIMAGE_LENGTH (sizeof (FirmwareImage) / sizeof(u8))
-#define FIRMWARE_MAJOR_VERSION 0
+#define FIRMWAREIMAGE_LENGTH 0x1000
-#define FIRMWAREIMAGEV1_LENGTH 0x1000
-#define FIRMWAREIMAGEV2_LENGTH 0x1000
+#define FIRMWARE_2870_MIN_VERSION 12
+#define FIRMWARE_2870_FILENAME "rt2870.bin"
+MODULE_FIRMWARE(FIRMWARE_2870_FILENAME);
-#ifdef RTMP_MAC_PCI
-#define FIRMWARE_MINOR_VERSION 2
-#endif /* RTMP_MAC_PCI // */
+#define FIRMWARE_3070_MIN_VERSION 17
+#define FIRMWARE_3070_FILENAME "rt3070.bin"
+MODULE_FIRMWARE(FIRMWARE_3070_FILENAME);
+
+#define FIRMWARE_3071_MIN_VERSION 17
+#define FIRMWARE_3071_FILENAME "rt3071.bin" /* for RT3071/RT3072 */
+MODULE_FIRMWARE(FIRMWARE_3071_FILENAME);
+
+#else /* RTMP_MAC_PCI */
+
+#define FIRMWAREIMAGE_LENGTH 0x2000
+
+#define FIRMWARE_2860_MIN_VERSION 11
+#define FIRMWARE_2860_FILENAME "rt2860.bin"
+MODULE_FIRMWARE(FIRMWARE_2860_FILENAME);
+
+#define FIRMWARE_3090_MIN_VERSION 19
+#define FIRMWARE_3090_FILENAME "rt3090.bin" /* for RT3090/RT3390 */
+MODULE_FIRMWARE(FIRMWARE_3090_FILENAME);
+
+#endif
/*
========================================================================
@@ -90,6 +93,78 @@ int RtmpAsicEraseFirmware(struct rt_rtmp_adapter *pAd)
return 0;
}
+static const struct firmware *rtmp_get_firmware(struct rt_rtmp_adapter *adapter)
+{
+ const char *name;
+ const struct firmware *fw = NULL;
+ u8 min_version;
+ struct device *dev;
+ int err;
+
+ if (adapter->firmware)
+ return adapter->firmware;
+
+#ifdef RTMP_MAC_USB
+ if (IS_RT3071(adapter)) {
+ name = FIRMWARE_3071_FILENAME;
+ min_version = FIRMWARE_3071_MIN_VERSION;
+ } else if (IS_RT3070(adapter)) {
+ name = FIRMWARE_3070_FILENAME;
+ min_version = FIRMWARE_3070_MIN_VERSION;
+ } else {
+ name = FIRMWARE_2870_FILENAME;
+ min_version = FIRMWARE_2870_MIN_VERSION;
+ }
+ dev = &((struct os_cookie *)adapter->OS_Cookie)->pUsb_Dev->dev;
+#else /* RTMP_MAC_PCI */
+ if (IS_RT3090(adapter) || IS_RT3390(adapter)) {
+ name = FIRMWARE_3090_FILENAME;
+ min_version = FIRMWARE_3090_MIN_VERSION;
+ } else {
+ name = FIRMWARE_2860_FILENAME;
+ min_version = FIRMWARE_2860_MIN_VERSION;
+ }
+ dev = &((struct os_cookie *)adapter->OS_Cookie)->pci_dev->dev;
+#endif
+
+ err = request_firmware(&fw, name, dev);
+ if (err) {
+ dev_err(dev, "firmware file %s request failed (%d)\n",
+ name, err);
+ return NULL;
+ }
+
+ if (fw->size < FIRMWAREIMAGE_LENGTH) {
+ dev_err(dev, "firmware file %s size is invalid\n", name);
+ goto invalid;
+ }
+
+ /* is it new enough? */
+ adapter->FirmwareVersion = fw->data[FIRMWAREIMAGE_LENGTH - 3];
+ if (adapter->FirmwareVersion < min_version) {
+ dev_err(dev,
+ "firmware file %s is too old;"
+ " driver requires v%d or later\n",
+ name, min_version);
+ goto invalid;
+ }
+
+ /* is the internal CRC correct? */
+ if (crc_ccitt(0xffff, fw->data, FIRMWAREIMAGE_LENGTH - 2) !=
+ (fw->data[FIRMWAREIMAGE_LENGTH - 2] |
+ (fw->data[FIRMWAREIMAGE_LENGTH - 1] << 8))) {
+ dev_err(dev, "firmware file %s failed internal CRC\n", name);
+ goto invalid;
+ }
+
+ adapter->firmware = fw;
+ return fw;
+
+invalid:
+ release_firmware(fw);
+ return NULL;
+}
+
/*
========================================================================
@@ -109,46 +184,16 @@ int RtmpAsicEraseFirmware(struct rt_rtmp_adapter *pAd)
*/
int RtmpAsicLoadFirmware(struct rt_rtmp_adapter *pAd)
{
-
+ const struct firmware *fw;
int Status = NDIS_STATUS_SUCCESS;
- u8 *pFirmwareImage = NULL;
- unsigned long FileLength, Index;
+ unsigned long Index;
u32 MacReg = 0;
-#ifdef RTMP_MAC_USB
- u32 Version = (pAd->MACVersion >> 16);
-#endif
- /* New 8k byte firmware size for RT3071/RT3072 */
- {
-#ifdef RTMP_MAC_PCI
- if (IS_RT3090(pAd) || IS_RT3390(pAd)) {
- pFirmwareImage = FirmwareImage_3090;
- FileLength = FIRMWAREIMAGE_MAX_LENGTH;
- } else {
- pFirmwareImage = FirmwareImage_2860;
- FileLength = FIRMWAREIMAGE_MAX_LENGTH;
- }
-#endif /* RTMP_MAC_PCI // */
-#ifdef RTMP_MAC_USB
- /* the firmware image consists of two parts */
- if ((Version != 0x2860) && (Version != 0x2872) && (Version != 0x3070)) { /* use the second part */
- /*printk("KH:Use New Version,part2\n"); */
- pFirmwareImage =
- (u8 *)&
- FirmwareImage_3070[FIRMWAREIMAGEV1_LENGTH];
- FileLength = FIRMWAREIMAGEV2_LENGTH;
- } else {
- /*printk("KH:Use New Version,part1\n"); */
- if (Version == 0x3070)
- pFirmwareImage = FirmwareImage_3070;
- else
- pFirmwareImage = FirmwareImage_2870;
- FileLength = FIRMWAREIMAGEV1_LENGTH;
- }
-#endif /* RTMP_MAC_USB // */
- }
+ fw = rtmp_get_firmware(pAd);
+ if (!fw)
+ return NDIS_STATUS_FAILURE;
- RTMP_WRITE_FIRMWARE(pAd, pFirmwareImage, FileLength);
+ RTMP_WRITE_FIRMWARE(pAd, fw->data, FIRMWAREIMAGE_LENGTH);
/* check if MCU is ready */
Index = 0;
@@ -221,7 +266,7 @@ int RtmpAsicSendCommandToMcu(struct rt_rtmp_adapter *pAd,
("AsicSendCommanToMcu::Mail box is busy\n"));
} while (i++ < 100);
- if (i >= 100) {
+ if (i > 100) {
DBGPRINT_ERR(("H2M_MAILBOX still hold by MCU. command fail\n"));
return FALSE;
}
diff --git a/drivers/staging/rt2860/rt_linux.c b/drivers/staging/rt2860/rt_linux.c
index 9357fb26cc2..b5c78aecf5e 100644
--- a/drivers/staging/rt2860/rt_linux.c
+++ b/drivers/staging/rt2860/rt_linux.c
@@ -25,6 +25,7 @@
*************************************************************************
*/
+#include <linux/firmware.h>
#include <linux/sched.h>
#include "rt_config.h"
@@ -260,6 +261,8 @@ void RTMPFreeAdapter(struct rt_rtmp_adapter *pAd)
NdisFreeSpinLock(&pAd->irq_lock);
+ release_firmware(pAd->firmware);
+
vfree(pAd); /* pci_free_consistent(os_cookie->pci_dev,sizeof(struct rt_rtmp_adapter),pAd,os_cookie->pAd_pa); */
if (os_cookie)
kfree(os_cookie);
@@ -462,9 +465,9 @@ void *duplicate_pkt(struct rt_rtmp_adapter *pAd,
if ((skb =
__dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != NULL) {
skb_reserve(skb, 2);
- NdisMoveMemory(skb->tail, pHeader802_3, HdrLen);
+ NdisMoveMemory(skb_tail_pointer(skb), pHeader802_3, HdrLen);
skb_put(skb, HdrLen);
- NdisMoveMemory(skb->tail, pData, DataSize);
+ NdisMoveMemory(skb_tail_pointer(skb), pData, DataSize);
skb_put(skb, DataSize);
skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
pPacket = OSPKT_TO_RTPKT(skb);
@@ -515,7 +518,7 @@ void *ClonePacket(struct rt_rtmp_adapter *pAd,
pClonedPkt->dev = pRxPkt->dev;
pClonedPkt->data = pData;
pClonedPkt->len = DataSize;
- pClonedPkt->tail = pClonedPkt->data + pClonedPkt->len;
+ skb_set_tail_pointer(pClonedPkt, DataSize)
ASSERT(DataSize < 1530);
}
return pClonedPkt;
@@ -535,7 +538,7 @@ void update_os_packet_info(struct rt_rtmp_adapter *pAd,
pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
pOSPkt->data = pRxBlk->pData;
pOSPkt->len = pRxBlk->DataSize;
- pOSPkt->tail = pOSPkt->data + pOSPkt->len;
+ skb_set_tail_pointer(pOSPkt, pOSPkt->len);
}
void wlan_802_11_to_802_3_packet(struct rt_rtmp_adapter *pAd,
@@ -553,7 +556,7 @@ void wlan_802_11_to_802_3_packet(struct rt_rtmp_adapter *pAd,
pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
pOSPkt->data = pRxBlk->pData;
pOSPkt->len = pRxBlk->DataSize;
- pOSPkt->tail = pOSPkt->data + pOSPkt->len;
+ skb_set_tail_pointer(pOSPkt, pOSPkt->len);
/* */
/* copy 802.3 header */
diff --git a/drivers/staging/rt2860/rt_linux.h b/drivers/staging/rt2860/rt_linux.h
index f85508d9d5a..a7c540f8e3e 100644
--- a/drivers/staging/rt2860/rt_linux.h
+++ b/drivers/staging/rt2860/rt_linux.h
@@ -658,9 +658,9 @@ void linux_pci_unmap_single(void *handle, dma_addr_t dma_addr, size_t size,
(RTPKT_TO_OSPKT(_pkt)->len) = (_len)
#define GET_OS_PKT_DATATAIL(_pkt) \
- (RTPKT_TO_OSPKT(_pkt)->tail)
+ (skb_tail_pointer(RTPKT_TO_OSPKT(_pkt))
#define SET_OS_PKT_DATATAIL(_pkt, _start, _len) \
- ((RTPKT_TO_OSPKT(_pkt))->tail) = (u8 *)((_start) + (_len))
+ (skb_set_tail_pointer(RTPKT_TO_OSPKT(_pkt), _len))
#define GET_OS_PKT_HEAD(_pkt) \
(RTPKT_TO_OSPKT(_pkt)->head)
diff --git a/drivers/staging/rt2860/rt_main_dev.c b/drivers/staging/rt2860/rt_main_dev.c
index c3d92802d0c..fbddb00cfed 100644
--- a/drivers/staging/rt2860/rt_main_dev.c
+++ b/drivers/staging/rt2860/rt_main_dev.c
@@ -216,7 +216,7 @@ int rt28xx_close(struct net_device *dev)
u32 i = 0;
#ifdef RTMP_MAC_USB
- DECLARE_WAIT_QUEUE_HEAD(unlink_wakeup);
+ DECLARE_WAIT_QUEUE_HEAD_ONSTACK(unlink_wakeup);
DECLARE_WAITQUEUE(wait, current);
#endif /* RTMP_MAC_USB // */
diff --git a/drivers/staging/rt2860/rtmp.h b/drivers/staging/rt2860/rtmp.h
index c50abf4b806..4401a55bda6 100644
--- a/drivers/staging/rt2860/rtmp.h
+++ b/drivers/staging/rt2860/rtmp.h
@@ -1719,6 +1719,7 @@ struct rt_rtmp_adapter {
void *OS_Cookie; /* save specific structure relative to OS */
struct net_device *net_dev;
unsigned long VirtualIfCnt;
+ const struct firmware *firmware;
struct rt_rtmp_chip_op chipOps;
u16 ThisTbttNumToNextWakeUp;
@@ -4043,10 +4044,10 @@ int RTUSBMultiRead(struct rt_rtmp_adapter *pAd,
u16 Offset, u8 *pData, u16 length);
int RTUSBMultiWrite(struct rt_rtmp_adapter *pAd,
- u16 Offset, u8 *pData, u16 length);
+ u16 Offset, const u8 *pData, u16 length);
int RTUSBMultiWrite_OneByte(struct rt_rtmp_adapter *pAd,
- u16 Offset, u8 *pData);
+ u16 Offset, const u8 *pData);
int RTUSBReadBBPRegister(struct rt_rtmp_adapter *pAd,
u8 Id, u8 *pValue);
@@ -4112,7 +4113,7 @@ int RTUSBSingleWrite(struct rt_rtmp_adapter *pAd,
u16 Offset, u16 Value);
int RTUSBFirmwareWrite(struct rt_rtmp_adapter *pAd,
- u8 *pFwImage, unsigned long FwLen);
+ const u8 *pFwImage, unsigned long FwLen);
int RTUSBVenderReset(struct rt_rtmp_adapter *pAd);
diff --git a/drivers/staging/rt2860/sta/connect.c b/drivers/staging/rt2860/sta/connect.c
index 17e59ba3d80..55732b10062 100644
--- a/drivers/staging/rt2860/sta/connect.c
+++ b/drivers/staging/rt2860/sta/connect.c
@@ -62,8 +62,8 @@ u8 CipherSuiteWpaNoneAes[] = {
u8 CipherSuiteWpaNoneAesLen =
(sizeof(CipherSuiteWpaNoneAes) / sizeof(u8));
-/* The following MACRO is called after 1. starting an new IBSS, 2. succesfully JOIN an IBSS, */
-/* or 3. succesfully ASSOCIATE to a BSS, 4. successfully RE_ASSOCIATE to a BSS */
+/* The following MACRO is called after 1. starting an new IBSS, 2. successfully JOIN an IBSS, */
+/* or 3. successfully ASSOCIATE to a BSS, 4. successfully RE_ASSOCIATE to a BSS */
/* All settings successfuly negotiated furing MLME state machines become final settings */
/* and are copied to pAd->StaActive */
#define COPY_SETTINGS_FROM_MLME_AUX_TO_ACTIVE_CFG(_pAd) \
diff --git a/drivers/staging/rt2860/sta_ioctl.c b/drivers/staging/rt2860/sta_ioctl.c
index d8fbe6cc694..de4b6277bae 100644
--- a/drivers/staging/rt2860/sta_ioctl.c
+++ b/drivers/staging/rt2860/sta_ioctl.c
@@ -975,10 +975,7 @@ int rt_ioctl_giwscan(struct net_device *dev,
/*================================ */
memset(&iwe, 0, sizeof(iwe));
iwe.cmd = SIOCGIWFREQ;
- if (INFRA_ON(pAdapter) || ADHOC_ON(pAdapter))
- iwe.u.freq.m = pAdapter->ScanTab.BssEntry[i].Channel;
- else
- iwe.u.freq.m = pAdapter->ScanTab.BssEntry[i].Channel;
+ iwe.u.freq.m = pAdapter->ScanTab.BssEntry[i].Channel;
iwe.u.freq.e = 0;
iwe.u.freq.i = 0;
diff --git a/drivers/staging/rt2860/usb_main_dev.c b/drivers/staging/rt2860/usb_main_dev.c
index 925a236e104..1873a79bb03 100644
--- a/drivers/staging/rt2860/usb_main_dev.c
+++ b/drivers/staging/rt2860/usb_main_dev.c
@@ -216,10 +216,6 @@ static int rt2870_suspend(struct usb_interface *intf, pm_message_t state);
static int rt2870_resume(struct usb_interface *intf);
#endif /* CONFIG_PM // */
-static int rtusb_probe(struct usb_interface *intf,
- const struct usb_device_id *id);
-static void rtusb_disconnect(struct usb_interface *intf);
-
static BOOLEAN USBDevConfigInit(IN struct usb_device *dev,
IN struct usb_interface *intf,
struct rt_rtmp_adapter *pAd)
@@ -296,7 +292,7 @@ static BOOLEAN USBDevConfigInit(IN struct usb_device *dev,
}
-static int rtusb_probe(struct usb_interface *intf,
+static int __devinit rtusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct rt_rtmp_adapter *pAd;
diff --git a/drivers/staging/rt2870/Kconfig b/drivers/staging/rt2870/Kconfig
index fd3ba3a3b12..6ea172b433e 100644
--- a/drivers/staging/rt2870/Kconfig
+++ b/drivers/staging/rt2870/Kconfig
@@ -3,5 +3,7 @@ config RT2870
depends on USB && X86 && WLAN
select WIRELESS_EXT
select WEXT_PRIV
+ select CRC_CCITT
+ select FW_LOADER
---help---
This is an experimental driver for the Ralink xx70 wireless chips.
diff --git a/drivers/staging/rt2870/common/rtusb_io.c b/drivers/staging/rt2870/common/rtusb_io.c
index 34443f2243f..cf0d2f5dbc6 100644
--- a/drivers/staging/rt2870/common/rtusb_io.c
+++ b/drivers/staging/rt2870/common/rtusb_io.c
@@ -84,7 +84,7 @@ static int RTUSBFirmwareRun(struct rt_rtmp_adapter *pAd)
========================================================================
*/
int RTUSBFirmwareWrite(struct rt_rtmp_adapter *pAd,
- u8 *pFwImage, unsigned long FwLen)
+ const u8 *pFwImage, unsigned long FwLen)
{
u32 MacReg;
int Status;
@@ -167,7 +167,7 @@ int RTUSBMultiRead(struct rt_rtmp_adapter *pAd,
========================================================================
*/
int RTUSBMultiWrite_OneByte(struct rt_rtmp_adapter *pAd,
- u16 Offset, u8 *pData)
+ u16 Offset, const u8 *pData)
{
int Status;
@@ -175,18 +175,18 @@ int RTUSBMultiWrite_OneByte(struct rt_rtmp_adapter *pAd,
Status = RTUSB_VendorRequest(pAd,
USBD_TRANSFER_DIRECTION_OUT,
DEVICE_VENDOR_REQUEST_OUT,
- 0x6, 0, Offset, pData, 1);
+ 0x6, 0, Offset, (u8 *)pData, 1);
return Status;
}
int RTUSBMultiWrite(struct rt_rtmp_adapter *pAd,
- u16 Offset, u8 *pData, u16 length)
+ u16 Offset, const u8 *pData, u16 length)
{
int Status;
u16 index = 0, Value;
- u8 *pSrc = pData;
+ const u8 *pSrc = pData;
u16 resude = 0;
resude = length % 2;
diff --git a/drivers/staging/rt3070/firmware.h b/drivers/staging/rt3070/firmware.h
deleted file mode 100644
index 5cf9cbcf4ab..00000000000
--- a/drivers/staging/rt3070/firmware.h
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- Copyright (c) 2007, Ralink Technology Corporation
- All rights reserved.
-
- Redistribution. Redistribution and use in binary form, without
- modification, are permitted provided that the following conditions are
- met:
-
- * Redistributions must reproduce the above copyright notice and the
- following disclaimer in the documentation and/or other materials
- provided with the distribution.
- * Neither the name of Ralink Technology Corporation nor the names of its
- suppliers may be used to endorse or promote products derived from this
- software without specific prior written permission.
- * No reverse engineering, decompilation, or disassembly of this software
- is permitted.
-
- Limited patent license. Ralink Technology Corporation grants a world-wide,
- royalty-free, non-exclusive license under patents it now or hereafter
- owns or controls to make, have made, use, import, offer to sell and
- sell ("Utilize") this software, but solely to the extent that any
- such patent is necessary to Utilize the software alone, or in
- combination with an operating system licensed under an approved Open
- Source license as listed by the Open Source Initiative at
- http://opensource.org/licenses. The patent license shall not apply to
- any other combinations which include this software. No hardware per
- se is licensed hereunder.
-
- DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
- BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
- TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- DAMAGE.
-*/
-/* AUTO GEN PLEASE DO NOT MODIFY IT */
-/* AUTO GEN PLEASE DO NOT MODIFY IT */
-
-
-u8 FirmwareImage_2870 [] = {
-0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x32, 0x02, 0x10, 0x78, 0x02, 0x12, 0x67, 0x02,
-0x12, 0x68, 0x02, 0x12, 0x87, 0x02, 0x12, 0x8c, 0x12, 0x12, 0x88, 0x22, 0x02, 0x16, 0x49, 0x02,
-0x17, 0x1f, 0x02, 0x13, 0x77, 0x02, 0x12, 0x8d, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x17,
-0xc1, 0x22, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe3, 0x1b, 0xe5, 0x4c, 0x30, 0xe0, 0x04, 0x7f, 0x40,
-0x80, 0x02, 0x7f, 0x00, 0x90, 0x10, 0x2f, 0xef, 0xf0, 0x90, 0x01, 0x8c, 0x74, 0x08, 0xf0, 0xe4,
-0x90, 0x01, 0xa7, 0xf0, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe0, 0x1c, 0x90, 0x01, 0x80, 0xe0, 0xb4,
-0x02, 0x15, 0xa3, 0xe0, 0xb4, 0x01, 0x10, 0x90, 0x01, 0x84, 0xe0, 0xb4, 0x81, 0x09, 0x90, 0x01,
-0x8c, 0x74, 0x01, 0xf0, 0x12, 0x0d, 0xc8, 0x22, 0x90, 0x04, 0x14, 0xe0, 0x20, 0xe7, 0x03, 0x02,
-0x12, 0x66, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0, 0x12, 0x0a, 0x9d, 0x10,
-0xb7, 0x31, 0x10, 0xe0, 0x50, 0x11, 0x04, 0x51, 0x11, 0x0d, 0x52, 0x11, 0x0d, 0x53, 0x11, 0x0d,
-0x54, 0x11, 0x4e, 0x55, 0x11, 0x7e, 0x70, 0x11, 0xa9, 0x71, 0x11, 0xd7, 0x72, 0x12, 0x1d, 0x73,
-0x12, 0x3e, 0x80, 0x00, 0x00, 0x12, 0x66, 0x20, 0x02, 0x03, 0x30, 0x03, 0x1d, 0x7d, 0x02, 0xaf,
-0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5,
-0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0x85, 0x56, 0x41, 0xd2, 0x02, 0x22,
-0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0x64, 0x02, 0x60, 0x03, 0x02, 0x12, 0x66, 0x90, 0x70, 0x11,
-0xe0, 0x64, 0x08, 0x60, 0x08, 0xe0, 0x64, 0x20, 0x60, 0x03, 0x02, 0x12, 0x66, 0x75, 0x4e, 0x03,
-0x75, 0x4f, 0x20, 0x22, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, 0x92, 0x47, 0x22, 0x90, 0x04, 0x04,
-0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70, 0x10, 0xe0, 0xff, 0x74, 0x47, 0x25, 0x57,
-0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff, 0x74, 0x48, 0x25, 0x57, 0xf8, 0xc6, 0xef,
-0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90,
-0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0xe5, 0x47,
-0x64, 0x07, 0x60, 0x0b, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x05, 0xe5, 0x47, 0xb4, 0x09, 0x08, 0x90,
-0x70, 0x11, 0xe0, 0x54, 0x0f, 0xf5, 0x3a, 0xe5, 0x47, 0xb4, 0x09, 0x08, 0xe5, 0x3a, 0xb4, 0x03,
-0x03, 0xe4, 0xf5, 0x46, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0xd2, 0x04, 0x22, 0x90, 0x70,
-0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf8, 0xe6, 0xf5, 0x57, 0xfd, 0xaf, 0x56,
-0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56,
-0xf4, 0x70, 0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70,
-0x11, 0xe0, 0xfd, 0xed, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x0b,
-0x91, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70,
-0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0x90, 0x10, 0x02, 0xe0, 0xb4, 0x70, 0x1e, 0xa3, 0xe0,
-0xb4, 0x30, 0x19, 0x90, 0x05, 0x08, 0xe0, 0x44, 0x01, 0xf0, 0xfd, 0x90, 0x05, 0x05, 0xe0, 0x54,
-0xfb, 0xf0, 0x44, 0x04, 0xf0, 0xed, 0x54, 0xfe, 0x90, 0x05, 0x08, 0xf0, 0xe4, 0xf5, 0x4e, 0xf5,
-0x4f, 0x75, 0x3a, 0xff, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74, 0x80,
-0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x4b, 0x80, 0x42, 0x90, 0x70, 0x10,
-0xe0, 0x24, 0xff, 0x92, 0x93, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90, 0x04, 0x14, 0x74,
-0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x2a, 0x80, 0x21, 0x90, 0x70,
-0x10, 0xe0, 0x24, 0xff, 0x92, 0x4a, 0xd2, 0x05, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x0b, 0x91, 0x90,
-0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x07, 0x90,
-0x70, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x22, 0x22, 0xe5, 0x53, 0x70, 0x1a, 0x30, 0x60, 0x09, 0xb2,
-0x4d, 0x30, 0x4d, 0x04, 0x05, 0x46, 0xc2, 0x04, 0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08, 0xe5, 0x4f,
-0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e, 0x22, 0x22, 0xc2, 0x42, 0xd3, 0x22, 0x22, 0xc2, 0x4b, 0xc2,
-0x4c, 0xe5, 0x44, 0x12, 0x0a, 0x9d, 0x12, 0xaf, 0x00, 0x13, 0x42, 0x04, 0x13, 0x3e, 0x08, 0x13,
-0x19, 0x10, 0x12, 0xc3, 0x20, 0x12, 0xe3, 0x60, 0x12, 0xf4, 0xa0, 0x00, 0x00, 0x13, 0x44, 0x85,
-0x48, 0x43, 0x85, 0x4a, 0x42, 0x85, 0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60, 0x03, 0x02, 0x13,
-0x44, 0x80, 0x1b, 0xe5, 0x48, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4, 0x54, 0x0f, 0xf5,
-0x42, 0xe5, 0x4c, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x66, 0x53, 0x43,
-0x0f, 0x80, 0x61, 0x85, 0x49, 0x43, 0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5, 0x47, 0x64, 0x06,
-0x70, 0x52, 0x80, 0x1b, 0xe5, 0x49, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b, 0xc4, 0x54, 0x0f,
-0xf5, 0x42, 0xe5, 0x4d, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x35, 0xe5,
-0x43, 0x54, 0x0f, 0x44, 0x10, 0xf5, 0x43, 0x80, 0x2b, 0xe5, 0x47, 0xb4, 0x04, 0x06, 0x53, 0x5e,
-0xfb, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43, 0x5e, 0x04, 0x75, 0x42, 0x09, 0xe5,
-0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30, 0xf5, 0x43, 0x80, 0x06, 0xd2, 0x4b,
-0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x25, 0xe5, 0x42, 0xc4, 0x54, 0xf0, 0xff, 0xe5, 0x43, 0x54,
-0x0f, 0x4f, 0xf5, 0x5f, 0x90, 0x70, 0x44, 0xf0, 0xa3, 0xe5, 0x5e, 0xf0, 0xa3, 0xe5, 0x4a, 0xf0,
-0xa3, 0xe5, 0x48, 0xf0, 0xa3, 0xe5, 0x4c, 0xf0, 0xa3, 0xe5, 0x44, 0xf0, 0xa3, 0xe5, 0x42, 0xf0,
-0xa3, 0xe5, 0x43, 0xf0, 0xd2, 0x60, 0x22, 0xe5, 0x47, 0x60, 0x10, 0x24, 0xc0, 0x70, 0x03, 0x12,
-0x16, 0x29, 0x12, 0x13, 0x8c, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0x90, 0x04,
-0x14, 0xe0, 0x54, 0x0e, 0x60, 0x04, 0xd2, 0x18, 0x80, 0x08, 0xe5, 0x4e, 0x45, 0x4f, 0x24, 0xff,
-0x92, 0x18, 0xd2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x19, 0x74, 0x1e, 0xf0, 0xe5,
-0x5f, 0x54, 0x0f, 0xf5, 0x2d, 0xe5, 0x25, 0x70, 0x13, 0x30, 0x18, 0x05, 0xe5, 0x5f, 0x20, 0xe5,
-0x0b, 0x30, 0x19, 0x19, 0xe5, 0x5f, 0x54, 0x30, 0xff, 0xbf, 0x30, 0x11, 0xe5, 0x25, 0x70, 0x05,
-0x75, 0x25, 0x0c, 0x80, 0x02, 0x15, 0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f, 0xe5, 0x5f, 0x30,
-0xe6, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5, 0x47, 0x64, 0x03,
-0x70, 0x21, 0x30, 0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x25, 0x70, 0x03, 0x30,
-0x4c, 0x11, 0xc2, 0x4c, 0xe5, 0x25, 0x70, 0x05, 0x75, 0x25, 0x07, 0x80, 0x02, 0x15, 0x25, 0xd2,
-0x6c, 0xd2, 0x6d, 0xe5, 0x47, 0xb4, 0x09, 0x14, 0xe5, 0x44, 0x20, 0xe3, 0x0b, 0xe5, 0x3a, 0x64,
-0x02, 0x60, 0x05, 0xe5, 0x3a, 0xb4, 0x03, 0x04, 0xc2, 0x6c, 0xd2, 0x6d, 0x90, 0x70, 0x46, 0xe5,
-0x2d, 0xf0, 0x20, 0x69, 0x07, 0xe5, 0x5e, 0x20, 0xe0, 0x02, 0xb2, 0x68, 0x20, 0x6b, 0x07, 0xe5,
-0x5e, 0x20, 0xe1, 0x02, 0xb2, 0x6a, 0x20, 0x6d, 0x07, 0xe5, 0x5e, 0x20, 0xe2, 0x02, 0xb2, 0x6c,
-0x90, 0x70, 0x47, 0xe5, 0x2d, 0xf0, 0x75, 0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x26,
-0x30, 0x68, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe2, 0x04, 0x7f, 0x01,
-0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02,
-0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x73, 0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80,
-0x26, 0x30, 0x6a, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe0, 0x04, 0x7f,
-0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80,
-0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x75, 0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c,
-0x80, 0x26, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe1, 0x04,
-0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01,
-0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x71, 0x92, 0x70, 0x90, 0x10, 0x00, 0xe0,
-0x90, 0x10, 0x2f, 0xf0, 0x90, 0x10, 0x03, 0xe0, 0xc3, 0x94, 0x30, 0x40, 0x14, 0xa2, 0x71, 0x92,
-0x77, 0xa2, 0x70, 0x92, 0x76, 0xe5, 0x2e, 0x13, 0x13, 0x54, 0x3f, 0xf5, 0x2e, 0xc2, 0x77, 0xd2,
-0x76, 0x90, 0x10, 0x2f, 0xe5, 0x2e, 0xf0, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x4c, 0x90, 0x02, 0x29,
-0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, 0x54, 0x0f, 0x14, 0x60, 0x14, 0x24, 0xfe, 0x60, 0x23,
-0x24, 0x03, 0x60, 0x03, 0x02, 0x16, 0x18, 0x90, 0x02, 0x28, 0xe0, 0x30, 0x47, 0x0f, 0x80, 0x07,
-0x90, 0x02, 0x28, 0xe0, 0x20, 0x47, 0x06, 0x54, 0xfe, 0xf0, 0x02, 0x16, 0x18, 0x44, 0x01, 0xf0,
-0x02, 0x16, 0x18, 0xe5, 0x46, 0x30, 0xe2, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x90, 0x02,
-0x28, 0xe0, 0x54, 0xfe, 0x4f, 0xf0, 0x02, 0x16, 0x18, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x0f, 0xe5,
-0x47, 0x64, 0x08, 0x60, 0x09, 0xe5, 0x47, 0x64, 0x09, 0x60, 0x03, 0x02, 0x16, 0x18, 0xe4, 0xf5,
-0x27, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x2d, 0x14, 0x60, 0x2e,
-0x14, 0x60, 0x36, 0x24, 0xfc, 0x60, 0x5f, 0x24, 0xf9, 0x60, 0x1f, 0x24, 0x0e, 0x70, 0x69, 0xe5,
-0x46, 0x13, 0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xaf, 0xf0, 0x20, 0x47, 0x04, 0x7e, 0x01,
-0x80, 0x02, 0x7e, 0x00, 0xef, 0x6e, 0x24, 0xff, 0x80, 0x45, 0xa2, 0x47, 0x80, 0x41, 0xe5, 0x46,
-0x30, 0xe2, 0x03, 0xd3, 0x80, 0x27, 0xc3, 0x80, 0x24, 0xe5, 0x46, 0x30, 0xe2, 0x0d, 0x54, 0x38,
-0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x20,
-0x47, 0x04, 0x7d, 0x01, 0x80, 0x02, 0x7d, 0x00, 0xef, 0x6d, 0x4e, 0x24, 0xff, 0x92, 0x38, 0xa2,
-0x47, 0xb3, 0x92, 0x39, 0x80, 0x19, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92,
-0x39, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x80, 0x07, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x92, 0x39, 0x90,
-0x02, 0x28, 0xe0, 0x54, 0xfc, 0x45, 0x27, 0xf0, 0x90, 0x70, 0x9c, 0xe5, 0x3a, 0xf0, 0xa3, 0xe5,
-0x47, 0xf0, 0x90, 0x70, 0x41, 0xe5, 0x3a, 0xf0, 0x22, 0xe4, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47,
-0x04, 0xaf, 0x45, 0x80, 0x04, 0xe5, 0x45, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0x8f,
-0x50, 0xd2, 0x59, 0x22, 0x8f, 0x54, 0xd2, 0x58, 0x22, 0xe4, 0xf5, 0x62, 0xc2, 0xaf, 0xe5, 0x51,
-0x14, 0x60, 0x46, 0x14, 0x60, 0x62, 0x24, 0x02, 0x60, 0x03, 0x02, 0x17, 0x03, 0xd2, 0x59, 0x75,
-0x55, 0x01, 0x90, 0x02, 0xa2, 0xe0, 0x54, 0x7f, 0xf0, 0xa3, 0xe0, 0x20, 0xe7, 0x22, 0x90, 0x04,
-0x34, 0xe0, 0xb4, 0x02, 0x1b, 0xa3, 0xe0, 0xb4, 0x02, 0x16, 0xa3, 0xe0, 0xb4, 0x02, 0x11, 0x7f,
-0x20, 0x12, 0x16, 0x3f, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf3, 0xf0, 0x75, 0x51, 0x01, 0x80, 0x73,
-0xe5, 0x50, 0x70, 0x05, 0x75, 0x62, 0x03, 0x80, 0x6a, 0x90, 0x12, 0x00, 0xe0, 0x54, 0x03, 0x70,
-0x11, 0x7f, 0x20, 0x12, 0x16, 0x3f, 0x90, 0x02, 0xa2, 0xe0, 0x54, 0xbf, 0xf0, 0x75, 0x51, 0x02,
-0x80, 0x51, 0xe5, 0x50, 0x70, 0x02, 0x80, 0x46, 0x90, 0x02, 0xa3, 0xe0, 0x20, 0xe6, 0x3b, 0x90,
-0x04, 0x37, 0xe0, 0x64, 0x22, 0x70, 0x33, 0x90, 0x01, 0x8a, 0x74, 0x7e, 0xf0, 0x90, 0x01, 0x96,
-0xf0, 0x90, 0x12, 0x04, 0x74, 0x0a, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0,
-0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xfa, 0xf0, 0x90, 0x04, 0x01, 0xe0, 0x54, 0xf9, 0xf0, 0x75,
-0x62, 0x01, 0x75, 0x55, 0x02, 0xe4, 0xf5, 0x51, 0x80, 0x09, 0xe5, 0x50, 0x70, 0x05, 0x75, 0x62,
-0x03, 0xf5, 0x51, 0xe5, 0x62, 0x60, 0x15, 0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2, 0x59, 0xad, 0x62,
-0xaf, 0x40, 0x12, 0x17, 0x8d, 0xe5, 0x62, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2, 0xaf, 0x22, 0xc2,
-0xaf, 0x30, 0x01, 0x12, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xf5, 0x51, 0xc2, 0x59, 0xc2, 0x01, 0x7d,
-0x02, 0xaf, 0x40, 0x12, 0x17, 0x8d, 0xe5, 0x52, 0x14, 0x60, 0x09, 0x04, 0x70, 0x4c, 0x75, 0x52,
-0x01, 0x75, 0x55, 0x03, 0x90, 0x04, 0x01, 0xe0, 0x44, 0x0e, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x44,
-0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x12, 0x04, 0x74,
-0x03, 0xf0, 0x90, 0x02, 0xa2, 0xe0, 0x44, 0xc0, 0xf0, 0x90, 0x10, 0x04, 0xe0, 0x44, 0x0c, 0xf0,
-0xe4, 0xf5, 0x52, 0xf5, 0x55, 0x30, 0x02, 0x0b, 0xc2, 0x02, 0x7d, 0x01, 0xaf, 0x41, 0x12, 0x17,
-0x8d, 0x80, 0x02, 0xc2, 0x03, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xd2, 0xaf, 0x22, 0xef, 0xf4, 0x60,
-0x2d, 0xe4, 0xfe, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xe0, 0xb4, 0xff,
-0x19, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xef, 0xf0, 0x74, 0x1c, 0x2e,
-0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xd5, 0x22, 0x22,
-0x22, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1, 0x4d, 0xc2, 0xaf, 0x90, 0x70, 0x28, 0xe0, 0x90, 0x10,
-0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90, 0x10, 0x1d, 0xf0, 0x90, 0x70, 0x2a, 0xe0, 0x90, 0x10,
-0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x62, 0x90, 0x10, 0x1e, 0xe0, 0x20, 0xe1, 0xf3, 0x90,
-0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0, 0x90, 0x10, 0x1d, 0xe0, 0x90, 0x70, 0x29, 0xf0, 0x90,
-0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0, 0x30, 0x4a, 0x07, 0x90, 0x70, 0x24, 0xe0, 0x44, 0x01,
-0xf0, 0xc2, 0x05, 0xd2, 0xaf, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x94, 0x3f,
-0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x32, 0x02, 0x10, 0x78, 0x02, 0x12, 0x67, 0x02,
-0x12, 0x68, 0x02, 0x12, 0x87, 0x02, 0x12, 0x8c, 0x12, 0x12, 0x88, 0x22, 0x02, 0x16, 0x49, 0x02,
-0x17, 0x1f, 0x02, 0x13, 0x77, 0x02, 0x12, 0x8d, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x17,
-0xc1, 0x22, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe3, 0x1b, 0xe5, 0x4c, 0x30, 0xe0, 0x04, 0x7f, 0x40,
-0x80, 0x02, 0x7f, 0x00, 0x90, 0x10, 0x2f, 0xef, 0xf0, 0x90, 0x01, 0x8c, 0x74, 0x08, 0xf0, 0xe4,
-0x90, 0x01, 0xa7, 0xf0, 0x90, 0x01, 0x8c, 0xe0, 0x30, 0xe0, 0x1c, 0x90, 0x01, 0x80, 0xe0, 0xb4,
-0x02, 0x15, 0xa3, 0xe0, 0xb4, 0x01, 0x10, 0x90, 0x01, 0x84, 0xe0, 0xb4, 0x81, 0x09, 0x90, 0x01,
-0x8c, 0x74, 0x01, 0xf0, 0x12, 0x0d, 0xdd, 0x22, 0x90, 0x04, 0x14, 0xe0, 0x20, 0xe7, 0x03, 0x02,
-0x12, 0x66, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0, 0x12, 0x0a, 0xb6, 0x10,
-0xb7, 0x31, 0x10, 0xe0, 0x50, 0x11, 0x04, 0x51, 0x11, 0x0d, 0x52, 0x11, 0x0d, 0x53, 0x11, 0x0d,
-0x54, 0x11, 0x4e, 0x55, 0x11, 0x7e, 0x70, 0x11, 0xa9, 0x71, 0x11, 0xd7, 0x72, 0x12, 0x1d, 0x73,
-0x12, 0x3e, 0x80, 0x00, 0x00, 0x12, 0x66, 0x20, 0x02, 0x03, 0x30, 0x03, 0x1d, 0x7d, 0x02, 0xaf,
-0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5,
-0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0x85, 0x56, 0x41, 0xd2, 0x02, 0x22,
-0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0x64, 0x02, 0x60, 0x03, 0x02, 0x12, 0x66, 0x90, 0x70, 0x11,
-0xe0, 0x64, 0x08, 0x60, 0x08, 0xe0, 0x64, 0x20, 0x60, 0x03, 0x02, 0x12, 0x66, 0x75, 0x4e, 0x03,
-0x75, 0x4f, 0x20, 0x22, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, 0x92, 0x47, 0x22, 0x90, 0x04, 0x04,
-0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70, 0x10, 0xe0, 0xff, 0x74, 0x47, 0x25, 0x57,
-0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff, 0x74, 0x48, 0x25, 0x57, 0xf8, 0xc6, 0xef,
-0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90,
-0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70, 0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0xe5, 0x47,
-0x64, 0x07, 0x60, 0x0b, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x05, 0xe5, 0x47, 0xb4, 0x09, 0x08, 0x90,
-0x70, 0x11, 0xe0, 0x54, 0x0f, 0xf5, 0x3a, 0xe5, 0x47, 0xb4, 0x09, 0x08, 0xe5, 0x3a, 0xb4, 0x03,
-0x03, 0xe4, 0xf5, 0x46, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0xd2, 0x04, 0x22, 0x90, 0x70,
-0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf8, 0xe6, 0xf5, 0x57, 0xfd, 0xaf, 0x56,
-0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56,
-0xf4, 0x70, 0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70,
-0x11, 0xe0, 0xfd, 0xed, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x0b,
-0xaa, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x70,
-0x03, 0x02, 0x12, 0x66, 0x02, 0x12, 0x5f, 0x90, 0x10, 0x02, 0xe0, 0xb4, 0x70, 0x1e, 0xa3, 0xe0,
-0xb4, 0x30, 0x19, 0x90, 0x05, 0x08, 0xe0, 0x44, 0x01, 0xf0, 0xfd, 0x90, 0x05, 0x05, 0xe0, 0x54,
-0xfb, 0xf0, 0x44, 0x04, 0xf0, 0xed, 0x54, 0xfe, 0x90, 0x05, 0x08, 0xf0, 0xe4, 0xf5, 0x4e, 0xf5,
-0x4f, 0x75, 0x3a, 0xff, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74, 0x80,
-0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x4b, 0x80, 0x42, 0x90, 0x70, 0x10,
-0xe0, 0x24, 0xff, 0x92, 0x93, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90, 0x04, 0x14, 0x74,
-0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x2a, 0x80, 0x21, 0x90, 0x70,
-0x10, 0xe0, 0x24, 0xff, 0x92, 0x4a, 0xd2, 0x05, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x0b, 0xaa, 0x90,
-0x04, 0x14, 0x74, 0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0xe5, 0x56, 0xf4, 0x60, 0x07, 0x90,
-0x70, 0x25, 0xe0, 0x44, 0x01, 0xf0, 0x22, 0x22, 0xe5, 0x53, 0x70, 0x1a, 0x30, 0x60, 0x09, 0xb2,
-0x4d, 0x30, 0x4d, 0x04, 0x05, 0x46, 0xc2, 0x04, 0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08, 0xe5, 0x4f,
-0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e, 0x22, 0x22, 0xc2, 0x42, 0xd3, 0x22, 0x22, 0xc2, 0x4b, 0xc2,
-0x4c, 0xe5, 0x44, 0x12, 0x0a, 0xb6, 0x12, 0xaf, 0x00, 0x13, 0x42, 0x04, 0x13, 0x3e, 0x08, 0x13,
-0x19, 0x10, 0x12, 0xc3, 0x20, 0x12, 0xe3, 0x60, 0x12, 0xf4, 0xa0, 0x00, 0x00, 0x13, 0x44, 0x85,
-0x48, 0x43, 0x85, 0x4a, 0x42, 0x85, 0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60, 0x03, 0x02, 0x13,
-0x44, 0x80, 0x1b, 0xe5, 0x48, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4, 0x54, 0x0f, 0xf5,
-0x42, 0xe5, 0x4c, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x66, 0x53, 0x43,
-0x0f, 0x80, 0x61, 0x85, 0x49, 0x43, 0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5, 0x47, 0x64, 0x06,
-0x70, 0x52, 0x80, 0x1b, 0xe5, 0x49, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b, 0xc4, 0x54, 0x0f,
-0xf5, 0x42, 0xe5, 0x4d, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x35, 0xe5,
-0x43, 0x54, 0x0f, 0x44, 0x10, 0xf5, 0x43, 0x80, 0x2b, 0xe5, 0x47, 0xb4, 0x04, 0x06, 0x53, 0x5e,
-0xfb, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43, 0x5e, 0x04, 0x75, 0x42, 0x09, 0xe5,
-0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30, 0xf5, 0x43, 0x80, 0x06, 0xd2, 0x4b,
-0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x25, 0xe5, 0x42, 0xc4, 0x54, 0xf0, 0xff, 0xe5, 0x43, 0x54,
-0x0f, 0x4f, 0xf5, 0x5f, 0x90, 0x70, 0x44, 0xf0, 0xa3, 0xe5, 0x5e, 0xf0, 0xa3, 0xe5, 0x4a, 0xf0,
-0xa3, 0xe5, 0x48, 0xf0, 0xa3, 0xe5, 0x4c, 0xf0, 0xa3, 0xe5, 0x44, 0xf0, 0xa3, 0xe5, 0x42, 0xf0,
-0xa3, 0xe5, 0x43, 0xf0, 0xd2, 0x60, 0x22, 0xe5, 0x47, 0x60, 0x10, 0x24, 0xc0, 0x70, 0x03, 0x12,
-0x16, 0x29, 0x12, 0x13, 0x8c, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0x90, 0x04,
-0x14, 0xe0, 0x54, 0x0e, 0x60, 0x04, 0xd2, 0x18, 0x80, 0x08, 0xe5, 0x4e, 0x45, 0x4f, 0x24, 0xff,
-0x92, 0x18, 0xd2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x19, 0x74, 0x1e, 0xf0, 0xe5,
-0x5f, 0x54, 0x0f, 0xf5, 0x2d, 0xe5, 0x25, 0x70, 0x13, 0x30, 0x18, 0x05, 0xe5, 0x5f, 0x20, 0xe5,
-0x0b, 0x30, 0x19, 0x19, 0xe5, 0x5f, 0x54, 0x30, 0xff, 0xbf, 0x30, 0x11, 0xe5, 0x25, 0x70, 0x05,
-0x75, 0x25, 0x0c, 0x80, 0x02, 0x15, 0x25, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f, 0xe5, 0x5f, 0x30,
-0xe6, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5, 0x47, 0x64, 0x03,
-0x70, 0x21, 0x30, 0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x25, 0x70, 0x03, 0x30,
-0x4c, 0x11, 0xc2, 0x4c, 0xe5, 0x25, 0x70, 0x05, 0x75, 0x25, 0x07, 0x80, 0x02, 0x15, 0x25, 0xd2,
-0x6c, 0xd2, 0x6d, 0xe5, 0x47, 0xb4, 0x09, 0x14, 0xe5, 0x44, 0x20, 0xe3, 0x0b, 0xe5, 0x3a, 0x64,
-0x02, 0x60, 0x05, 0xe5, 0x3a, 0xb4, 0x03, 0x04, 0xc2, 0x6c, 0xd2, 0x6d, 0x90, 0x70, 0x46, 0xe5,
-0x2d, 0xf0, 0x20, 0x69, 0x07, 0xe5, 0x5e, 0x20, 0xe0, 0x02, 0xb2, 0x68, 0x20, 0x6b, 0x07, 0xe5,
-0x5e, 0x20, 0xe1, 0x02, 0xb2, 0x6a, 0x20, 0x6d, 0x07, 0xe5, 0x5e, 0x20, 0xe2, 0x02, 0xb2, 0x6c,
-0x90, 0x70, 0x47, 0xe5, 0x2d, 0xf0, 0x75, 0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x26,
-0x30, 0x68, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe2, 0x04, 0x7f, 0x01,
-0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02,
-0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x73, 0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80,
-0x26, 0x30, 0x6a, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe0, 0x04, 0x7f,
-0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80,
-0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x75, 0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c,
-0x80, 0x26, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80, 0x1d, 0xe5, 0x5e, 0x20, 0xe1, 0x04,
-0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01,
-0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x71, 0x92, 0x70, 0x90, 0x10, 0x00, 0xe0,
-0x90, 0x10, 0x2f, 0xf0, 0x90, 0x10, 0x03, 0xe0, 0xc3, 0x94, 0x30, 0x40, 0x14, 0xa2, 0x71, 0x92,
-0x77, 0xa2, 0x70, 0x92, 0x76, 0xe5, 0x2e, 0x13, 0x13, 0x54, 0x3f, 0xf5, 0x2e, 0xc2, 0x77, 0xd2,
-0x76, 0x90, 0x10, 0x2f, 0xe5, 0x2e, 0xf0, 0xe5, 0x47, 0x64, 0x06, 0x70, 0x4c, 0x90, 0x02, 0x29,
-0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, 0x54, 0x0f, 0x14, 0x60, 0x14, 0x24, 0xfe, 0x60, 0x23,
-0x24, 0x03, 0x60, 0x03, 0x02, 0x16, 0x18, 0x90, 0x02, 0x28, 0xe0, 0x30, 0x47, 0x0f, 0x80, 0x07,
-0x90, 0x02, 0x28, 0xe0, 0x20, 0x47, 0x06, 0x54, 0xfe, 0xf0, 0x02, 0x16, 0x18, 0x44, 0x01, 0xf0,
-0x02, 0x16, 0x18, 0xe5, 0x46, 0x30, 0xe2, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x90, 0x02,
-0x28, 0xe0, 0x54, 0xfe, 0x4f, 0xf0, 0x02, 0x16, 0x18, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x0f, 0xe5,
-0x47, 0x64, 0x08, 0x60, 0x09, 0xe5, 0x47, 0x64, 0x09, 0x60, 0x03, 0x02, 0x16, 0x18, 0xe4, 0xf5,
-0x27, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x2d, 0x14, 0x60, 0x2e,
-0x14, 0x60, 0x36, 0x24, 0xfc, 0x60, 0x5f, 0x24, 0xf9, 0x60, 0x1f, 0x24, 0x0e, 0x70, 0x69, 0xe5,
-0x46, 0x13, 0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xaf, 0xf0, 0x20, 0x47, 0x04, 0x7e, 0x01,
-0x80, 0x02, 0x7e, 0x00, 0xef, 0x6e, 0x24, 0xff, 0x80, 0x45, 0xa2, 0x47, 0x80, 0x41, 0xe5, 0x46,
-0x30, 0xe2, 0x03, 0xd3, 0x80, 0x27, 0xc3, 0x80, 0x24, 0xe5, 0x46, 0x30, 0xe2, 0x0d, 0x54, 0x38,
-0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x20,
-0x47, 0x04, 0x7d, 0x01, 0x80, 0x02, 0x7d, 0x00, 0xef, 0x6d, 0x4e, 0x24, 0xff, 0x92, 0x38, 0xa2,
-0x47, 0xb3, 0x92, 0x39, 0x80, 0x19, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92,
-0x39, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x80, 0x07, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x92, 0x39, 0x90,
-0x02, 0x28, 0xe0, 0x54, 0xfc, 0x45, 0x27, 0xf0, 0x90, 0x70, 0x9c, 0xe5, 0x3a, 0xf0, 0xa3, 0xe5,
-0x47, 0xf0, 0x90, 0x70, 0x41, 0xe5, 0x3a, 0xf0, 0x22, 0xe4, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47,
-0x04, 0xaf, 0x45, 0x80, 0x04, 0xe5, 0x45, 0xf4, 0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0x8f,
-0x50, 0xd2, 0x59, 0x22, 0x8f, 0x54, 0xd2, 0x58, 0x22, 0xe4, 0xf5, 0x62, 0xc2, 0xaf, 0xe5, 0x51,
-0x14, 0x60, 0x46, 0x14, 0x60, 0x62, 0x24, 0x02, 0x60, 0x03, 0x02, 0x17, 0x03, 0xd2, 0x59, 0x75,
-0x55, 0x01, 0x90, 0x02, 0xa2, 0xe0, 0x54, 0x7f, 0xf0, 0xa3, 0xe0, 0x20, 0xe7, 0x22, 0x90, 0x04,
-0x34, 0xe0, 0xb4, 0x02, 0x1b, 0xa3, 0xe0, 0xb4, 0x02, 0x16, 0xa3, 0xe0, 0xb4, 0x02, 0x11, 0x7f,
-0x20, 0x12, 0x16, 0x3f, 0x90, 0x10, 0x04, 0xe0, 0x54, 0xf3, 0xf0, 0x75, 0x51, 0x01, 0x80, 0x73,
-0xe5, 0x50, 0x70, 0x05, 0x75, 0x62, 0x03, 0x80, 0x6a, 0x90, 0x12, 0x00, 0xe0, 0x54, 0x03, 0x70,
-0x11, 0x7f, 0x20, 0x12, 0x16, 0x3f, 0x90, 0x02, 0xa2, 0xe0, 0x54, 0xbf, 0xf0, 0x75, 0x51, 0x02,
-0x80, 0x51, 0xe5, 0x50, 0x70, 0x02, 0x80, 0x46, 0x90, 0x02, 0xa3, 0xe0, 0x20, 0xe6, 0x3b, 0x90,
-0x04, 0x37, 0xe0, 0x64, 0x22, 0x70, 0x33, 0x90, 0x01, 0x8a, 0x74, 0x7e, 0xf0, 0x90, 0x01, 0x96,
-0xf0, 0x90, 0x12, 0x04, 0x74, 0x0a, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0,
-0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54, 0xfa, 0xf0, 0x90, 0x04, 0x01, 0xe0, 0x54, 0xf9, 0xf0, 0x75,
-0x62, 0x01, 0x75, 0x55, 0x02, 0xe4, 0xf5, 0x51, 0x80, 0x09, 0xe5, 0x50, 0x70, 0x05, 0x75, 0x62,
-0x03, 0xf5, 0x51, 0xe5, 0x62, 0x60, 0x15, 0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2, 0x59, 0xad, 0x62,
-0xaf, 0x40, 0x12, 0x17, 0x8d, 0xe5, 0x62, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2, 0xaf, 0x22, 0xc2,
-0xaf, 0x30, 0x01, 0x12, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xf5, 0x51, 0xc2, 0x59, 0xc2, 0x01, 0x7d,
-0x02, 0xaf, 0x40, 0x12, 0x17, 0x8d, 0xe5, 0x52, 0x14, 0x60, 0x09, 0x04, 0x70, 0x4c, 0x75, 0x52,
-0x01, 0x75, 0x55, 0x03, 0x90, 0x04, 0x01, 0xe0, 0x44, 0x0e, 0xf0, 0x90, 0x13, 0x28, 0xe0, 0x44,
-0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x12, 0x04, 0x74,
-0x03, 0xf0, 0x90, 0x02, 0xa2, 0xe0, 0x44, 0xc0, 0xf0, 0x90, 0x10, 0x04, 0xe0, 0x44, 0x0c, 0xf0,
-0xe4, 0xf5, 0x52, 0xf5, 0x55, 0x30, 0x02, 0x0b, 0xc2, 0x02, 0x7d, 0x01, 0xaf, 0x41, 0x12, 0x17,
-0x8d, 0x80, 0x02, 0xc2, 0x03, 0xe4, 0x90, 0x01, 0x96, 0xf0, 0xd2, 0xaf, 0x22, 0xef, 0xf4, 0x60,
-0x2d, 0xe4, 0xfe, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xe0, 0xb4, 0xff,
-0x19, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xef, 0xf0, 0x74, 0x1c, 0x2e,
-0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xd5, 0x22, 0x22,
-0x22, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1, 0x4d, 0xc2, 0xaf, 0x90, 0x70, 0x28, 0xe0, 0x90, 0x10,
-0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90, 0x10, 0x1d, 0xf0, 0x90, 0x70, 0x2a, 0xe0, 0x90, 0x10,
-0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x62, 0x90, 0x10, 0x1e, 0xe0, 0x20, 0xe1, 0xf3, 0x90,
-0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0, 0x90, 0x10, 0x1d, 0xe0, 0x90, 0x70, 0x29, 0xf0, 0x90,
-0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0, 0x30, 0x4a, 0x07, 0x90, 0x70, 0x24, 0xe0, 0x44, 0x01,
-0xf0, 0xc2, 0x05, 0xd2, 0xaf, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x9b, 0xc0, } ;
diff --git a/drivers/staging/rt3070/md4.h b/drivers/staging/rt3070/md4.h
index a9cc7b0f3ee..b3fb6372618 100644
--- a/drivers/staging/rt3070/md4.h
+++ b/drivers/staging/rt3070/md4.h
@@ -35,8 +35,8 @@ typedef struct _MD4_CTX_ {
u8 buffer[64]; /* input buffer */
} MD4_CTX;
-void MD4Init (MD4_CTX *);
-void MD4Update (MD4_CTX *, u8 *, UINT);
-void MD4Final (u8 [16], MD4_CTX *);
+void MD4Init(MD4_CTX *);
+void MD4Update(MD4_CTX *, u8 *, UINT);
+void MD4Final(u8 [16], MD4_CTX *);
-#endif //__MD4_H__ \ No newline at end of file
+#endif /*__MD4_H__*/
diff --git a/drivers/staging/rt3090/firmware.h b/drivers/staging/rt3090/firmware.h
deleted file mode 100644
index 17056e26795..00000000000
--- a/drivers/staging/rt3090/firmware.h
+++ /dev/null
@@ -1,517 +0,0 @@
-/* AUTO GEN PLEASE DO NOT MODIFY IT */
-/* AUTO GEN PLEASE DO NOT MODIFY IT */
-
-
-u8 FirmwareImage_3090 [] = {
-0x02, 0x02, 0xf3, 0x02, 0x02, 0xa1, 0x22, 0x22, 0xff, 0xff, 0xff, 0x02, 0x01, 0x27, 0xff, 0xff,
-0xff, 0xff, 0xff, 0x02, 0x00, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x00, 0xd8, 0xc0, 0xe0,
-0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x18, 0xc2, 0xaf, 0x30, 0x45, 0x03,
-0x12, 0x10, 0x09, 0x90, 0x04, 0x16, 0xe0, 0x30, 0xe3, 0x03, 0x74, 0x08, 0xf0, 0x90, 0x04, 0x14,
-0xe0, 0x20, 0xe7, 0x03, 0x02, 0x00, 0xcb, 0x74, 0x80, 0xf0, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x36,
-0x90, 0x04, 0x04, 0xe0, 0x24, 0xcf, 0x60, 0x30, 0x14, 0x60, 0x42, 0x24, 0xe2, 0x60, 0x47, 0x14,
-0x60, 0x55, 0x24, 0x21, 0x70, 0x60, 0xe5, 0x55, 0x24, 0xfe, 0x60, 0x07, 0x14, 0x60, 0x08, 0x24,
-0x02, 0x70, 0x08, 0x7d, 0x01, 0x80, 0x28, 0x7d, 0x02, 0x80, 0x24, 0x90, 0x70, 0x10, 0xe0, 0xf5,
-0x50, 0x85, 0x36, 0x40, 0xd2, 0x01, 0x80, 0x3e, 0xe5, 0x55, 0x64, 0x03, 0x60, 0x04, 0xe5, 0x55,
-0x70, 0x04, 0x7d, 0x02, 0x80, 0x09, 0x85, 0x36, 0x41, 0xd2, 0x02, 0x80, 0x29, 0xad, 0x55, 0xaf,
-0x36, 0x12, 0x02, 0x7d, 0x80, 0x20, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x47, 0x90, 0x70, 0x11, 0xe0,
-0xf5, 0x44, 0x12, 0x10, 0x25, 0x80, 0x06, 0x90, 0x70, 0x10, 0xe0, 0xf5, 0x45, 0xe4, 0xfd, 0xaf,
-0x36, 0x12, 0x02, 0x7d, 0xd2, 0x04, 0x90, 0x70, 0x13, 0xe4, 0xf0, 0xd2, 0xaf, 0xd0, 0xd0, 0xd0,
-0x82, 0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82,
-0xc0, 0xd0, 0xe8, 0xc0, 0xe0, 0xe9, 0xc0, 0xe0, 0xea, 0xc0, 0xe0, 0xeb, 0xc0, 0xe0, 0xec, 0xc0,
-0xe0, 0xed, 0xc0, 0xe0, 0xee, 0xc0, 0xe0, 0xef, 0xc0, 0xe0, 0xc2, 0xaf, 0x30, 0x45, 0x03, 0x12,
-0x10, 0x12, 0xd2, 0xaf, 0xd0, 0xe0, 0xff, 0xd0, 0xe0, 0xfe, 0xd0, 0xe0, 0xfd, 0xd0, 0xe0, 0xfc,
-0xd0, 0xe0, 0xfb, 0xd0, 0xe0, 0xfa, 0xd0, 0xe0, 0xf9, 0xd0, 0xe0, 0xf8, 0xd0, 0xd0, 0xd0, 0x82,
-0xd0, 0x83, 0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0,
-0xd0, 0x75, 0xd0, 0x10, 0xc2, 0xaf, 0x30, 0x45, 0x03, 0x12, 0x10, 0x0c, 0x30, 0x58, 0x0a, 0xe5,
-0x54, 0x60, 0x04, 0x15, 0x54, 0x80, 0x02, 0xc2, 0x58, 0x30, 0x59, 0x0a, 0xe5, 0x50, 0x60, 0x04,
-0x15, 0x50, 0x80, 0x02, 0xc2, 0x59, 0xd5, 0x53, 0x07, 0x30, 0x60, 0x04, 0x15, 0x46, 0xd2, 0x04,
-0x30, 0x45, 0x03, 0x12, 0x10, 0x0f, 0xc2, 0x8d, 0xd2, 0xaf, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83,
-0xd0, 0xf0, 0xd0, 0xe0, 0x32, 0x90, 0x70, 0x2a, 0xe0, 0x30, 0xe1, 0x43, 0xc2, 0xaf, 0x90, 0x70,
-0x28, 0xe0, 0x90, 0x10, 0x1c, 0xf0, 0x90, 0x70, 0x29, 0xe0, 0x90, 0x10, 0x1d, 0xf0, 0x90, 0x70,
-0x2a, 0xe0, 0x90, 0x10, 0x1e, 0xf0, 0x90, 0x10, 0x1c, 0xe0, 0xf5, 0x37, 0x90, 0x10, 0x1e, 0xe0,
-0x20, 0xe1, 0xf3, 0x90, 0x10, 0x1c, 0xe0, 0x90, 0x70, 0x28, 0xf0, 0x90, 0x10, 0x1d, 0xe0, 0x90,
-0x70, 0x29, 0xf0, 0x90, 0x10, 0x1e, 0xe0, 0x90, 0x70, 0x2a, 0xf0, 0xc2, 0x05, 0xd2, 0xaf, 0x22,
-0x12, 0x02, 0xc3, 0x30, 0x45, 0x03, 0x12, 0x10, 0x03, 0x30, 0x01, 0x06, 0x20, 0x09, 0x03, 0x12,
-0x10, 0x1c, 0x30, 0x02, 0x06, 0x20, 0x0a, 0x03, 0x12, 0x10, 0x1f, 0x30, 0x03, 0x06, 0x20, 0x0b,
-0x03, 0x12, 0x10, 0x1f, 0x30, 0x04, 0x06, 0x20, 0x0c, 0x03, 0x12, 0x10, 0x22, 0x20, 0x13, 0x09,
-0x20, 0x11, 0x06, 0xe5, 0x2b, 0x45, 0x2c, 0x60, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0xa9, 0x12,
-0x03, 0x1c, 0x80, 0xbf, 0xc2, 0x43, 0xd2, 0x45, 0xe4, 0xf5, 0x20, 0xf5, 0x21, 0xf5, 0x53, 0xf5,
-0x46, 0xf5, 0x2b, 0xf5, 0x2c, 0xc2, 0x42, 0xf5, 0x51, 0xf5, 0x52, 0xf5, 0x55, 0x90, 0x04, 0x18,
-0x74, 0x80, 0xf0, 0x90, 0x04, 0x1a, 0x74, 0x08, 0xf0, 0xc2, 0x1a, 0xc2, 0x18, 0xc2, 0x1b, 0x22,
-0xc8, 0xef, 0xc8, 0xe6, 0xfa, 0x08, 0xe6, 0x4a, 0x60, 0x0c, 0xc8, 0xef, 0xc8, 0x08, 0xe6, 0x16,
-0x18, 0x70, 0x01, 0x16, 0xc3, 0x22, 0xed, 0x24, 0xff, 0xfd, 0xec, 0x34, 0xff, 0xc8, 0xef, 0xc8,
-0xf6, 0x08, 0xc6, 0xed, 0xc6, 0xd3, 0x22, 0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12,
-0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3, 0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83,
-0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60, 0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0xef, 0xf4, 0x60,
-0x1f, 0xe4, 0xfe, 0x12, 0x03, 0x5b, 0xe0, 0xb4, 0xff, 0x12, 0x12, 0x03, 0x5b, 0xef, 0xf0, 0x74,
-0x1c, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xe3,
-0x22, 0xc0, 0xe0, 0xc0, 0xf0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0xd0, 0x75, 0xd0, 0x08, 0xc2, 0xaf,
-0x30, 0x45, 0x03, 0x12, 0x10, 0x06, 0xd2, 0xaf, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xf0,
-0xd0, 0xe0, 0x32, 0xc2, 0xaf, 0x12, 0x00, 0x06, 0x12, 0x02, 0x04, 0x12, 0x02, 0xdc, 0xe4, 0xf5,
-0x22, 0xf5, 0x47, 0x90, 0x04, 0x00, 0x74, 0x80, 0xf0, 0xd2, 0xaf, 0x22, 0x75, 0x89, 0x02, 0xe4,
-0xf5, 0x8c, 0xf5, 0x8a, 0xf5, 0x88, 0xf5, 0xb8, 0xf5, 0xe8, 0x75, 0x90, 0x18, 0xd2, 0x8c, 0x75,
-0xa8, 0x05, 0x22, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x5f, 0x02, 0x01, 0xc0, 0xff,
-0xc0, 0x26, 0x74, 0x03, 0xc0, 0xe0, 0xc0, 0x82, 0xc0, 0x83, 0x75, 0x26, 0x0a, 0x22, 0xc0, 0x26,
-0x74, 0x03, 0xc0, 0xe0, 0xc0, 0x82, 0xc0, 0x83, 0x75, 0x26, 0x18, 0x22, 0x30, 0x45, 0x03, 0x12,
-0x10, 0x15, 0xe5, 0x20, 0x70, 0x03, 0x20, 0x10, 0x03, 0x30, 0x11, 0x03, 0x43, 0x87, 0x01, 0x22,
-0xce, 0xef, 0xce, 0xee, 0x60, 0x08, 0x7f, 0xff, 0x12, 0x03, 0x71, 0x1e, 0x80, 0xf5, 0x22, 0xc8,
-0xef, 0xc8, 0xe6, 0x60, 0x03, 0x16, 0xc3, 0x22, 0xed, 0x14, 0xf6, 0xd3, 0x22, 0xc8, 0xef, 0xc8,
-0xe6, 0x60, 0x06, 0x16, 0xe6, 0x24, 0xff, 0xb3, 0x22, 0xc3, 0x22, 0x74, 0x14, 0x2e, 0xf5, 0x82,
-0xe4, 0x34, 0x70, 0xf5, 0x83, 0x22, 0xef, 0x90, 0x03, 0x6f, 0x93, 0x90, 0x03, 0x00, 0x73, 0x0a,
-0x18, 0xef, 0x60, 0x03, 0x1f, 0x80, 0xfa, 0x22, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-0xff, 0xff, 0xff, 0x02, 0x10, 0x28, 0x02, 0x10, 0x3b, 0x02, 0x10, 0x3c, 0x02, 0x13, 0x68, 0x02,
-0x13, 0x69, 0x02, 0x14, 0x1e, 0x02, 0x14, 0x1f, 0xc3, 0x22, 0xff, 0xff, 0x02, 0x19, 0xa1, 0x02,
-0x1b, 0x31, 0x02, 0x14, 0xea, 0x02, 0x14, 0x20, 0x30, 0x05, 0x06, 0x20, 0x0d, 0x03, 0x12, 0x01,
-0x75, 0x30, 0x06, 0x06, 0x20, 0x0e, 0x03, 0x12, 0x1c, 0x4f, 0x22, 0x22, 0x90, 0x04, 0x14, 0xe0,
-0x20, 0xe7, 0x03, 0x02, 0x13, 0x67, 0x90, 0x70, 0x12, 0xe0, 0xf5, 0x56, 0x90, 0x04, 0x04, 0xe0,
-0x12, 0x02, 0x57, 0x11, 0x11, 0x30, 0x10, 0xe2, 0x31, 0x10, 0x90, 0x33, 0x10, 0xa0, 0x34, 0x10,
-0xbe, 0x35, 0x10, 0xac, 0x36, 0x11, 0x1f, 0x50, 0x11, 0x68, 0x51, 0x11, 0x71, 0x52, 0x11, 0x71,
-0x53, 0x11, 0x71, 0x54, 0x11, 0xb3, 0x55, 0x12, 0x16, 0x70, 0x12, 0x42, 0x71, 0x12, 0x71, 0x72,
-0x12, 0xda, 0x73, 0x12, 0xfe, 0x80, 0x13, 0x29, 0x83, 0x13, 0x47, 0x84, 0x00, 0x00, 0x13, 0x67,
-0xd2, 0x18, 0xd2, 0x61, 0x75, 0x35, 0x2a, 0x75, 0x32, 0x0b, 0x75, 0x33, 0xb8, 0x02, 0x13, 0x62,
-0xc2, 0x18, 0x90, 0x01, 0x14, 0xe0, 0x54, 0xfd, 0xf0, 0x02, 0x13, 0x62, 0x90, 0x70, 0x11, 0xe0,
-0xf5, 0x3c, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0x22, 0xe5, 0x55,
-0xb4, 0x02, 0x0f, 0xe5, 0x59, 0xb4, 0x28, 0x06, 0x90, 0x01, 0x0d, 0x74, 0x08, 0xf0, 0x7d, 0x01,
-0x80, 0x02, 0x7d, 0x02, 0xaf, 0x56, 0x12, 0x02, 0x7d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0x02,
-0x13, 0x62, 0x20, 0x02, 0x03, 0x30, 0x03, 0x10, 0x7d, 0x02, 0xaf, 0x56, 0x12, 0x02, 0x7d, 0x90,
-0x04, 0x14, 0x74, 0x80, 0xf0, 0x02, 0x13, 0x62, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40, 0x0c, 0x90,
-0x01, 0x0c, 0xe0, 0x44, 0x02, 0xf0, 0xa3, 0xe0, 0x44, 0x04, 0xf0, 0x85, 0x56, 0x41, 0xd2, 0x02,
-0x22, 0x90, 0x70, 0x11, 0xe0, 0xf4, 0x70, 0x03, 0x02, 0x13, 0x67, 0xe0, 0xf5, 0x30, 0x22, 0xe5,
-0x34, 0xc3, 0x94, 0x03, 0x40, 0x07, 0xe5, 0x55, 0x60, 0x03, 0x02, 0x13, 0x67, 0x90, 0x70, 0x10,
-0xe0, 0x54, 0x7f, 0xff, 0xbf, 0x0a, 0x0d, 0x90, 0x70, 0x11, 0xe0, 0xb4, 0x08, 0x06, 0x75, 0x4e,
-0x01, 0x75, 0x4f, 0x84, 0x90, 0x70, 0x10, 0xe0, 0x54, 0x7f, 0x64, 0x02, 0x60, 0x03, 0x02, 0x13,
-0x67, 0x90, 0x70, 0x11, 0xe0, 0x64, 0x08, 0x60, 0x08, 0xe0, 0x64, 0x20, 0x60, 0x03, 0x02, 0x13,
-0x67, 0x75, 0x4e, 0x03, 0x75, 0x4f, 0x20, 0x22, 0x90, 0x70, 0x11, 0xe0, 0x24, 0xff, 0x92, 0x47,
-0x22, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40, 0x07, 0xe5, 0x55, 0x60, 0x03, 0x02, 0x13, 0x09, 0x90,
-0x04, 0x04, 0xe0, 0x25, 0xe0, 0x24, 0x5d, 0xf5, 0x57, 0x90, 0x70, 0x10, 0xe0, 0xff, 0x74, 0x47,
-0x25, 0x57, 0xf8, 0xc6, 0xef, 0xc6, 0x90, 0x70, 0x11, 0xe0, 0xff, 0x74, 0x48, 0x25, 0x57, 0xf8,
-0xc6, 0xef, 0xc6, 0xe4, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x7d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0,
-0x02, 0x13, 0x62, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40, 0x07, 0xe5, 0x55, 0x60, 0x03, 0x02, 0x13,
-0x09, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x23, 0xe5, 0x47, 0x64, 0x08, 0x60, 0x1d, 0xe5, 0x47, 0x64,
-0x09, 0x60, 0x17, 0xe5, 0x47, 0x64, 0x0a, 0x60, 0x11, 0xe5, 0x47, 0x64, 0x0b, 0x60, 0x0b, 0xe5,
-0x47, 0x64, 0x0d, 0x60, 0x05, 0xe5, 0x47, 0xb4, 0x0d, 0x08, 0x90, 0x70, 0x11, 0xe0, 0x54, 0x0f,
-0xf5, 0x3a, 0xe5, 0x47, 0xb4, 0x09, 0x08, 0xe5, 0x3a, 0xb4, 0x03, 0x03, 0xe4, 0xf5, 0x46, 0xe5,
-0x47, 0xb4, 0x0a, 0x08, 0xe5, 0x3a, 0xb4, 0x01, 0x03, 0xe4, 0xf5, 0x46, 0xe4, 0xfd, 0xaf, 0x56,
-0x12, 0x02, 0x7d, 0xd2, 0x04, 0x22, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40, 0x07, 0xe5, 0x55, 0x60,
-0x03, 0x02, 0x13, 0x09, 0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf8,
-0xe6, 0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x7d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0x02,
-0x13, 0x62, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40, 0x07, 0xe5, 0x55, 0x60, 0x03, 0x02, 0x13, 0x09,
-0x90, 0x70, 0x10, 0xe0, 0xfe, 0x90, 0x70, 0x11, 0xe0, 0xfd, 0xed, 0xf5, 0x82, 0x8e, 0x83, 0xe0,
-0xf5, 0x57, 0xfd, 0xaf, 0x56, 0x12, 0x02, 0x7d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0x02, 0x13,
-0x62, 0x90, 0x10, 0x00, 0xe0, 0xf5, 0x57, 0x90, 0x10, 0x02, 0xe0, 0xf5, 0x58, 0xa3, 0xe0, 0xf5,
-0x59, 0xe5, 0x58, 0xb4, 0x70, 0x1e, 0xe5, 0x59, 0xb4, 0x30, 0x19, 0x90, 0x05, 0x08, 0xe0, 0x44,
-0x01, 0xf0, 0xfd, 0x90, 0x05, 0x05, 0xe0, 0x54, 0xfb, 0xf0, 0x44, 0x04, 0xf0, 0xed, 0x54, 0xfe,
-0x90, 0x05, 0x08, 0xf0, 0xe4, 0xf5, 0x4e, 0xf5, 0x4f, 0x75, 0x3a, 0xff, 0xc2, 0x1a, 0xc2, 0x18,
-0xc2, 0x1b, 0xf5, 0x34, 0x90, 0x05, 0xa4, 0x74, 0x11, 0xf0, 0xa3, 0x74, 0xff, 0xf0, 0xa3, 0x74,
-0x03, 0xf0, 0xe4, 0xf5, 0x30, 0xc2, 0x19, 0x75, 0x3c, 0xff, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02,
-0x7d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0x02, 0x13, 0x62, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40,
-0x06, 0xe5, 0x55, 0x60, 0x02, 0x80, 0x22, 0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x93, 0xe4,
-0xfd, 0xaf, 0x56, 0x12, 0x02, 0x7d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0x80, 0x64, 0xe5, 0x34,
-0xc3, 0x94, 0x03, 0x40, 0x0b, 0xe5, 0x55, 0x60, 0x07, 0x7d, 0x03, 0xaf, 0x56, 0x02, 0x02, 0x7d,
-0x90, 0x70, 0x10, 0xe0, 0x24, 0xff, 0x92, 0x4a, 0xd2, 0x05, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02,
-0x7d, 0x90, 0x04, 0x14, 0x74, 0x80, 0xf0, 0x80, 0x39, 0xe4, 0xf5, 0x34, 0xf5, 0x30, 0x90, 0x70,
-0x10, 0xe0, 0xf4, 0x60, 0x03, 0xe0, 0xf5, 0x34, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x7d, 0x90,
-0x04, 0x14, 0x74, 0x80, 0xf0, 0x80, 0x1b, 0xd2, 0x19, 0x05, 0x2f, 0xe5, 0x2f, 0xb4, 0x1a, 0x03,
-0xe4, 0xf5, 0x2f, 0xd2, 0x04, 0xad, 0x57, 0xaf, 0x56, 0x12, 0x02, 0x7d, 0x90, 0x04, 0x14, 0x74,
-0x80, 0xf0, 0xe4, 0x90, 0x70, 0x13, 0xf0, 0x22, 0x22, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40, 0x17,
-0xe5, 0x55, 0xb4, 0x02, 0x12, 0xe5, 0x30, 0x60, 0x0e, 0x30, 0x60, 0x0b, 0x74, 0xfd, 0x25, 0x46,
-0xf5, 0x46, 0xd2, 0x04, 0xe4, 0xf5, 0x53, 0xe5, 0x53, 0x60, 0x03, 0x02, 0x14, 0x1d, 0x30, 0x60,
-0x21, 0xb2, 0x4d, 0x30, 0x4d, 0x1c, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40, 0x11, 0xe5, 0x55, 0xb4,
-0x02, 0x0c, 0xe5, 0x30, 0x60, 0x08, 0x74, 0x03, 0x25, 0x46, 0xf5, 0x46, 0x80, 0x02, 0x05, 0x46,
-0xc2, 0x04, 0xe5, 0x4f, 0x45, 0x4e, 0x60, 0x08, 0xe5, 0x4f, 0x15, 0x4f, 0x70, 0x02, 0x15, 0x4e,
-0x30, 0x1a, 0x49, 0x7f, 0x32, 0x7d, 0xb8, 0x7c, 0x0b, 0x12, 0x02, 0x30, 0x50, 0x06, 0x90, 0x04,
-0x10, 0x74, 0x40, 0xf0, 0x7f, 0x35, 0x7d, 0x32, 0x12, 0x03, 0x3f, 0x50, 0x09, 0x90, 0x10, 0x04,
-0xe0, 0x54, 0xf7, 0xf0, 0xd2, 0x06, 0xe5, 0x35, 0xd3, 0x94, 0x2d, 0x40, 0x30, 0x30, 0x1b, 0x2d,
-0xc2, 0x1b, 0xa2, 0x18, 0x92, 0x1a, 0x20, 0x1a, 0x24, 0x90, 0x04, 0x09, 0xe0, 0x54, 0xdd, 0xf0,
-0x90, 0x10, 0x04, 0xe0, 0x44, 0x08, 0xf0, 0xc2, 0x61, 0xd2, 0x03, 0x22, 0xe4, 0xf5, 0x35, 0xa2,
-0x18, 0x92, 0x1a, 0x30, 0x1a, 0x07, 0x90, 0x04, 0x09, 0xe0, 0x44, 0x22, 0xf0, 0x22, 0x22, 0x22,
-0xc2, 0x4b, 0xc2, 0x4c, 0xe5, 0x44, 0x12, 0x02, 0x57, 0x14, 0x42, 0x00, 0x14, 0xd5, 0x04, 0x14,
-0xd1, 0x08, 0x14, 0xac, 0x10, 0x14, 0x56, 0x20, 0x14, 0x76, 0x60, 0x14, 0x87, 0xa0, 0x00, 0x00,
-0x14, 0xd7, 0x85, 0x48, 0x43, 0x85, 0x4a, 0x42, 0x85, 0x4c, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x60,
-0x03, 0x02, 0x14, 0xd7, 0x80, 0x1b, 0xe5, 0x48, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4a, 0xc4,
-0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4c, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06, 0x70,
-0x66, 0x53, 0x43, 0x0f, 0x80, 0x61, 0x85, 0x49, 0x43, 0x85, 0x4b, 0x42, 0x85, 0x4d, 0x5e, 0xe5,
-0x47, 0x64, 0x06, 0x70, 0x52, 0x80, 0x1b, 0xe5, 0x49, 0xc4, 0x54, 0x0f, 0xf5, 0x43, 0xe5, 0x4b,
-0xc4, 0x54, 0x0f, 0xf5, 0x42, 0xe5, 0x4d, 0xc4, 0x54, 0x0f, 0xf5, 0x5e, 0xe5, 0x47, 0x64, 0x06,
-0x70, 0x35, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x10, 0xf5, 0x43, 0x80, 0x2b, 0xe5, 0x47, 0xb4, 0x04,
-0x06, 0x53, 0x5e, 0xfb, 0x75, 0x42, 0x09, 0xe5, 0x47, 0xb4, 0x05, 0x06, 0x43, 0x5e, 0x04, 0x75,
-0x42, 0x09, 0xe5, 0x47, 0xb4, 0x06, 0x10, 0xe5, 0x43, 0x54, 0x0f, 0x44, 0x30, 0xf5, 0x43, 0x80,
-0x06, 0xd2, 0x4b, 0x80, 0x02, 0xd2, 0x4c, 0xe4, 0xf5, 0x2a, 0xe5, 0x42, 0xc4, 0x54, 0xf0, 0xff,
-0xe5, 0x43, 0x54, 0x0f, 0x4f, 0xf5, 0x5f, 0xd2, 0x60, 0x22, 0xe5, 0x47, 0x60, 0x1a, 0x24, 0xc0,
-0x60, 0x0a, 0x24, 0x35, 0x70, 0x09, 0x12, 0x19, 0x5f, 0x12, 0x15, 0x09, 0x12, 0x19, 0x5f, 0x12,
-0x15, 0x09, 0xc2, 0xaf, 0xc2, 0x04, 0xd2, 0xaf, 0x22, 0xc2, 0xaf, 0x90, 0x04, 0x14, 0xe0, 0x54,
-0x0e, 0x60, 0x04, 0xd2, 0x1c, 0x80, 0x08, 0xe5, 0x4e, 0x45, 0x4f, 0x24, 0xff, 0x92, 0x1c, 0xd2,
-0xaf, 0x90, 0x04, 0x14, 0xe0, 0xa2, 0xe4, 0x92, 0x1d, 0x74, 0x1e, 0xf0, 0xe5, 0x5f, 0x54, 0x0f,
-0xf5, 0x2d, 0xe5, 0x2a, 0x70, 0x13, 0x30, 0x1c, 0x05, 0xe5, 0x5f, 0x20, 0xe5, 0x0b, 0x30, 0x1d,
-0x29, 0xe5, 0x5f, 0x54, 0x30, 0x64, 0x30, 0x70, 0x21, 0xe5, 0x2a, 0x70, 0x15, 0xe5, 0x34, 0xc3,
-0x94, 0x03, 0x40, 0x09, 0xe5, 0x30, 0x60, 0x05, 0x75, 0x2a, 0x05, 0x80, 0x07, 0x75, 0x2a, 0x0c,
-0x80, 0x02, 0x15, 0x2a, 0xd2, 0x6c, 0xd2, 0x6d, 0x80, 0x0f, 0xe5, 0x5f, 0x30, 0xe6, 0x06, 0xc2,
-0x6c, 0xd2, 0x6d, 0x80, 0x04, 0xd2, 0x6c, 0xc2, 0x6d, 0xe5, 0x47, 0x64, 0x03, 0x70, 0x21, 0x30,
-0x4b, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x18, 0xe5, 0x2a, 0x70, 0x03, 0x30, 0x4c, 0x11, 0xc2,
-0x4c, 0xe5, 0x2a, 0x70, 0x05, 0x75, 0x2a, 0x07, 0x80, 0x02, 0x15, 0x2a, 0xd2, 0x6c, 0xd2, 0x6d,
-0xe5, 0x47, 0xb4, 0x09, 0x14, 0xe5, 0x44, 0x20, 0xe3, 0x0b, 0xe5, 0x3a, 0x64, 0x02, 0x60, 0x05,
-0xe5, 0x3a, 0xb4, 0x03, 0x04, 0xc2, 0x6c, 0xd2, 0x6d, 0xe5, 0x47, 0xb4, 0x0a, 0x13, 0xe5, 0x3a,
-0xb4, 0x01, 0x06, 0xc2, 0x6c, 0xd2, 0x6d, 0x80, 0x08, 0xe5, 0x3a, 0x70, 0x04, 0xd2, 0x6c, 0xc2,
-0x6d, 0x20, 0x69, 0x07, 0xe5, 0x5e, 0x20, 0xe0, 0x02, 0xb2, 0x68, 0x20, 0x6b, 0x07, 0xe5, 0x5e,
-0x20, 0xe1, 0x02, 0xb2, 0x6a, 0x20, 0x6d, 0x07, 0xe5, 0x5e, 0x20, 0xe2, 0x02, 0xb2, 0x6c, 0x75,
-0x2e, 0x40, 0x20, 0x69, 0x04, 0xa2, 0x68, 0x80, 0x45, 0x30, 0x68, 0x06, 0xe5, 0x46, 0xa2, 0xe2,
-0x80, 0x3c, 0x30, 0x19, 0x1c, 0xe5, 0x5e, 0x20, 0xe2, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00,
-0xe5, 0x2f, 0xb4, 0x19, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x80,
-0x1d, 0xe5, 0x5e, 0x20, 0xe2, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0,
-0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x73,
-0x92, 0x72, 0x20, 0x6b, 0x04, 0xa2, 0x6a, 0x80, 0x45, 0x30, 0x6a, 0x06, 0xe5, 0x46, 0xa2, 0xe2,
-0x80, 0x3c, 0x30, 0x19, 0x1c, 0xe5, 0x5e, 0x20, 0xe0, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00,
-0xe5, 0x2f, 0xb4, 0x19, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x80,
-0x1d, 0xe5, 0x5e, 0x20, 0xe0, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0,
-0xfe, 0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x75,
-0x92, 0x74, 0x20, 0x6d, 0x04, 0xa2, 0x6c, 0x80, 0x64, 0xe5, 0x47, 0x64, 0x0a, 0x70, 0x19, 0xe5,
-0x3a, 0xb4, 0x01, 0x06, 0xe5, 0x46, 0xa2, 0xe3, 0x80, 0x53, 0xe5, 0x46, 0x20, 0xe4, 0x03, 0x30,
-0xe5, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x80, 0x45, 0x30, 0x6c, 0x06, 0xe5, 0x46, 0xa2, 0xe2, 0x80,
-0x3c, 0x30, 0x19, 0x1c, 0xe5, 0x5e, 0x20, 0xe1, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5,
-0x2f, 0xb4, 0x19, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x80, 0x1d,
-0xe5, 0x5e, 0x20, 0xe1, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0xe5, 0x46, 0x54, 0xf0, 0xfe,
-0xbe, 0xf0, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xee, 0x6f, 0x24, 0xff, 0x92, 0x71, 0x92,
-0x70, 0x90, 0x10, 0x00, 0xe0, 0x90, 0x10, 0x2c, 0xf0, 0x90, 0x10, 0x03, 0xe0, 0xc3, 0x94, 0x30,
-0x40, 0x14, 0xa2, 0x71, 0x92, 0x77, 0xa2, 0x70, 0x92, 0x76, 0xe5, 0x2e, 0x13, 0x13, 0x54, 0x3f,
-0xf5, 0x2e, 0xc2, 0x77, 0xd2, 0x76, 0x90, 0x10, 0x2f, 0xe5, 0x2e, 0xf0, 0xe5, 0x47, 0x64, 0x06,
-0x70, 0x46, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfe, 0xf0, 0xe5, 0x43, 0xc4, 0x54, 0x0f, 0x14, 0x60,
-0x14, 0x24, 0xfe, 0x60, 0x1f, 0x24, 0x03, 0x60, 0x03, 0x02, 0x19, 0x5e, 0x90, 0x02, 0x28, 0xe0,
-0x30, 0x47, 0x0d, 0x80, 0x07, 0x90, 0x02, 0x28, 0xe0, 0x20, 0x47, 0x04, 0x54, 0xfe, 0xf0, 0x22,
-0x44, 0x01, 0xf0, 0x22, 0xe5, 0x46, 0x30, 0xe2, 0x04, 0x7f, 0x01, 0x80, 0x02, 0x7f, 0x00, 0x90,
-0x02, 0x28, 0xe0, 0x54, 0xfe, 0x4f, 0xf0, 0x22, 0xe5, 0x47, 0x64, 0x07, 0x60, 0x0f, 0xe5, 0x47,
-0x64, 0x08, 0x60, 0x09, 0xe5, 0x47, 0x64, 0x09, 0x60, 0x03, 0x02, 0x18, 0x27, 0xe4, 0xf5, 0x27,
-0x90, 0x02, 0x29, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x2d, 0x14, 0x60, 0x2e, 0x14,
-0x60, 0x36, 0x24, 0xfc, 0x60, 0x5f, 0x24, 0xf9, 0x60, 0x1f, 0x24, 0x0e, 0x70, 0x69, 0xe5, 0x46,
-0x13, 0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xaf, 0xf0, 0x20, 0x47, 0x04, 0x7e, 0x01, 0x80,
-0x02, 0x7e, 0x00, 0xef, 0x6e, 0x24, 0xff, 0x80, 0x45, 0xa2, 0x47, 0x80, 0x41, 0xe5, 0x46, 0x30,
-0xe2, 0x03, 0xd3, 0x80, 0x27, 0xc3, 0x80, 0x24, 0xe5, 0x46, 0x30, 0xe2, 0x0d, 0x54, 0x38, 0xc3,
-0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x20, 0x47,
-0x04, 0x7d, 0x01, 0x80, 0x02, 0x7d, 0x00, 0xef, 0x6d, 0x4e, 0x24, 0xff, 0x92, 0x38, 0xa2, 0x47,
-0xb3, 0x92, 0x39, 0x80, 0x19, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x39,
-0xa2, 0x47, 0xb3, 0x92, 0x38, 0x80, 0x07, 0xa2, 0x47, 0xb3, 0x92, 0x38, 0x92, 0x39, 0x90, 0x02,
-0x28, 0xe0, 0x54, 0xfc, 0x02, 0x19, 0x5b, 0xe5, 0x47, 0x64, 0x0c, 0x60, 0x09, 0xe5, 0x47, 0x64,
-0x0b, 0x60, 0x03, 0x02, 0x18, 0xc6, 0xe4, 0xf5, 0x27, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xfd, 0xf0,
-0xe5, 0x3a, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x2e, 0x14, 0x60, 0x38, 0x24, 0xfc, 0x60, 0x5c, 0x24,
-0xf9, 0x60, 0x1d, 0x24, 0x0e, 0x70, 0x61, 0xe5, 0x46, 0x13, 0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03,
-0x84, 0xaf, 0xf0, 0x20, 0x47, 0x04, 0x7e, 0x01, 0x80, 0x02, 0x7e, 0x00, 0xef, 0x6e, 0x80, 0x35,
-0xa2, 0x47, 0x92, 0x39, 0x80, 0x47, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92,
-0x39, 0x80, 0x3a, 0xe5, 0x46, 0x30, 0xe2, 0x0d, 0x54, 0x38, 0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e,
-0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x20, 0x47, 0x04, 0x7d, 0x01, 0x80, 0x02,
-0x7d, 0x00, 0xef, 0x6d, 0x4e, 0x24, 0xff, 0x92, 0x39, 0x80, 0x12, 0xe5, 0x46, 0x30, 0xe2, 0x03,
-0xd3, 0x80, 0x01, 0xc3, 0x92, 0x39, 0x80, 0x05, 0xa2, 0x47, 0xb3, 0x92, 0x39, 0x90, 0x02, 0x28,
-0xe0, 0x54, 0xfd, 0x02, 0x19, 0x5b, 0xe5, 0x47, 0x64, 0x0d, 0x60, 0x03, 0x02, 0x19, 0x5e, 0xf5,
-0x27, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xef, 0xf0, 0xe5, 0x3a, 0x14, 0x60, 0x2b, 0x14, 0x60, 0x2e,
-0x14, 0x60, 0x38, 0x24, 0xfc, 0x60, 0x5c, 0x24, 0xf9, 0x60, 0x1d, 0x24, 0x0e, 0x70, 0x61, 0xe5,
-0x46, 0x13, 0x13, 0x54, 0x3f, 0x75, 0xf0, 0x03, 0x84, 0xaf, 0xf0, 0x20, 0x47, 0x04, 0x7e, 0x01,
-0x80, 0x02, 0x7e, 0x00, 0xef, 0x6e, 0x80, 0x35, 0xa2, 0x47, 0x92, 0x3c, 0x80, 0x47, 0xe5, 0x46,
-0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x3c, 0x80, 0x3a, 0xe5, 0x46, 0x30, 0xe2, 0x0d,
-0x54, 0x38, 0xc3, 0x94, 0x30, 0x50, 0x06, 0x7e, 0x00, 0x7f, 0x01, 0x80, 0x04, 0x7e, 0x00, 0x7f,
-0x00, 0x20, 0x47, 0x04, 0x7d, 0x01, 0x80, 0x02, 0x7d, 0x00, 0xef, 0x6d, 0x4e, 0x24, 0xff, 0x92,
-0x3c, 0x80, 0x12, 0xe5, 0x46, 0x30, 0xe2, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x3c, 0x80, 0x05,
-0xa2, 0x47, 0xb3, 0x92, 0x3c, 0x90, 0x02, 0x28, 0xe0, 0x54, 0xef, 0x45, 0x27, 0xf0, 0x22, 0xe5,
-0x47, 0x64, 0x0b, 0x70, 0x1c, 0x90, 0x02, 0x29, 0xe0, 0x54, 0xeb, 0xf0, 0x30, 0x47, 0x04, 0xaf,
-0x45, 0x80, 0x05, 0xe5, 0x45, 0x64, 0x14, 0xff, 0x90, 0x02, 0x28, 0xe0, 0x54, 0xeb, 0x4f, 0xf0,
-0x22, 0xe4, 0x90, 0x02, 0x29, 0xf0, 0x30, 0x47, 0x04, 0xaf, 0x45, 0x80, 0x04, 0xe5, 0x45, 0xf4,
-0xff, 0x90, 0x02, 0x28, 0xef, 0xf0, 0x22, 0x8f, 0x50, 0xd2, 0x59, 0x22, 0x8f, 0x54, 0xd2, 0x58,
-0x22, 0xe4, 0xf5, 0x37, 0xc2, 0xaf, 0xe5, 0x51, 0x14, 0x60, 0x4a, 0x14, 0x60, 0x6b, 0x24, 0x02,
-0x60, 0x03, 0x02, 0x1b, 0x12, 0xd2, 0x59, 0x75, 0x55, 0x01, 0x20, 0x1a, 0x1c, 0x90, 0x02, 0x08,
-0xe0, 0x54, 0xfe, 0xf0, 0xe0, 0x20, 0xe1, 0x23, 0x90, 0x04, 0x34, 0xe0, 0xb4, 0x02, 0x1c, 0xa3,
-0xe0, 0xb4, 0x02, 0x17, 0xa3, 0xe0, 0xb4, 0x02, 0x12, 0x7f, 0x20, 0x12, 0x19, 0x97, 0x90, 0x10,
-0x04, 0xe0, 0x54, 0xf3, 0xf0, 0x75, 0x51, 0x01, 0x02, 0x1b, 0x12, 0xe5, 0x50, 0x70, 0x06, 0x75,
-0x37, 0x03, 0x02, 0x1b, 0x12, 0x90, 0x12, 0x00, 0xe0, 0x54, 0x03, 0x70, 0x15, 0x7f, 0x20, 0x12,
-0x19, 0x97, 0x20, 0x1a, 0x07, 0x90, 0x02, 0x08, 0xe0, 0x54, 0xfb, 0xf0, 0x75, 0x51, 0x02, 0x02,
-0x1b, 0x12, 0xe5, 0x50, 0x70, 0x03, 0x02, 0x1b, 0x0d, 0x20, 0x1a, 0x15, 0x90, 0x02, 0x08, 0xe0,
-0x30, 0xe3, 0x03, 0x02, 0x1b, 0x09, 0x90, 0x04, 0x37, 0xe0, 0x64, 0x22, 0x60, 0x03, 0x02, 0x1b,
-0x09, 0x90, 0x12, 0x04, 0x74, 0x0a, 0xf0, 0xe5, 0x58, 0xb4, 0x72, 0x15, 0xe5, 0x59, 0xb4, 0x35,
-0x10, 0xe4, 0x90, 0x05, 0x00, 0xf0, 0xa3, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03,
-0xf0, 0x7f, 0x01, 0x12, 0x03, 0x30, 0x90, 0x13, 0x28, 0xe0, 0x54, 0xf0, 0xf0, 0xa3, 0xe0, 0x54,
-0xf0, 0xf0, 0xe5, 0x59, 0xb4, 0x35, 0x14, 0xe5, 0x3c, 0xf4, 0x60, 0x06, 0xa3, 0xe0, 0x54, 0xf3,
-0x80, 0x14, 0x90, 0x13, 0x2a, 0xe0, 0x54, 0xfb, 0xf0, 0x80, 0x14, 0xe5, 0x3c, 0xf4, 0x90, 0x13,
-0x2a, 0x60, 0x08, 0xe0, 0x54, 0xf2, 0x45, 0x3c, 0xf0, 0x80, 0x04, 0xe0, 0x54, 0xfa, 0xf0, 0x20,
-0x1a, 0x07, 0x90, 0x04, 0x01, 0xe0, 0x44, 0x10, 0xf0, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40, 0x09,
-0xe5, 0x30, 0x70, 0x05, 0x75, 0x8c, 0x40, 0x80, 0x03, 0x75, 0x8c, 0x80, 0x90, 0x04, 0x01, 0xe0,
-0x54, 0xfd, 0xf0, 0x20, 0x1a, 0x07, 0x90, 0x12, 0x04, 0xe0, 0x44, 0x04, 0xf0, 0xe5, 0x59, 0xb4,
-0x28, 0x06, 0x90, 0x01, 0x0d, 0xe0, 0xf5, 0x31, 0xe5, 0x34, 0xc3, 0x94, 0x02, 0x40, 0x14, 0x90,
-0x01, 0x0d, 0xe0, 0x44, 0x01, 0xf0, 0xe5, 0x59, 0x64, 0x35, 0x60, 0x07, 0x90, 0x12, 0x04, 0xe0,
-0x54, 0xfd, 0xf0, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40, 0x14, 0x20, 0x02, 0x11, 0x20, 0x03, 0x0e,
-0x90, 0x01, 0x0d, 0xe0, 0x54, 0xfb, 0xf0, 0x90, 0x01, 0x0c, 0xe0, 0x54, 0xfd, 0xf0, 0x75, 0x37,
-0x01, 0x75, 0x55, 0x02, 0xe4, 0xf5, 0x51, 0x80, 0x09, 0xe5, 0x50, 0x70, 0x05, 0x75, 0x37, 0x03,
-0xf5, 0x51, 0xe5, 0x37, 0x60, 0x18, 0xc2, 0x01, 0xe4, 0xf5, 0x51, 0xc2, 0x59, 0x20, 0x1a, 0x0e,
-0xad, 0x37, 0xaf, 0x40, 0x12, 0x1c, 0x1b, 0xe5, 0x37, 0xb4, 0x03, 0x02, 0xd2, 0x03, 0xd2, 0xaf,
-0x22, 0xc2, 0xaf, 0x30, 0x01, 0x0e, 0xe4, 0xf5, 0x51, 0xc2, 0x59, 0xc2, 0x01, 0x7d, 0x02, 0xaf,
-0x40, 0x12, 0x1c, 0x1b, 0xe5, 0x52, 0x14, 0x60, 0x5c, 0x14, 0x60, 0x3a, 0x24, 0x02, 0x60, 0x03,
-0x02, 0x1c, 0x18, 0xe5, 0x34, 0xc3, 0x94, 0x03, 0x40, 0x0c, 0x90, 0x01, 0x0c, 0xe0, 0x44, 0x02,
-0xf0, 0xa3, 0xe0, 0x44, 0x04, 0xf0, 0xe5, 0x34, 0xc3, 0x94, 0x02, 0x40, 0x13, 0x90, 0x12, 0x04,
-0xe0, 0x44, 0x02, 0xf0, 0x7f, 0x32, 0x12, 0x03, 0x30, 0x90, 0x01, 0x0d, 0xe0, 0x54, 0xfe, 0xf0,
-0x75, 0x52, 0x02, 0x75, 0x55, 0x03, 0xe5, 0x59, 0xb4, 0x28, 0x06, 0x90, 0x01, 0x0d, 0xe5, 0x31,
-0xf0, 0x90, 0x12, 0x04, 0xe0, 0x54, 0xfb, 0xf0, 0x7f, 0x20, 0x12, 0x19, 0x9c, 0x75, 0x52, 0x01,
-0x75, 0x55, 0x03, 0x80, 0x73, 0xe5, 0x54, 0x70, 0x6f, 0x90, 0x04, 0x01, 0xe0, 0x44, 0x0e, 0xf0,
-0x20, 0x1a, 0x04, 0xe0, 0x54, 0xef, 0xf0, 0xe4, 0xf5, 0x8c, 0x90, 0x13, 0x28, 0xe0, 0x44, 0x0f,
-0xf0, 0xa3, 0xe0, 0x44, 0x0f, 0xf0, 0xa3, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x12, 0x04, 0x74, 0x03,
-0xf0, 0xe5, 0x58, 0xb4, 0x72, 0x16, 0xe5, 0x59, 0xb4, 0x35, 0x11, 0x90, 0x05, 0x00, 0x74, 0xe2,
-0xf0, 0xa3, 0x74, 0x08, 0xf0, 0xa3, 0x74, 0x01, 0xf0, 0x74, 0x03, 0xf0, 0x7f, 0x01, 0x12, 0x03,
-0x30, 0x20, 0x1a, 0x07, 0x90, 0x02, 0x08, 0xe0, 0x44, 0x05, 0xf0, 0x90, 0x10, 0x04, 0xe0, 0x44,
-0x0c, 0xf0, 0xe4, 0xf5, 0x52, 0xf5, 0x55, 0x30, 0x02, 0x09, 0xc2, 0x02, 0x7d, 0x01, 0xaf, 0x41,
-0x12, 0x1c, 0x1b, 0x30, 0x03, 0x02, 0xc2, 0x03, 0xd2, 0xaf, 0x22, 0xef, 0xf4, 0x60, 0x2d, 0xe4,
-0xfe, 0x74, 0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xe0, 0xb4, 0xff, 0x19, 0x74,
-0x14, 0x2e, 0xf5, 0x82, 0xe4, 0x34, 0x70, 0xf5, 0x83, 0xef, 0xf0, 0x74, 0x1c, 0x2e, 0xf5, 0x82,
-0xe4, 0x34, 0x70, 0xf5, 0x83, 0xed, 0xf0, 0x22, 0x0e, 0xbe, 0x04, 0xd5, 0x22, 0x22, 0x22, 0x30,
-0x1a, 0x77, 0x90, 0x04, 0x37, 0xe0, 0x20, 0xe5, 0x6c, 0x90, 0x04, 0x28, 0xe0, 0xf5, 0x38, 0xa3,
-0xe0, 0xf5, 0x37, 0xf5, 0x39, 0xe4, 0xf5, 0x25, 0xe5, 0x39, 0x75, 0xf0, 0x80, 0xa4, 0x24, 0x00,
-0xff, 0xe5, 0xf0, 0x34, 0x80, 0xfe, 0xe5, 0x37, 0x65, 0x39, 0x70, 0x05, 0xfc, 0x7d, 0x28, 0x80,
-0x04, 0x7c, 0x00, 0x7d, 0x00, 0xef, 0x2d, 0xff, 0xee, 0x3c, 0xfe, 0x12, 0x1c, 0xca, 0x50, 0x07,
-0x90, 0x01, 0x14, 0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x39, 0x65, 0x38, 0x60, 0x10, 0xe4, 0x25, 0x39,
-0xff, 0xe4, 0x34, 0x80, 0x8f, 0x82, 0xf5, 0x83, 0xe0, 0xf5, 0x39, 0x80, 0xbb, 0x90, 0x04, 0x10,
-0x74, 0x01, 0xf0, 0x90, 0x04, 0x28, 0xe5, 0x38, 0xf0, 0xa3, 0xe5, 0x37, 0xf0, 0x90, 0x04, 0x11,
-0x74, 0x01, 0xf0, 0x80, 0x8d, 0xc2, 0x06, 0xd2, 0x1b, 0x22, 0xe5, 0x25, 0xc3, 0x94, 0x06, 0x50,
-0x19, 0x8f, 0x82, 0x8e, 0x83, 0xe0, 0xb4, 0xff, 0x07, 0x05, 0x25, 0xe4, 0xf5, 0x24, 0x80, 0x2e,
-0xe4, 0xf5, 0x25, 0x8f, 0x82, 0x8e, 0x83, 0xf0, 0x80, 0x24, 0xe5, 0x24, 0x75, 0xf0, 0x06, 0x84,
-0x74, 0x08, 0x25, 0xf0, 0xf5, 0x82, 0xe4, 0x34, 0x10, 0xf5, 0x83, 0xe0, 0xfd, 0x8f, 0x82, 0x8e,
-0x83, 0xe0, 0x6d, 0x70, 0x06, 0x05, 0x25, 0x05, 0x24, 0x80, 0x03, 0xe4, 0xf5, 0x25, 0x0f, 0xbf,
-0x00, 0x01, 0x0e, 0xef, 0x54, 0x7f, 0x60, 0x07, 0xe5, 0x25, 0xc3, 0x94, 0x2a, 0x40, 0xab, 0xe5,
-0x25, 0xb4, 0x2a, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xe3, 0x34, } ;
diff --git a/drivers/staging/rtl8187se/Kconfig b/drivers/staging/rtl8187se/Kconfig
index e24a6f7a0d8..155a78e0740 100644
--- a/drivers/staging/rtl8187se/Kconfig
+++ b/drivers/staging/rtl8187se/Kconfig
@@ -3,6 +3,7 @@ config R8187SE
depends on PCI && WLAN
select WIRELESS_EXT
select WEXT_PRIV
+ select EEPROM_93CX6
default N
---help---
If built as a module, it will be called r8187se.ko.
diff --git a/drivers/staging/rtl8187se/Makefile b/drivers/staging/rtl8187se/Makefile
index b395acf5a38..e6adf91cdd2 100644
--- a/drivers/staging/rtl8187se/Makefile
+++ b/drivers/staging/rtl8187se/Makefile
@@ -18,7 +18,6 @@ EXTRA_CFLAGS += -DENABLE_LPS
r8187se-objs := \
r8180_core.o \
- r8180_93cx6.o \
r8180_wx.o \
r8180_rtl8225z2.o \
r8185b_init.o \
diff --git a/drivers/staging/rtl8187se/TODO b/drivers/staging/rtl8187se/TODO
index a762e79873e..704949a9da0 100644
--- a/drivers/staging/rtl8187se/TODO
+++ b/drivers/staging/rtl8187se/TODO
@@ -5,7 +5,6 @@ TODO:
- switch to use shared "librtl" instead of private ieee80211 stack
- switch to use LIB80211
- switch to use MAC80211
-- switch to use EEPROM_93CX6
- use kernel coding style
- checkpatch.pl fixes
- sparse fixes
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h
index 9086047c32d..4cd95c3dc94 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211.h
@@ -29,6 +29,7 @@
#include <linux/jiffies.h>
#include <linux/timer.h>
#include <linux/sched.h>
+#include <linux/semaphore.h>
#include <linux/wireless.h>
#include <linux/ieee80211.h>
@@ -161,10 +162,6 @@ do { if (ieee80211_debug_level & (level)) \
#define IEEE80211_DEBUG(level, fmt, args...) do {} while (0)
#endif /* CONFIG_IEEE80211_DEBUG */
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAC_ARG(x) ((u8 *)(x))[0], ((u8 *)(x))[1], ((u8 *)(x))[2], \
- ((u8 *)(x))[3], ((u8 *)(x))[4], ((u8 *)(x))[5]
-
/*
* To use the debug system;
*
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
index 172e8f3ae6c..40f1b99faad 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c
@@ -285,7 +285,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (!(keyidx & (1 << 5))) {
if (net_ratelimit()) {
printk(KERN_DEBUG "CCMP: received packet without ExtIV"
- " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
+ " flag from %pM\n", hdr->addr2);
}
key->dot11RSNAStatsCCMPFormatErrors++;
return -2;
@@ -298,9 +298,9 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
}
if (!key->key_set) {
if (net_ratelimit()) {
- printk(KERN_DEBUG "CCMP: received packet from " MAC_FMT
+ printk(KERN_DEBUG "CCMP: received packet from %pM"
" with keyid=%d that does not have a configured"
- " key\n", MAC_ARG(hdr->addr2), keyidx);
+ " key\n", hdr->addr2, keyidx);
}
return -3;
}
@@ -315,11 +315,9 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
if (net_ratelimit()) {
- printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT
- " previous PN %02x%02x%02x%02x%02x%02x "
- "received PN %02x%02x%02x%02x%02x%02x\n",
- MAC_ARG(hdr->addr2), MAC_ARG(key->rx_pn),
- MAC_ARG(pn));
+ printk(KERN_DEBUG "CCMP: replay detected: STA=%pM"
+ " previous PN %pm received PN %pm\n",
+ hdr->addr2, key->rx_pn, pn);
}
key->dot11RSNAStatsCCMPReplays++;
return -4;
@@ -347,7 +345,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
if (net_ratelimit()) {
printk(KERN_DEBUG "CCMP: decrypt failed: STA="
- MAC_FMT "\n", MAC_ARG(hdr->addr2));
+ "%pM\n", hdr->addr2);
}
key->dot11RSNAStatsCCMPDecryptErrors++;
return -5;
@@ -423,11 +421,10 @@ static char * ieee80211_ccmp_print_stats(char *p, void *priv)
{
struct ieee80211_ccmp_data *ccmp = priv;
p += sprintf(p, "key[%d] alg=CCMP key_set=%d "
- "tx_pn=%02x%02x%02x%02x%02x%02x "
- "rx_pn=%02x%02x%02x%02x%02x%02x "
+ "tx_pn=%pm rx_pn=%pm "
"format_errors=%d replays=%d decrypt_errors=%d\n",
ccmp->key_idx, ccmp->key_set,
- MAC_ARG(ccmp->tx_pn), MAC_ARG(ccmp->rx_pn),
+ ccmp->tx_pn, ccmp->rx_pn,
ccmp->dot11RSNAStatsCCMPFormatErrors,
ccmp->dot11RSNAStatsCCMPReplays,
ccmp->dot11RSNAStatsCCMPDecryptErrors);
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c
index e6d8385e1d8..a5254111d9a 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c
@@ -385,7 +385,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (!(keyidx & (1 << 5))) {
if (net_ratelimit()) {
printk(KERN_DEBUG "TKIP: received packet without ExtIV"
- " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
+ " flag from %pM\n", hdr->addr2);
}
return -2;
}
@@ -397,9 +397,9 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
}
if (!tkey->key_set) {
if (net_ratelimit()) {
- printk(KERN_DEBUG "TKIP: received packet from " MAC_FMT
+ printk(KERN_DEBUG "TKIP: received packet from %pM"
" with keyid=%d that does not have a configured"
- " key\n", MAC_ARG(hdr->addr2), keyidx);
+ " key\n", hdr->addr2, keyidx);
}
return -3;
}
@@ -410,9 +410,9 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (iv32 < tkey->rx_iv32 ||
(iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
if (net_ratelimit()) {
- printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT
+ printk(KERN_DEBUG "TKIP: replay detected: STA=%pM"
" previous TSC %08x%04x received TSC "
- "%08x%04x\n", MAC_ARG(hdr->addr2),
+ "%08x%04x\n", hdr->addr2,
tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
}
tkey->dot11RSNAStatsTKIPReplays++;
@@ -431,8 +431,8 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
if (net_ratelimit()) {
printk(KERN_DEBUG ": TKIP: failed to decrypt "
- "received packet from " MAC_FMT "\n",
- MAC_ARG(hdr->addr2));
+ "received packet from %pM\n",
+ hdr->addr2);
}
return -7;
}
@@ -450,7 +450,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
}
if (net_ratelimit()) {
printk(KERN_DEBUG "TKIP: ICV error detected: STA="
- MAC_FMT "\n", MAC_ARG(hdr->addr2));
+ "%pM\n", hdr->addr2);
}
tkey->dot11RSNAStatsTKIPICVErrors++;
return -5;
@@ -604,8 +604,8 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
struct ieee80211_hdr_4addr *hdr;
hdr = (struct ieee80211_hdr_4addr *)skb->data;
printk(KERN_DEBUG "%s: Michael MIC verification failed for "
- "MSDU from " MAC_FMT " keyidx=%d\n",
- skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2),
+ "MSDU from %pM keyidx=%d\n",
+ skb->dev ? skb->dev->name : "N/A", hdr->addr2,
keyidx);
if (skb->dev)
ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
index 9128c181bc7..2b7080cc2c0 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c
@@ -311,8 +311,8 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
strcmp(crypt->ops->name, "TKIP") == 0) {
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
- "received packet from " MAC_FMT "\n",
- ieee->dev->name, MAC_ARG(hdr->addr2));
+ "received packet from %pM\n",
+ ieee->dev->name, hdr->addr2);
}
return -1;
}
@@ -323,8 +323,8 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
atomic_dec(&crypt->refcnt);
if (res < 0) {
IEEE80211_DEBUG_DROP(
- "decryption failed (SA=" MAC_FMT
- ") res=%d\n", MAC_ARG(hdr->addr2), res);
+ "decryption failed (SA=%pM"
+ ") res=%d\n", hdr->addr2, res);
if (res == -2)
IEEE80211_DEBUG_DROP("Decryption failed ICV "
"mismatch (key %d)\n",
@@ -356,8 +356,8 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device* ieee, struct sk_buff *s
atomic_dec(&crypt->refcnt);
if (res < 0) {
printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
- " (SA=" MAC_FMT " keyidx=%d)\n",
- ieee->dev->name, MAC_ARG(hdr->addr2), keyidx);
+ " (SA=%pM keyidx=%d)\n",
+ ieee->dev->name, hdr->addr2, keyidx);
return -1;
}
@@ -550,8 +550,8 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
* frames silently instead of filling system log with
* these reports. */
IEEE80211_DEBUG_DROP("Decryption failed (not set)"
- " (SA=" MAC_FMT ")\n",
- MAC_ARG(hdr->addr2));
+ " (SA=%pM)\n",
+ hdr->addr2);
ieee->ieee_stats.rx_discards_undecryptable++;
goto rx_dropped;
}
@@ -709,8 +709,8 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
} else {
IEEE80211_DEBUG_DROP(
"encryption configured, but RX "
- "frame not encrypted (SA=" MAC_FMT ")\n",
- MAC_ARG(hdr->addr2));
+ "frame not encrypted (SA=%pM)\n",
+ hdr->addr2);
goto rx_dropped;
}
}
@@ -729,9 +729,9 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
!ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
IEEE80211_DEBUG_DROP(
"dropped unencrypted RX data "
- "frame from " MAC_FMT
+ "frame from %pM"
" (drop_unencrypted=1)\n",
- MAC_ARG(hdr->addr2));
+ hdr->addr2);
goto rx_dropped;
}
/*
@@ -1196,11 +1196,11 @@ inline int ieee80211_network_init(
}
if (network->mode == 0) {
- IEEE80211_DEBUG_SCAN("Filtered out '%s (" MAC_FMT ")' "
+ IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' "
"network.\n",
escape_essid(network->ssid,
network->ssid_len),
- MAC_ARG(network->bssid));
+ network->bssid);
return 1;
}
@@ -1341,9 +1341,9 @@ inline void ieee80211_process_probe_response(
memset(&network, 0, sizeof(struct ieee80211_network));
IEEE80211_DEBUG_SCAN(
- "'%s' (" MAC_FMT "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
+ "'%s' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
escape_essid(info_element->data, info_element->len),
- MAC_ARG(beacon->header.addr3),
+ beacon->header.addr3,
(beacon->capability & (1<<0xf)) ? '1' : '0',
(beacon->capability & (1<<0xe)) ? '1' : '0',
(beacon->capability & (1<<0xd)) ? '1' : '0',
@@ -1362,10 +1362,10 @@ inline void ieee80211_process_probe_response(
(beacon->capability & (1<<0x0)) ? '1' : '0');
if (ieee80211_network_init(ieee, beacon, &network, stats)) {
- IEEE80211_DEBUG_SCAN("Dropped '%s' (" MAC_FMT ") via %s.\n",
+ IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
escape_essid(info_element->data,
info_element->len),
- MAC_ARG(beacon->header.addr3),
+ beacon->header.addr3,
WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
IEEE80211_STYPE_PROBE_RESP ?
"PROBE RESPONSE" : "BEACON");
@@ -1464,11 +1464,11 @@ inline void ieee80211_process_probe_response(
/* If there are no more slots, expire the oldest */
list_del(&oldest->list);
target = oldest;
- IEEE80211_DEBUG_SCAN("Expired '%s' (" MAC_FMT ") from "
+ IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from "
"network list.\n",
escape_essid(target->ssid,
target->ssid_len),
- MAC_ARG(target->bssid));
+ target->bssid);
} else {
/* Otherwise just pull from the free list */
target = list_entry(ieee->network_free_list.next,
@@ -1478,10 +1478,10 @@ inline void ieee80211_process_probe_response(
#ifdef CONFIG_IEEE80211_DEBUG
- IEEE80211_DEBUG_SCAN("Adding '%s' (" MAC_FMT ") via %s.\n",
+ IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
escape_essid(network.ssid,
network.ssid_len),
- MAC_ARG(network.bssid),
+ network.bssid,
WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
IEEE80211_STYPE_PROBE_RESP ?
"PROBE RESPONSE" : "BEACON");
@@ -1492,10 +1492,10 @@ inline void ieee80211_process_probe_response(
if(ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)
ieee80211_softmac_new_net(ieee,&network);
} else {
- IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n",
+ IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
escape_essid(target->ssid,
target->ssid_len),
- MAC_ARG(target->bssid),
+ target->bssid,
WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
IEEE80211_STYPE_PROBE_RESP ?
"PROBE RESPONSE" : "BEACON");
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
index a2150670ef5..c2f472ee6eb 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
@@ -1573,7 +1573,7 @@ ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
ieee80211_resp_to_assoc_rq(ieee, dest);
}
- printk(KERN_INFO"New client associated: "MAC_FMT"\n", MAC_ARG(dest));
+ printk(KERN_INFO"New client associated: %pM\n", dest);
}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c
index f1d6cb45256..ad42bcdc937 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c
@@ -482,8 +482,7 @@ int ieee80211_wx_set_power(struct ieee80211_device *ieee,
(!ieee->enter_sleep_state) ||
(!ieee->ps_is_queue_empty)){
- printk("ERROR. PS mode is tryied to be use but\
-driver missed a callback\n\n");
+ printk("ERROR. PS mode tried to be use but driver missed a callback\n\n");
return -1;
}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
index 69bd02164b0..6cb31e1760a 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c
@@ -198,8 +198,8 @@ int ieee80211_encrypt_fragment(
header = (struct ieee80211_hdr_4addr *)frag->data;
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
- "TX packet to " MAC_FMT "\n",
- ieee->dev->name, MAC_ARG(header->addr1));
+ "TX packet to %pM\n",
+ ieee->dev->name, header->addr1);
}
return -1;
}
@@ -407,7 +407,7 @@ int ieee80211_rtl_xmit(struct sk_buff *skb,
memcpy(&header.addr2, src, ETH_ALEN);
memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN);
}
- // printk(KERN_WARNING "essid MAC address is "MAC_FMT, MAC_ARG(&header.addr1));
+ // printk(KERN_WARNING "essid MAC address is %pM", &header.addr1);
header.frame_ctl = cpu_to_le16(fc);
//hdr_len = IEEE80211_3ADDR_LEN;
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
index 6aad48fe2e1..bd5e77bf716 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
@@ -234,10 +234,10 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
else
IEEE80211_DEBUG_SCAN(
"Not showing network '%s ("
- MAC_FMT ")' due to age (%lums).\n",
+ "%pM)' due to age (%lums).\n",
escape_essid(network->ssid,
network->ssid_len),
- MAC_ARG(network->bssid),
+ network->bssid,
(jiffies - network->last_scanned) / (HZ / 100));
}
}
@@ -694,7 +694,7 @@ int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
#if 1
case IW_AUTH_WPA_ENABLED:
ieee->wpa_enabled = (data->value)?1:0;
- //printk("enalbe wpa:%d\n", ieee->wpa_enabled);
+ //printk("enable wpa:%d\n", ieee->wpa_enabled);
break;
#endif
diff --git a/drivers/staging/rtl8187se/r8180.h b/drivers/staging/rtl8187se/r8180.h
index ce828885b64..d15bdf64efd 100644
--- a/drivers/staging/rtl8187se/r8180.h
+++ b/drivers/staging/rtl8187se/r8180.h
@@ -366,7 +366,6 @@ typedef struct r8180_priv
short diversity;
u8 cs_treshold;
short rcr_csense;
- short rf_chip;
u32 key0[4];
short (*rf_set_sens)(struct net_device *dev,short sens);
void (*rf_set_chan)(struct net_device *dev,short ch);
@@ -479,9 +478,6 @@ typedef struct r8180_priv
u8 retry_rts;
u16 rts;
-//add for RF power on power off by lizhaoming 080512
- u8 RegThreeWireMode; // See "Three wire mode" defined above, 2006.05.31, by rcnjko.
-
//by amy for led
LED_STRATEGY_8185 LedStrategy;
//by amy for led
diff --git a/drivers/staging/rtl8187se/r8180_93cx6.c b/drivers/staging/rtl8187se/r8180_93cx6.c
deleted file mode 100644
index 7e4711fb930..00000000000
--- a/drivers/staging/rtl8187se/r8180_93cx6.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- This files contains card eeprom (93c46 or 93c56) programming routines,
- memory is addressed by 16 bits words.
-
- This is part of rtl8180 OpenSource driver.
- Copyright (C) Andrea Merello 2004 <andreamrl@tiscali.it>
- Released under the terms of GPL (General Public Licence)
-
- Parts of this driver are based on the GPL part of the
- official realtek driver.
-
- Parts of this driver are based on the rtl8180 driver skeleton
- from Patric Schenke & Andres Salomon.
-
- Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
-
- We want to tanks the Authors of those projects and the Ndiswrapper
- project Authors.
-*/
-
-#include "r8180_93cx6.h"
-
-void eprom_cs(struct net_device *dev, short bit)
-{
- if(bit)
- write_nic_byte(dev, EPROM_CMD,
- (1<<EPROM_CS_SHIFT) | \
- read_nic_byte(dev, EPROM_CMD)); //enable EPROM
- else
- write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev, EPROM_CMD)\
- &~(1<<EPROM_CS_SHIFT)); //disable EPROM
-
- force_pci_posting(dev);
- udelay(EPROM_DELAY);
-}
-
-
-void eprom_ck_cycle(struct net_device *dev)
-{
- write_nic_byte(dev, EPROM_CMD,
- (1<<EPROM_CK_SHIFT) | read_nic_byte(dev,EPROM_CMD));
- force_pci_posting(dev);
- udelay(EPROM_DELAY);
- write_nic_byte(dev, EPROM_CMD,
- read_nic_byte(dev, EPROM_CMD) &~ (1<<EPROM_CK_SHIFT));
- force_pci_posting(dev);
- udelay(EPROM_DELAY);
-}
-
-
-void eprom_w(struct net_device *dev,short bit)
-{
- if(bit)
- write_nic_byte(dev, EPROM_CMD, (1<<EPROM_W_SHIFT) | \
- read_nic_byte(dev,EPROM_CMD));
- else
- write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev,EPROM_CMD)\
- &~(1<<EPROM_W_SHIFT));
-
- force_pci_posting(dev);
- udelay(EPROM_DELAY);
-}
-
-
-short eprom_r(struct net_device *dev)
-{
- short bit;
-
- bit=(read_nic_byte(dev, EPROM_CMD) & (1<<EPROM_R_SHIFT) );
- udelay(EPROM_DELAY);
-
- if(bit) return 1;
- return 0;
-}
-
-
-void eprom_send_bits_string(struct net_device *dev, short b[], int len)
-{
- int i;
-
- for(i=0; i<len; i++){
- eprom_w(dev, b[i]);
- eprom_ck_cycle(dev);
- }
-}
-
-
-u32 eprom_read(struct net_device *dev, u32 addr)
-{
- struct r8180_priv *priv = ieee80211_priv(dev);
- short read_cmd[]={1,1,0};
- short addr_str[8];
- int i;
- int addr_len;
- u32 ret;
-
- ret=0;
- //enable EPROM programming
- write_nic_byte(dev, EPROM_CMD,
- (EPROM_CMD_PROGRAM<<EPROM_CMD_OPERATING_MODE_SHIFT));
- force_pci_posting(dev);
- udelay(EPROM_DELAY);
-
- if (priv->epromtype==EPROM_93c56){
- addr_str[7]=addr & 1;
- addr_str[6]=addr & (1<<1);
- addr_str[5]=addr & (1<<2);
- addr_str[4]=addr & (1<<3);
- addr_str[3]=addr & (1<<4);
- addr_str[2]=addr & (1<<5);
- addr_str[1]=addr & (1<<6);
- addr_str[0]=addr & (1<<7);
- addr_len=8;
- }else{
- addr_str[5]=addr & 1;
- addr_str[4]=addr & (1<<1);
- addr_str[3]=addr & (1<<2);
- addr_str[2]=addr & (1<<3);
- addr_str[1]=addr & (1<<4);
- addr_str[0]=addr & (1<<5);
- addr_len=6;
- }
- eprom_cs(dev, 1);
- eprom_ck_cycle(dev);
- eprom_send_bits_string(dev, read_cmd, 3);
- eprom_send_bits_string(dev, addr_str, addr_len);
-
- //keep chip pin D to low state while reading.
- //I'm unsure if it is necessary, but anyway shouldn't hurt
- eprom_w(dev, 0);
-
- for(i=0;i<16;i++){
- //eeprom needs a clk cycle between writing opcode&adr
- //and reading data. (eeprom outs a dummy 0)
- eprom_ck_cycle(dev);
- ret |= (eprom_r(dev)<<(15-i));
- }
-
- eprom_cs(dev, 0);
- eprom_ck_cycle(dev);
-
- //disable EPROM programming
- write_nic_byte(dev, EPROM_CMD,
- (EPROM_CMD_NORMAL<<EPROM_CMD_OPERATING_MODE_SHIFT));
- return ret;
-}
diff --git a/drivers/staging/rtl8187se/r8180_93cx6.h b/drivers/staging/rtl8187se/r8180_93cx6.h
index 36ae100f3f1..79e7391ac88 100644
--- a/drivers/staging/rtl8187se/r8180_93cx6.h
+++ b/drivers/staging/rtl8187se/r8180_93cx6.h
@@ -45,13 +45,10 @@
#define EPROM_TXPW_OFDM_CH1_2 0x20
-//#define EPROM_TXPW_CH1_2 0x10
-#define EPROM_TXPW_CH1_2 0x30
-#define EPROM_TXPW_CH3_4 0x11
-#define EPROM_TXPW_CH5_6 0x12
-#define EPROM_TXPW_CH7_8 0x13
-#define EPROM_TXPW_CH9_10 0x14
-#define EPROM_TXPW_CH11_12 0x15
-#define EPROM_TXPW_CH13_14 0x16
-
-u32 eprom_read(struct net_device *dev,u32 addr); //reads a 16 bits word
+#define EPROM_TXPW_CH1_2 0x30
+
+#define RTL818X_EEPROM_CMD_READ (1 << 0)
+#define RTL818X_EEPROM_CMD_WRITE (1 << 1)
+#define RTL818X_EEPROM_CMD_CK (1 << 2)
+#define RTL818X_EEPROM_CMD_CS (1 << 3)
+
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
index 1847f38b9f2..b1757acabed 100644
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ b/drivers/staging/rtl8187se/r8180_core.c
@@ -31,6 +31,7 @@
#undef DUMMY_RX
#include <linux/syscalls.h>
+#include <linux/eeprom_93cx6.h>
#include "r8180_hw.h"
#include "r8180.h"
@@ -41,13 +42,6 @@
#include "ieee80211/dot11d.h"
-#ifndef PCI_VENDOR_ID_BELKIN
- #define PCI_VENDOR_ID_BELKIN 0x1799
-#endif
-#ifndef PCI_VENDOR_ID_DLINK
- #define PCI_VENDOR_ID_DLINK 0x1186
-#endif
-
static struct pci_device_id rtl8180_pci_id_tbl[] __devinitdata = {
{
.vendor = PCI_VENDOR_ID_REALTEK,
@@ -669,11 +663,8 @@ unsigned char STRENGTH_MAP[] = {
void rtl8180_RSSI_calc(struct net_device *dev, u8 *rssi, u8 *qual)
{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
u32 temp;
u32 temp2;
- u32 temp3;
- u32 lsb;
u32 q;
u32 orig_qual;
u8 _rssi;
@@ -695,88 +686,6 @@ void rtl8180_RSSI_calc(struct net_device *dev, u8 *rssi, u8 *qual)
*qual = temp;
temp2 = *rssi;
- switch(priv->rf_chip){
- case RFCHIPID_RFMD:
- lsb = temp2 & 1;
- temp2 &= 0x7e;
- if ( !lsb || !(temp2 <= 0x3c) ) {
- temp2 = 0x64;
- } else {
- temp2 = 100 * temp2 / 0x3c;
- }
- *rssi = temp2 & 0xff;
- _rssi = temp2 & 0xff;
- break;
- case RFCHIPID_INTERSIL:
- lsb = temp2;
- temp2 &= 0xfffffffe;
- temp2 *= 251;
- temp3 = temp2;
- temp2 <<= 6;
- temp3 += temp2;
- temp3 <<= 1;
- temp2 = 0x4950df;
- temp2 -= temp3;
- lsb &= 1;
- if ( temp2 <= 0x3e0000 ) {
- if ( temp2 < 0xffef0000 )
- temp2 = 0xffef0000;
- } else {
- temp2 = 0x3e0000;
- }
- if ( !lsb ) {
- temp2 -= 0xf0000;
- } else {
- temp2 += 0xf0000;
- }
-
- temp3 = 0x4d0000;
- temp3 -= temp2;
- temp3 *= 100;
- temp3 = temp3 / 0x6d;
- temp3 >>= 0x10;
- _rssi = temp3 & 0xff;
- *rssi = temp3 & 0xff;
- break;
- case RFCHIPID_GCT:
- lsb = temp2 & 1;
- temp2 &= 0x7e;
- if ( ! lsb || !(temp2 <= 0x3c) ){
- temp2 = 0x64;
- } else {
- temp2 = (100 * temp2) / 0x3c;
- }
- *rssi = temp2 & 0xff;
- _rssi = temp2 & 0xff;
- break;
- case RFCHIPID_PHILIPS:
- if( orig_qual <= 0x4e ){
- _rssi = STRENGTH_MAP[orig_qual];
- *rssi = _rssi;
- } else {
- orig_qual -= 0x80;
- if ( !orig_qual ){
- _rssi = 1;
- *rssi = 1;
- } else {
- _rssi = 0x32;
- *rssi = 0x32;
- }
- }
- break;
- case RFCHIPID_MAXIM:
- lsb = temp2 & 1;
- temp2 &= 0x7e;
- temp2 >>= 1;
- temp2 += 0x42;
- if( lsb != 0 ){
- temp2 += 0xa;
- }
- *rssi = temp2 & 0xff;
- _rssi = temp2 & 0xff;
- break;
- }
-
if ( _rssi < 0x64 ){
if ( _rssi == 0 ) {
*rssi = 1;
@@ -1421,11 +1330,9 @@ u16 N_DBPSOfRate(u16 DataRate)
return N_DBPS;
}
-//{by amy 080312
//
// Description:
// For Netgear case, they want good-looking singal strength.
-// 2004.12.05, by rcnjko.
//
long NetgearSignalStrengthTranslate(long LastSS, long CurrSS)
{
@@ -1481,7 +1388,6 @@ long TranslateToDbm8185(u8 SignalStrengthIndex)
// This is different with PerformSignalSmoothing8185 in smoothing fomula.
// No dramatic adjustion is apply because dynamic mechanism need some degree
// of correctness. Ported from 8187B.
-// 2007-02-26, by Bruce.
//
void PerformUndecoratedSignalSmoothing8185(struct r8180_priv *priv,
bool bCckRate)
@@ -1502,7 +1408,6 @@ void PerformUndecoratedSignalSmoothing8185(struct r8180_priv *priv,
priv->CurCCKRSSI = 0;
}
-//by amy 080312}
/* This is rough RX isr handling routine*/
void rtl8180_rx(struct net_device *dev)
@@ -1638,7 +1543,7 @@ void rtl8180_rx(struct net_device *dev)
}
signal=(unsigned char)(((*(priv->rxringtail+3))& (0x00ff0000))>>16);
- signal=(signal&0xfe)>>1; // Modify by hikaru 6.6
+ signal = (signal & 0xfe) >> 1;
quality=(unsigned char)((*(priv->rxringtail+3)) & (0xff));
@@ -1652,7 +1557,6 @@ void rtl8180_rx(struct net_device *dev)
stats.rate = rtl8180_rate2rate(rate);
Antenna = (((*(priv->rxringtail +3))& (0x00008000)) == 0 )? 0:1 ;
-//by amy for antenna
if(!rtl8180_IsWirelessBMode(stats.rate))
{ // OFDM rate.
@@ -1691,11 +1595,10 @@ void rtl8180_rx(struct net_device *dev)
RXAGC=(95-RXAGC)*100/65;
}
priv->SignalStrength = (u8)RXAGC;
- priv->RecvSignalPower = RxAGC_dBm ; // It can use directly by SD3 CMLin
+ priv->RecvSignalPower = RxAGC_dBm;
priv->RxPower = rxpower;
priv->RSSI = RSSI;
-//{by amy 080312
- // SQ translation formular is provided by SD3 DZ. 2006.06.27, by rcnjko.
+ /* SQ translation formula is provided by SD3 DZ. 2006.06.27 */
if(quality >= 127)
quality = 1;//0; //0 will cause epc to show signal zero , walk aroud now;
else if(quality < 27)
@@ -1712,7 +1615,6 @@ void rtl8180_rx(struct net_device *dev)
// printk("==========================>rx : RXAGC is %d,signalstrength is %d\n",RXAGC,stats.signalstrength);
stats.rssi = priv->wstats.qual.qual = priv->SignalQuality;
stats.noise = priv->wstats.qual.noise = 100 - priv ->wstats.qual.qual;
-//by amy 080312}
bHwError = (((*(priv->rxringtail))& (0x00000fff)) == 4080)| (((*(priv->rxringtail))& (0x04000000)) != 0 )
| (((*(priv->rxringtail))& (0x08000000)) != 0 )| (((~(*(priv->rxringtail)))& (0x10000000)) != 0 )| (((~(*(priv->rxringtail)))& (0x20000000)) != 0 );
bCRC = ((*(priv->rxringtail)) & (0x00002000)) >> 13;
@@ -1725,11 +1627,12 @@ void rtl8180_rx(struct net_device *dev)
(eqMacAddr(priv->ieee80211->current_network.bssid, (fc & IEEE80211_FCTL_TODS)? hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS )? hdr->addr2 : hdr->addr3))
&& (!bHwError) && (!bCRC)&& (!bICV))
{
-//by amy 080312
- // Perform signal smoothing for dynamic mechanism on demand.
- // This is different with PerformSignalSmoothing8185 in smoothing fomula.
- // No dramatic adjustion is apply because dynamic mechanism need some degree
- // of correctness. 2007.01.23, by shien chang.
+ /* Perform signal smoothing for dynamic
+ * mechanism on demand. This is different
+ * with PerformSignalSmoothing8185 in smoothing
+ * fomula. No dramatic adjustion is apply
+ * because dynamic mechanism need some degree
+ * of correctness. */
PerformUndecoratedSignalSmoothing8185(priv,bCckRate);
//
// For good-looking singal strength.
@@ -1749,12 +1652,9 @@ void rtl8180_rx(struct net_device *dev)
// Figure out which antenna that received the lasted packet.
priv->LastRxPktAntenna = Antenna ? 1 : 0; // 0: aux, 1: main.
-//by amy 080312
SwAntennaDiversityRxOk8185(dev, priv->SignalStrength);
}
-//by amy for antenna
-#ifndef DUMMY_RX
if(first){
if(!priv->rx_skb_complete){
/* seems that HW sometimes fails to reiceve and
@@ -1810,19 +1710,12 @@ void rtl8180_rx(struct net_device *dev)
if(last && !priv->rx_skb_complete){
if(priv->rx_skb->len > 4)
skb_trim(priv->rx_skb,priv->rx_skb->len-4);
-#ifndef RX_DONT_PASS_UL
if(!ieee80211_rtl_rx(priv->ieee80211,
- priv->rx_skb, &stats)){
-#endif // RX_DONT_PASS_UL
-
+ priv->rx_skb, &stats))
dev_kfree_skb_any(priv->rx_skb);
-#ifndef RX_DONT_PASS_UL
- }
-#endif
priv->rx_skb_complete=1;
}
-#endif //DUMMY_RX
pci_dma_sync_single_for_device(priv->pdev,
priv->rxbuffer->dma,
priv->rxbuffersize * \
@@ -2056,7 +1949,7 @@ short rtl8180_tx(struct net_device *dev, u8* txbuf, int len, int priority,
u16 RtsDur = 0;
u16 ThisFrameTime = 0;
u16 TxDescDuration = 0;
- u8 ownbit_flag = false; //added by david woo for sync Tx, 2007.12.14
+ u8 ownbit_flag = false;
switch(priority) {
case MANAGE_PRIORITY:
@@ -2123,7 +2016,8 @@ short rtl8180_tx(struct net_device *dev, u8* txbuf, int len, int priority,
//YJ,add,080828,for Keep alive
priv->NumTxUnicast++;
- // Figure out ACK rate according to BSS basic rate and Tx rate, 2006.03.08 by rcnjko.
+ /* Figure out ACK rate according to BSS basic rate
+ * and Tx rate. */
AckTime = ComputeTxTime(14, 10,0, 0); // AckCTSLng = 14 use 1M bps send
if ( ((len + sCrcLng) > priv->rts) && priv->rts )
@@ -2206,7 +2100,7 @@ short rtl8180_tx(struct net_device *dev, u8* txbuf, int len, int priority,
*tail |= (1<<15); /* no encrypt */
if(remain==len && !descfrag) {
- ownbit_flag = false; //added by david woo,2007.12.14
+ ownbit_flag = false;
*tail = *tail| (1<<29) ; //fist segment of the packet
*tail = *tail |(len);
} else {
@@ -2556,27 +2450,16 @@ void watch_dog_adaptive(unsigned long data)
}
// Tx High Power Mechanism.
-#ifdef HIGH_POWER
if(CheckHighPower((struct net_device *)data))
- {
queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->tx_pw_wq);
- }
-#endif
// Tx Power Tracking on 87SE.
-#ifdef TX_TRACK
- //if( priv->bTxPowerTrack ) //lzm mod 080826
- if( CheckTxPwrTracking((struct net_device *)data));
+ if (CheckTxPwrTracking((struct net_device *)data))
TxPwrTracking87SE((struct net_device *)data);
-#endif
// Perform DIG immediately.
-#ifdef SW_DIG
if(CheckDig((struct net_device *)data) == true)
- {
queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->hw_dig_wq);
- }
-#endif
rtl8180_watch_dog((struct net_device *)data);
queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->GPIOChangeRFWorkItem);
@@ -2675,6 +2558,36 @@ static void rtl8180_link_detect_init(plink_detect_t plink_detect)
}
//YJ,add,080828,end
+static void rtl8187se_eeprom_register_read(struct eeprom_93cx6 *eeprom)
+{
+ struct net_device *dev = eeprom->data;
+ u8 reg = read_nic_byte(dev, EPROM_CMD);
+
+ eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE;
+ eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ;
+ eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK;
+ eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS;
+}
+
+static void rtl8187se_eeprom_register_write(struct eeprom_93cx6 *eeprom)
+{
+ struct net_device *dev = eeprom->data;
+ u8 reg = 2 << 6;
+
+ if (eeprom->reg_data_in)
+ reg |= RTL818X_EEPROM_CMD_WRITE;
+ if (eeprom->reg_data_out)
+ reg |= RTL818X_EEPROM_CMD_READ;
+ if (eeprom->reg_data_clock)
+ reg |= RTL818X_EEPROM_CMD_CK;
+ if (eeprom->reg_chip_select)
+ reg |= RTL818X_EEPROM_CMD_CS;
+
+ write_nic_byte(dev, EPROM_CMD, reg);
+ read_nic_byte(dev, EPROM_CMD);
+ udelay(10);
+}
+
short rtl8180_init(struct net_device *dev)
{
struct r8180_priv *priv = ieee80211_priv(dev);
@@ -2683,8 +2596,16 @@ short rtl8180_init(struct net_device *dev)
u32 usValue;
u16 tmpu16;
int i, j;
+ struct eeprom_93cx6 eeprom;
+ u16 eeprom_val;
+
+ eeprom.data = dev;
+ eeprom.register_read = rtl8187se_eeprom_register_read;
+ eeprom.register_write = rtl8187se_eeprom_register_write;
+ eeprom.width = PCI_EEPROM_WIDTH_93C46;
- priv->channel_plan = eprom_read(dev, EEPROM_COUNTRY_CODE>>1) & 0xFF;
+ eeprom_93cx6_read(&eeprom, EEPROM_COUNTRY_CODE>>1, &eeprom_val);
+ priv->channel_plan = eeprom_val & 0xFF;
if(priv->channel_plan > COUNTRY_CODE_GLOBAL_DOMAIN){
printk("rtl8180_init:Error channel plan! Set to default.\n");
priv->channel_plan = 0;
@@ -2701,8 +2622,6 @@ short rtl8180_init(struct net_device *dev)
priv->txbeaconcount = 2;
priv->rx_skb_complete = 1;
- priv->RegThreeWireMode = HW_THREE_WIRE_SI;
-
priv->RFChangeInProgress = false;
priv->SetRFPowerStateInProgress = false;
priv->RFProgType = 0;
@@ -2747,10 +2666,8 @@ short rtl8180_init(struct net_device *dev)
priv->TxPollingTimes = 0;//lzm add 080826
priv->bLeisurePs = true;
priv->dot11PowerSaveMode = eActive;
-//by amy for antenna
priv->AdMinCheckPeriod = 5;
priv->AdMaxCheckPeriod = 10;
-// Lower signal strength threshold to fit the HW participation in antenna diversity. +by amy 080312
priv->AdMaxRxSsThreshold = 30;//60->30
priv->AdRxSsThreshold = 20;//50->20
priv->AdCheckPeriod = priv->AdMinCheckPeriod;
@@ -2765,8 +2682,6 @@ short rtl8180_init(struct net_device *dev)
init_timer(&priv->SwAntennaDiversityTimer);
priv->SwAntennaDiversityTimer.data = (unsigned long)dev;
priv->SwAntennaDiversityTimer.function = (void *)SwAntennaDiversityTimerCallback;
-//by amy for antenna
-//{by amy 080312
priv->bDigMechanism = 1;
priv->InitialGain = 6;
priv->bXtalCalibration = false;
@@ -2803,58 +2718,63 @@ short rtl8180_init(struct net_device *dev)
priv->NumTxUnicast = 0;
priv->keepAliveLevel = DEFAULT_KEEP_ALIVE_LEVEL;
priv->PowerProfile = POWER_PROFILE_AC;
- priv->CurrRetryCnt=0;
- priv->LastRetryCnt=0;
- priv->LastTxokCnt=0;
- priv->LastRxokCnt=0;
- priv->LastRetryRate=0;
- priv->bTryuping=0;
- priv->CurrTxRate=0;
- priv->CurrRetryRate=0;
- priv->TryupingCount=0;
- priv->TryupingCountNoData=0;
- priv->TryDownCountLowData=0;
- priv->LastTxOKBytes=0;
- priv->LastFailTxRate=0;
- priv->LastFailTxRateSS=0;
- priv->FailTxRateCount=0;
- priv->LastTxThroughput=0;
- priv->NumTxOkBytesTotal=0;
+ priv->CurrRetryCnt = 0;
+ priv->LastRetryCnt = 0;
+ priv->LastTxokCnt = 0;
+ priv->LastRxokCnt = 0;
+ priv->LastRetryRate = 0;
+ priv->bTryuping = 0;
+ priv->CurrTxRate = 0;
+ priv->CurrRetryRate = 0;
+ priv->TryupingCount = 0;
+ priv->TryupingCountNoData = 0;
+ priv->TryDownCountLowData = 0;
+ priv->LastTxOKBytes = 0;
+ priv->LastFailTxRate = 0;
+ priv->LastFailTxRateSS = 0;
+ priv->FailTxRateCount = 0;
+ priv->LastTxThroughput = 0;
+ priv->NumTxOkBytesTotal = 0;
priv->ForcedDataRate = 0;
priv->RegBModeGainStage = 1;
- priv->promisc = (dev->flags & IFF_PROMISC) ? 1:0;
+ priv->promisc = (dev->flags & IFF_PROMISC) ? 1 : 0;
spin_lock_init(&priv->irq_lock);
spin_lock_init(&priv->irq_th_lock);
spin_lock_init(&priv->tx_lock);
spin_lock_init(&priv->ps_lock);
spin_lock_init(&priv->rf_ps_lock);
- sema_init(&priv->wx_sem,1);
- sema_init(&priv->rf_state,1);
- INIT_WORK(&priv->reset_wq,(void*) rtl8180_restart_wq);
- INIT_WORK(&priv->tx_irq_wq,(void*) rtl8180_tx_irq_wq);
- INIT_DELAYED_WORK(&priv->ieee80211->hw_wakeup_wq,(void*) rtl8180_hw_wakeup_wq);
- INIT_DELAYED_WORK(&priv->ieee80211->hw_sleep_wq,(void*) rtl8180_hw_sleep_wq);
- INIT_WORK(&priv->ieee80211->wmm_param_update_wq,(void*) rtl8180_wmm_param_update);
- INIT_DELAYED_WORK(&priv->ieee80211->rate_adapter_wq,(void*)rtl8180_rate_adapter);//+by amy 080312
- INIT_DELAYED_WORK(&priv->ieee80211->hw_dig_wq,(void*)rtl8180_hw_dig_wq);//+by amy 080312
- INIT_DELAYED_WORK(&priv->ieee80211->tx_pw_wq,(void*)rtl8180_tx_pw_wq);//+by amy 080312
-
- INIT_DELAYED_WORK(&priv->ieee80211->GPIOChangeRFWorkItem,(void*) GPIOChangeRFWorkItemCallBack);
-
+ sema_init(&priv->wx_sem, 1);
+ sema_init(&priv->rf_state, 1);
+ INIT_WORK(&priv->reset_wq, (void *)rtl8180_restart_wq);
+ INIT_WORK(&priv->tx_irq_wq, (void *)rtl8180_tx_irq_wq);
+ INIT_DELAYED_WORK(&priv->ieee80211->hw_wakeup_wq,
+ (void *)rtl8180_hw_wakeup_wq);
+ INIT_DELAYED_WORK(&priv->ieee80211->hw_sleep_wq,
+ (void *)rtl8180_hw_sleep_wq);
+ INIT_WORK(&priv->ieee80211->wmm_param_update_wq,
+ (void *)rtl8180_wmm_param_update);
+ INIT_DELAYED_WORK(&priv->ieee80211->rate_adapter_wq,
+ (void *)rtl8180_rate_adapter);
+ INIT_DELAYED_WORK(&priv->ieee80211->hw_dig_wq,
+ (void *)rtl8180_hw_dig_wq);
+ INIT_DELAYED_WORK(&priv->ieee80211->tx_pw_wq,
+ (void *)rtl8180_tx_pw_wq);
+ INIT_DELAYED_WORK(&priv->ieee80211->GPIOChangeRFWorkItem,
+ (void *) GPIOChangeRFWorkItemCallBack);
tasklet_init(&priv->irq_rx_tasklet,
(void(*)(unsigned long)) rtl8180_irq_rx_tasklet,
(unsigned long)priv);
- init_timer(&priv->watch_dog_timer);
+ init_timer(&priv->watch_dog_timer);
priv->watch_dog_timer.data = (unsigned long)dev;
priv->watch_dog_timer.function = watch_dog_adaptive;
- init_timer(&priv->rateadapter_timer);
- priv->rateadapter_timer.data = (unsigned long)dev;
- priv->rateadapter_timer.function = timer_rate_adaptive;
- priv->RateAdaptivePeriod= RATE_ADAPTIVE_TIMER_PERIOD;
- priv->bEnhanceTxPwr=false;
+ init_timer(&priv->rateadapter_timer);
+ priv->rateadapter_timer.data = (unsigned long)dev;
+ priv->rateadapter_timer.function = timer_rate_adaptive;
+ priv->RateAdaptivePeriod = RATE_ADAPTIVE_TIMER_PERIOD;
+ priv->bEnhanceTxPwr = false;
priv->ieee80211->softmac_hard_start_xmit = rtl8180_hard_start_xmit;
priv->ieee80211->set_chan = rtl8180_set_chan;
@@ -2877,30 +2797,28 @@ short rtl8180_init(struct net_device *dev)
priv->CSMethod = (0x01 << 29);
- priv->TransmitConfig =
- 1<<TCR_DurProcMode_OFFSET | //for RTL8185B, duration setting by HW
- (7<<TCR_MXDMA_OFFSET) | // Max DMA Burst Size per Tx DMA Burst, 7: reservied.
- (priv->ShortRetryLimit<<TCR_SRL_OFFSET) | // Short retry limit
- (priv->LongRetryLimit<<TCR_LRL_OFFSET) | // Long retry limit
- (0 ? TCR_SAT : 0); // FALSE: HW provies PLCP length and LENGEXT, TURE: SW proiveds them
-
- priv->ReceiveConfig =
- RCR_AMF | RCR_ADF | //accept management/data
- RCR_ACF | //accept control frame for SW AP needs PS-poll, 2005.07.07, by rcnjko.
- RCR_AB | RCR_AM | RCR_APM | //accept BC/MC/UC
- (7<<RCR_MXDMA_OFFSET) | // Max DMA Burst Size per Rx DMA Burst, 7: unlimited.
- (priv->EarlyRxThreshold<<RCR_FIFO_OFFSET) | // Rx FIFO Threshold, 7: No Rx threshold.
- (priv->EarlyRxThreshold == 7 ? RCR_ONLYERLPKT:0);
+ priv->TransmitConfig = TCR_DurProcMode_OFFSET |
+ (7<<TCR_MXDMA_OFFSET) |
+ (priv->ShortRetryLimit<<TCR_SRL_OFFSET) |
+ (priv->LongRetryLimit<<TCR_LRL_OFFSET) |
+ (0 ? TCR_SAT : 0);
+
+ priv->ReceiveConfig = RCR_AMF | RCR_ADF | RCR_ACF |
+ RCR_AB | RCR_AM | RCR_APM |
+ (7<<RCR_MXDMA_OFFSET) |
+ (priv->EarlyRxThreshold<<RCR_FIFO_OFFSET) |
+ (priv->EarlyRxThreshold == 7 ?
+ RCR_ONLYERLPKT : 0);
priv->IntrMask = IMR_TMGDOK | IMR_TBDER | IMR_THPDER |
- IMR_THPDER | IMR_THPDOK |
- IMR_TVODER | IMR_TVODOK |
- IMR_TVIDER | IMR_TVIDOK |
- IMR_TBEDER | IMR_TBEDOK |
- IMR_TBKDER | IMR_TBKDOK |
- IMR_RDU | // To handle the defragmentation not enough Rx descriptors case. Annie, 2006-03-27.
- IMR_RER | IMR_ROK |
- IMR_RQoSOK; // <NOTE> ROK and RQoSOK are mutually exclusive, so, we must handle RQoSOK interrupt to receive QoS frames, 2005.12.09, by rcnjko.
+ IMR_THPDER | IMR_THPDOK |
+ IMR_TVODER | IMR_TVODOK |
+ IMR_TVIDER | IMR_TVIDOK |
+ IMR_TBEDER | IMR_TBEDOK |
+ IMR_TBKDER | IMR_TBKDOK |
+ IMR_RDU |
+ IMR_RER | IMR_ROK |
+ IMR_RQoSOK;
priv->InitialGain = 6;
@@ -2913,7 +2831,8 @@ short rtl8180_init(struct net_device *dev)
// just for sync 85
priv->enable_gpio0 = 0;
- usValue = eprom_read(dev, EEPROM_SW_REVD_OFFSET);
+ eeprom_93cx6_read(&eeprom, EEPROM_SW_REVD_OFFSET, &eeprom_val);
+ usValue = eeprom_val;
DMESG("usValue is 0x%x\n",usValue);
//3Read AntennaDiversity
@@ -2953,54 +2872,46 @@ short rtl8180_init(struct net_device *dev)
else
priv->epromtype=EPROM_93c46;
- dev->dev_addr[0]=eprom_read(dev,MAC_ADR) & 0xff;
- dev->dev_addr[1]=(eprom_read(dev,MAC_ADR) & 0xff00)>>8;
- dev->dev_addr[2]=eprom_read(dev,MAC_ADR+1) & 0xff;
- dev->dev_addr[3]=(eprom_read(dev,MAC_ADR+1) & 0xff00)>>8;
- dev->dev_addr[4]=eprom_read(dev,MAC_ADR+2) & 0xff;
- dev->dev_addr[5]=(eprom_read(dev,MAC_ADR+2) & 0xff00)>>8;
+ eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *)
+ dev->dev_addr, 3);
for(i=1,j=0; i<14; i+=2,j++){
- word = eprom_read(dev,EPROM_TXPW_CH1_2 + j);
+ eeprom_93cx6_read(&eeprom, EPROM_TXPW_CH1_2 + j, &word);
priv->chtxpwr[i]=word & 0xff;
priv->chtxpwr[i+1]=(word & 0xff00)>>8;
}
for (i = 1, j = 0; i < 14; i += 2, j++) {
- word = eprom_read(dev, EPROM_TXPW_OFDM_CH1_2 + j);
+ eeprom_93cx6_read(&eeprom, EPROM_TXPW_OFDM_CH1_2 + j, &word);
priv->chtxpwr_ofdm[i] = word & 0xff;
- priv->chtxpwr_ofdm[i+1] = (word & 0xff00)>>8;
+ priv->chtxpwr_ofdm[i+1] = (word & 0xff00) >> 8;
}
- //3Read crystal calibtration and thermal meter indication on 87SE.
-
- // By SD3 SY's request. Added by Roger, 2007.12.11.
+ /* 3Read crystal calibtration and thermal meter indication on 87SE. */
+ eeprom_93cx6_read(&eeprom, EEPROM_RSV>>1, &tmpu16);
- tmpu16 = eprom_read(dev, EEPROM_RSV>>1);
+ /* Crystal calibration for Xin and Xout resp. */
+ priv->XtalCal_Xout = tmpu16 & EEPROM_XTAL_CAL_XOUT_MASK;
+ priv->XtalCal_Xin = (tmpu16 & EEPROM_XTAL_CAL_XIN_MASK) >> 4;
+ if ((tmpu16 & EEPROM_XTAL_CAL_ENABLE) >> 12)
+ priv->bXtalCalibration = true;
- // Crystal calibration for Xin and Xout resp.
- priv->XtalCal_Xout = tmpu16 & EEPROM_XTAL_CAL_XOUT_MASK; // 0~7.5pF
- priv->XtalCal_Xin = (tmpu16 & EEPROM_XTAL_CAL_XIN_MASK)>>4; // 0~7.5pF
- if((tmpu16 & EEPROM_XTAL_CAL_ENABLE)>>12)
- priv->bXtalCalibration = true;
+ /* Thermal meter reference indication. */
+ priv->ThermalMeter = (u8)((tmpu16 & EEPROM_THERMAL_METER_MASK) >> 8);
+ if ((tmpu16 & EEPROM_THERMAL_METER_ENABLE) >> 13)
+ priv->bTxPowerTrack = true;
- // Thermal meter reference indication.
- priv->ThermalMeter = (u8)((tmpu16 & EEPROM_THERMAL_METER_MASK)>>8);
- if((tmpu16 & EEPROM_THERMAL_METER_ENABLE)>>13)
- priv->bTxPowerTrack = true;
-
- word = eprom_read(dev,EPROM_TXPW_BASE);
+ eeprom_93cx6_read(&eeprom, EPROM_TXPW_BASE, &word);
priv->cck_txpwr_base = word & 0xf;
priv->ofdm_txpwr_base = (word>>4) & 0xf;
- version = eprom_read(dev,EPROM_VERSION);
+ eeprom_93cx6_read(&eeprom, EPROM_VERSION, &version);
DMESG("EEPROM version %x",version);
priv->rcr_csense = 3;
- priv->cs_treshold = (eprom_read(dev, ENERGY_TRESHOLD) & 0xff00) >> 8;
-
- priv->rf_chip = 0xff & eprom_read(dev, RFCHIPID);
+ eeprom_93cx6_read(&eeprom, ENERGY_TRESHOLD, &eeprom_val);
+ priv->cs_treshold = (eeprom_val & 0xff00) >> 8;
- priv->rf_chip = RF_ZEBRA4;
+ eeprom_93cx6_read(&eeprom, RFCHIPID, &eeprom_val);
priv->rf_sleep = rtl8225z4_rf_sleep;
priv->rf_wakeup = rtl8225z4_rf_wakeup;
DMESGW("**PLEASE** REPORT SUCCESSFUL/UNSUCCESSFUL TO Realtek!");
@@ -3010,7 +2921,6 @@ short rtl8180_init(struct net_device *dev)
priv->rf_set_chan = rtl8225z2_rf_set_chan;
priv->rf_set_sens = NULL;
-
if (0!=alloc_rx_desc_ring(dev, priv->rxbuffersize, priv->rxringcount))
return -ENOMEM;
@@ -3042,11 +2952,7 @@ short rtl8180_init(struct net_device *dev)
TX_BEACON_RING_ADDR))
return -ENOMEM;
-#if !defined(SA_SHIRQ)
if(request_irq(dev->irq, (void *)rtl8180_interrupt, IRQF_SHARED, dev->name, dev)){
-#else
- if(request_irq(dev->irq, (void *)rtl8180_interrupt, SA_SHIRQ, dev->name, dev)){
-#endif
DMESGE("Error allocating IRQ %d",dev->irq);
return -1;
}else{
@@ -3169,43 +3075,6 @@ void write_phy_cck (struct net_device *dev, u8 adr, u32 data)
rtl8185_write_phy(dev, adr, data | 0x10000);
}
-/* 70*3 = 210 ms
- * I hope this is enougth
- */
-#define MAX_PHY 70
-void write_phy(struct net_device *dev, u8 adr, u8 data)
-{
- u32 phy;
- int i;
-
- phy = 0xff0000;
- phy |= adr;
- phy |= 0x80; /* this should enable writing */
- phy |= (data<<8);
-
- //PHY_ADR, PHY_R and PHY_W are contig and treated as one dword
- write_nic_dword(dev,PHY_ADR, phy);
-
- phy= 0xffff00;
- phy |= adr;
-
- write_nic_dword(dev,PHY_ADR, phy);
- for(i=0;i<MAX_PHY;i++){
- phy=read_nic_dword(dev,PHY_ADR);
- phy= phy & 0xff0000;
- phy= phy >> 16;
- if(phy == data){ //SUCCESS!
- force_pci_posting(dev);
- mdelay(3); //random value
- return;
- }else{
- force_pci_posting(dev);
- mdelay(3); //random value
- }
- }
- DMESGW ("Phy writing %x %x failed!", adr,data);
-}
-
void rtl8185_set_rate(struct net_device *dev)
{
int i;
@@ -3335,7 +3204,6 @@ static struct net_device_stats *rtl8180_stats(struct net_device *dev)
}
//
// Change current and default preamble mode.
-// 2005.01.06, by rcnjko.
//
bool
MgntActSet_802_11_PowerSaveMode(
@@ -3454,7 +3322,6 @@ void rtl8180_watch_dog(struct net_device *dev)
MgntLinkKeepAlive(priv);
//YJ,add,080828,for LPS
-#ifdef ENABLE_LPS
if (priv->PowerProfile == POWER_PROFILE_BATTERY)
priv->bLeisurePs = true;
else if (priv->PowerProfile == POWER_PROFILE_AC) {
@@ -3464,7 +3331,6 @@ void rtl8180_watch_dog(struct net_device *dev)
if(priv->ieee80211->state == IEEE80211_LINKED){
priv->link_detect.NumRxOkInPeriod = priv->ieee80211->NumRxDataInPeriod;
- //printk("TxOk=%d RxOk=%d\n", priv->link_detect.NumTxOkInPeriod, priv->link_detect.NumRxOkInPeriod);
if( priv->link_detect.NumRxOkInPeriod> 666 ||
priv->link_detect.NumTxOkInPeriod> 666 ) {
bBusyTraffic = true;
@@ -3481,7 +3347,6 @@ void rtl8180_watch_dog(struct net_device *dev)
LeisurePSLeave(priv);
} else
LeisurePSLeave(priv);
-#endif
priv->link_detect.bBusyTraffic = bBusyTraffic;
priv->link_detect.NumRxOkInPeriod = 0;
priv->link_detect.NumTxOkInPeriod = 0;
@@ -3503,16 +3368,11 @@ int _rtl8180_up(struct net_device *dev)
if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
IPSLeave(dev);
}
-#ifdef RATE_ADAPT
timer_rate_adaptive((unsigned long)dev);
-#endif
watch_dog_adaptive((unsigned long)dev);
-#ifdef SW_ANTE
if(priv->bSwAntennaDiverity)
SwAntennaDiversityTimerCallback(dev);
-#endif
ieee80211_softmac_start_protocol(priv->ieee80211);
-
return 0;
}
@@ -3748,7 +3608,7 @@ static int __devinit rtl8180_pci_probe(struct pci_dev *pdev,
dev->wireless_handlers = &r8180_wx_handlers_def;
dev->type=ARPHRD_ETHER;
- dev->watchdog_timeo = HZ*3; //added by david woo, 2007.12.13
+ dev->watchdog_timeo = HZ*3;
if (dev_alloc_name(dev, ifname) < 0){
DMESG("Oops: devname already taken! Trying wlan%%d...\n");
@@ -3864,8 +3724,7 @@ static int __init rtl8180_pci_module_init(void)
return ret;
}
- printk(KERN_INFO "\nLinux kernel driver for RTL8180 \
-/ RTL8185 based WLAN cards\n");
+ printk(KERN_INFO "\nLinux kernel driver for RTL8180 / RTL8185 based WLAN cards\n");
printk(KERN_INFO "Copyright (c) 2004-2005, Andrea Merello\n");
DMESG("Initializing module");
DMESG("Wireless extensions version %d", WIRELESS_EXT);
@@ -4236,60 +4095,51 @@ void GPIOChangeRFWorkItemCallBack(struct work_struct *work)
static char *envp[] = {"HOME=/", "TERM=linux", "PATH=/usr/bin:/bin", NULL};
static int readf_count = 0;
-#ifdef ENABLE_LPS
if(readf_count % 10 == 0)
priv->PowerProfile = read_acadapter_file("/proc/acpi/ac_adapter/AC0/state");
readf_count = (readf_count+1)%0xffff;
-#endif
- {
- // We should turn off LED before polling FF51[4].
+ /* We should turn off LED before polling FF51[4]. */
- //Turn off LED.
- btPSR = read_nic_byte(dev, PSR);
- write_nic_byte(dev, PSR, (btPSR & ~BIT3));
+ /* Turn off LED. */
+ btPSR = read_nic_byte(dev, PSR);
+ write_nic_byte(dev, PSR, (btPSR & ~BIT3));
- //It need to delay 4us suggested by Jong, 2008-01-16
- udelay(4);
+ /* It need to delay 4us suggested by Jong, 2008-01-16 */
+ udelay(4);
- //HW radio On/Off according to the value of FF51[4](config0)
- btConfig0 = btPSR = read_nic_byte(dev, CONFIG0);
+ /* HW radio On/Off according to the value of FF51[4](config0) */
+ btConfig0 = btPSR = read_nic_byte(dev, CONFIG0);
- //Turn on LED.
- write_nic_byte(dev, PSR, btPSR| BIT3);
+ eRfPowerStateToSet = (btConfig0 & BIT4) ? eRfOn : eRfOff;
- eRfPowerStateToSet = (btConfig0 & BIT4) ? eRfOn : eRfOff;
+ /* Turn LED back on when radio enabled */
+ if (eRfPowerStateToSet == eRfOn)
+ write_nic_byte(dev, PSR, btPSR | BIT3);
- if((priv->ieee80211->bHwRadioOff == true) && (eRfPowerStateToSet == eRfOn))
- {
- priv->ieee80211->bHwRadioOff = false;
- bActuallySet = true;
- }
- else if((priv->ieee80211->bHwRadioOff == false) && (eRfPowerStateToSet == eRfOff))
- {
- priv->ieee80211->bHwRadioOff = true;
- bActuallySet = true;
- }
+ if ((priv->ieee80211->bHwRadioOff == true) &&
+ (eRfPowerStateToSet == eRfOn)) {
+ priv->ieee80211->bHwRadioOff = false;
+ bActuallySet = true;
+ } else if ((priv->ieee80211->bHwRadioOff == false) &&
+ (eRfPowerStateToSet == eRfOff)) {
+ priv->ieee80211->bHwRadioOff = true;
+ bActuallySet = true;
+ }
- if(bActuallySet)
- {
- MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW);
-
- /* To update the UI status for Power status changed */
- if(priv->ieee80211->bHwRadioOff == true)
- argv[1] = "RFOFF";
- else{
- //if(!priv->RfOffReason)
- argv[1] = "RFON";
- //else
- // argv[1] = "RFOFF";
- }
- argv[0] = RadioPowerPath;
- argv[2] = NULL;
-
- call_usermodehelper(RadioPowerPath,argv,envp,1);
- }
- }
+ if (bActuallySet) {
+ MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW);
+
+ /* To update the UI status for Power status changed */
+ if (priv->ieee80211->bHwRadioOff == true)
+ argv[1] = "RFOFF";
+ else
+ argv[1] = "RFON";
+ argv[0] = RadioPowerPath;
+ argv[2] = NULL;
+
+ call_usermodehelper(RadioPowerPath, argv, envp, 1);
+ }
}
static u8 read_acadapter_file(char *filename)
diff --git a/drivers/staging/rtl8187se/r8180_dm.c b/drivers/staging/rtl8187se/r8180_dm.c
index cbca58db85e..fc4907839c5 100644
--- a/drivers/staging/rtl8187se/r8180_dm.c
+++ b/drivers/staging/rtl8187se/r8180_dm.c
@@ -282,30 +282,13 @@ DIG_Zebra(
// Dispatch DIG implementation according to RF.
//
void
-DynamicInitGain(
- struct net_device *dev
- )
+DynamicInitGain(struct net_device *dev)
{
- struct r8180_priv *priv = ieee80211_priv(dev);
-
- switch(priv->rf_chip)
- {
- case RF_ZEBRA2: // [AnnieWorkaround] For Zebra2, 2005-08-01.
- case RF_ZEBRA4:
- DIG_Zebra( dev );
- break;
-
- default:
- printk("DynamicInitGain(): unknown RFChipID(%d) !!!\n", priv->rf_chip);
- break;
- }
+ DIG_Zebra(dev);
}
void rtl8180_hw_dig_wq (struct work_struct *work)
{
-// struct r8180_priv *priv = container_of(work, struct r8180_priv, watch_dog_wq);
-// struct ieee80211_device * ieee = (struct ieee80211_device*)
-// container_of(work, struct ieee80211_device, watch_dog_wq);
struct delayed_work *dwork = to_delayed_work(work);
struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,hw_dig_wq);
struct net_device *dev = ieee->dev;
@@ -1310,44 +1293,24 @@ SetAntenna8185(
switch(u1bAntennaIndex)
{
case 0:
- switch(priv->rf_chip)
- {
- case RF_ZEBRA2:
- case RF_ZEBRA4:
- // Mac register, main antenna
- write_nic_byte(dev, ANTSEL, 0x03);
- //base band
- write_phy_cck(dev,0x11, 0x9b); // Config CCK RX antenna.
- write_phy_ofdm(dev, 0x0d, 0x5c); // Config OFDM RX antenna.
-
-
- bAntennaSwitched = true;
- break;
+ /* Mac register, main antenna */
+ write_nic_byte(dev, ANTSEL, 0x03);
+ /* base band */
+ write_phy_cck(dev, 0x11, 0x9b); /* Config CCK RX antenna. */
+ write_phy_ofdm(dev, 0x0d, 0x5c); /* Config OFDM RX antenna. */
- default:
- printk("SetAntenna8185: unknown RFChipID(%d)\n", priv->rf_chip);
- break;
- }
+ bAntennaSwitched = true;
break;
case 1:
- switch(priv->rf_chip)
- {
- case RF_ZEBRA2:
- case RF_ZEBRA4:
- // Mac register, aux antenna
- write_nic_byte(dev, ANTSEL, 0x00);
- //base band
- write_phy_cck(dev, 0x11, 0xbb); // Config CCK RX antenna.
- write_phy_ofdm(dev, 0x0d, 0x54); // Config OFDM RX antenna.
-
- bAntennaSwitched = true;
- break;
+ /* Mac register, aux antenna */
+ write_nic_byte(dev, ANTSEL, 0x00);
+ /* base band */
+ write_phy_cck(dev, 0x11, 0xbb); /* Config CCK RX antenna. */
+ write_phy_ofdm(dev, 0x0d, 0x54); /* Config OFDM RX antenna. */
+
+ bAntennaSwitched = true;
- default:
- printk("SetAntenna8185: unknown RFChipID(%d)\n", priv->rf_chip);
- break;
- }
break;
default:
diff --git a/drivers/staging/rtl8187se/r8180_rtl8225z2.c b/drivers/staging/rtl8187se/r8180_rtl8225z2.c
index afe10f0b75a..6edf5a46fa4 100644
--- a/drivers/staging/rtl8187se/r8180_rtl8225z2.c
+++ b/drivers/staging/rtl8187se/r8180_rtl8225z2.c
@@ -854,134 +854,48 @@ bool SetZebraRFPowerState8185(struct net_device *dev,
btConfig3 = read_nic_byte(dev, CONFIG3);
write_nic_byte(dev, CONFIG3, (btConfig3 | CONFIG3_PARM_En));
- switch (priv->rf_chip) {
- case RF_ZEBRA2:
- switch (eRFPowerState) {
- case eRfOn:
- RF_WriteReg(dev,0x4,0x9FF);
+ switch (eRFPowerState) {
+ case eRfOn:
+ write_nic_word(dev, 0x37C, 0x00EC);
- write_nic_dword(dev, ANAPARAM, ANAPARM_ON);
- write_nic_dword(dev, ANAPARAM2, ANAPARM2_ON);
+ /* turn on AFE */
+ write_nic_byte(dev, 0x54, 0x00);
+ write_nic_byte(dev, 0x62, 0x00);
- write_nic_byte(dev, CONFIG4, priv->RFProgType);
+ /* turn on RF */
+ RF_WriteReg(dev, 0x0, 0x009f); udelay(500);
+ RF_WriteReg(dev, 0x4, 0x0972); udelay(500);
- /* turn on CCK and OFDM */
- u1bTmp = read_nic_byte(dev, 0x24E);
- write_nic_byte(dev, 0x24E, (u1bTmp & (~(BIT5 | BIT6))));
- break;
- case eRfSleep:
- break;
- case eRfOff:
- break;
- default:
- bResult = false;
- break;
- }
- break;
- case RF_ZEBRA4:
- switch (eRFPowerState) {
- case eRfOn:
- write_nic_word(dev, 0x37C, 0x00EC);
-
- /* turn on AFE */
- write_nic_byte(dev, 0x54, 0x00);
- write_nic_byte(dev, 0x62, 0x00);
-
- /* turn on RF */
- RF_WriteReg(dev, 0x0, 0x009f); udelay(500);
- RF_WriteReg(dev, 0x4, 0x0972); udelay(500);
-
- /* turn on RF again */
- RF_WriteReg(dev, 0x0, 0x009f); udelay(500);
- RF_WriteReg(dev, 0x4, 0x0972); udelay(500);
+ /* turn on RF again */
+ RF_WriteReg(dev, 0x0, 0x009f); udelay(500);
+ RF_WriteReg(dev, 0x4, 0x0972); udelay(500);
- /* turn on BB */
- write_phy_ofdm(dev,0x10,0x40);
- write_phy_ofdm(dev,0x12,0x40);
-
- /* Avoid power down at init time. */
- write_nic_byte(dev, CONFIG4, priv->RFProgType);
-
- u1bTmp = read_nic_byte(dev, 0x24E);
- write_nic_byte(dev, 0x24E, (u1bTmp & (~(BIT5 | BIT6))));
- break;
- case eRfSleep:
- for (QueueID = 0, i = 0; QueueID < 6;) {
- if (get_curr_tx_free_desc(dev, QueueID) == priv->txringcount) {
- QueueID++;
- continue;
- } else {
- priv->TxPollingTimes ++;
- if (priv->TxPollingTimes >= LPS_MAX_SLEEP_WAITING_TIMES_87SE) {
- bActionAllowed = false;
- break;
- } else
- udelay(10);
- }
- }
+ /* turn on BB */
+ write_phy_ofdm(dev, 0x10, 0x40);
+ write_phy_ofdm(dev, 0x12, 0x40);
- if (bActionAllowed) {
- /* turn off BB RXIQ matrix to cut off rx signal */
- write_phy_ofdm(dev, 0x10, 0x00);
- write_phy_ofdm(dev, 0x12, 0x00);
-
- /* turn off RF */
- RF_WriteReg(dev, 0x4, 0x0000);
- RF_WriteReg(dev, 0x0, 0x0000);
-
- /* turn off AFE except PLL */
- write_nic_byte(dev, 0x62, 0xff);
- write_nic_byte(dev, 0x54, 0xec);
-
- mdelay(1);
-
- {
- int i = 0;
- while (true) {
- u8 tmp24F = read_nic_byte(dev, 0x24f);
-
- if ((tmp24F == 0x01) || (tmp24F == 0x09)) {
- bTurnOffBB = true;
- break;
- } else {
- udelay(10);
- i++;
- priv->TxPollingTimes++;
-
- if (priv->TxPollingTimes >= LPS_MAX_SLEEP_WAITING_TIMES_87SE) {
- bTurnOffBB = false;
- break;
- } else
- udelay(10);
- }
- }
- }
-
- if (bTurnOffBB) {
- /* turn off BB */
- u1bTmp = read_nic_byte(dev, 0x24E);
- write_nic_byte(dev, 0x24E, (u1bTmp | BIT5 | BIT6));
-
- /* turn off AFE PLL */
- write_nic_byte(dev, 0x54, 0xFC);
- write_nic_word(dev, 0x37C, 0x00FC);
- }
- }
- break;
- case eRfOff:
- for (QueueID = 0, i = 0; QueueID < 6;) {
- if (get_curr_tx_free_desc(dev, QueueID) == priv->txringcount) {
- QueueID++;
- continue;
- } else {
- udelay(10);
- i++;
- }
+ /* Avoid power down at init time. */
+ write_nic_byte(dev, CONFIG4, priv->RFProgType);
- if (i >= MAX_DOZE_WAITING_TIMES_85B)
+ u1bTmp = read_nic_byte(dev, 0x24E);
+ write_nic_byte(dev, 0x24E, (u1bTmp & (~(BIT5 | BIT6))));
+ break;
+ case eRfSleep:
+ for (QueueID = 0, i = 0; QueueID < 6;) {
+ if (get_curr_tx_free_desc(dev, QueueID) == priv->txringcount) {
+ QueueID++;
+ continue;
+ } else {
+ priv->TxPollingTimes++;
+ if (priv->TxPollingTimes >= LPS_MAX_SLEEP_WAITING_TIMES_87SE) {
+ bActionAllowed = false;
break;
+ } else
+ udelay(10);
}
+ }
+ if (bActionAllowed) {
/* turn off BB RXIQ matrix to cut off rx signal */
write_phy_ofdm(dev, 0x10, 0x00);
write_phy_ofdm(dev, 0x12, 0x00);
@@ -998,22 +912,23 @@ bool SetZebraRFPowerState8185(struct net_device *dev,
{
int i = 0;
-
- while (true)
- {
+ while (true) {
u8 tmp24F = read_nic_byte(dev, 0x24f);
if ((tmp24F == 0x01) || (tmp24F == 0x09)) {
bTurnOffBB = true;
break;
} else {
- bTurnOffBB = false;
udelay(10);
i++;
- }
+ priv->TxPollingTimes++;
- if (i > MAX_POLLING_24F_TIMES_87SE)
- break;
+ if (priv->TxPollingTimes >= LPS_MAX_SLEEP_WAITING_TIMES_87SE) {
+ bTurnOffBB = false;
+ break;
+ } else
+ udelay(10);
+ }
}
}
@@ -1022,15 +937,68 @@ bool SetZebraRFPowerState8185(struct net_device *dev,
u1bTmp = read_nic_byte(dev, 0x24E);
write_nic_byte(dev, 0x24E, (u1bTmp | BIT5 | BIT6));
- /* turn off AFE PLL (80M) */
+ /* turn off AFE PLL */
write_nic_byte(dev, 0x54, 0xFC);
write_nic_word(dev, 0x37C, 0x00FC);
}
- break;
- default:
- bResult = false;
- printk("SetZebraRFPowerState8185(): unknown state to set: 0x%X!!!\n", eRFPowerState);
- break;
+ }
+ break;
+ case eRfOff:
+ for (QueueID = 0, i = 0; QueueID < 6;) {
+ if (get_curr_tx_free_desc(dev, QueueID) == priv->txringcount) {
+ QueueID++;
+ continue;
+ } else {
+ udelay(10);
+ i++;
+ }
+
+ if (i >= MAX_DOZE_WAITING_TIMES_85B)
+ break;
+ }
+
+ /* turn off BB RXIQ matrix to cut off rx signal */
+ write_phy_ofdm(dev, 0x10, 0x00);
+ write_phy_ofdm(dev, 0x12, 0x00);
+
+ /* turn off RF */
+ RF_WriteReg(dev, 0x4, 0x0000);
+ RF_WriteReg(dev, 0x0, 0x0000);
+
+ /* turn off AFE except PLL */
+ write_nic_byte(dev, 0x62, 0xff);
+ write_nic_byte(dev, 0x54, 0xec);
+
+ mdelay(1);
+
+ {
+ int i = 0;
+
+ while (true) {
+ u8 tmp24F = read_nic_byte(dev, 0x24f);
+
+ if ((tmp24F == 0x01) || (tmp24F == 0x09)) {
+ bTurnOffBB = true;
+ break;
+ } else {
+ bTurnOffBB = false;
+ udelay(10);
+ i++;
+ }
+
+ if (i > MAX_POLLING_24F_TIMES_87SE)
+ break;
+ }
+ }
+
+ if (bTurnOffBB) {
+ /* turn off BB */
+ u1bTmp = read_nic_byte(dev, 0x24E);
+ write_nic_byte(dev, 0x24E, (u1bTmp | BIT5 | BIT6));
+
+ /* turn off AFE PLL (80M) */
+ write_nic_byte(dev, 0x54, 0xFC);
+ write_nic_word(dev, 0x37C, 0x00FC);
}
break;
}
diff --git a/drivers/staging/rtl8187se/r8185b_init.c b/drivers/staging/rtl8187se/r8185b_init.c
index 50309f2da9c..a0ece1fd64a 100644
--- a/drivers/staging/rtl8187se/r8185b_init.c
+++ b/drivers/staging/rtl8187se/r8185b_init.c
@@ -238,100 +238,12 @@ PlatformIORead4Byte(
return data;
}
-void
-SetOutputEnableOfRfPins(
- struct net_device *dev
- )
+void SetOutputEnableOfRfPins(struct net_device *dev)
{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
- switch(priv->rf_chip)
- {
- case RFCHIPID_RTL8225:
- case RF_ZEBRA2:
- case RF_ZEBRA4:
- write_nic_word(dev, RFPinsEnable, 0x1bff);
- //write_nic_word(dev, RFPinsEnable, 0x1fff);
- break;
- }
+ write_nic_word(dev, RFPinsEnable, 0x1bff);
}
-void
-ZEBRA_RFSerialWrite(
- struct net_device *dev,
- u32 data2Write,
- u8 totalLength,
- u8 low2high
- )
-{
- ThreeWireReg twreg;
- int i;
- u16 oval,oval2,oval3;
- u32 mask;
- u16 UshortBuffer;
-
- u8 u1bTmp;
- // RTL8187S HSSI Read/Write Function
- u1bTmp = read_nic_byte(dev, RF_SW_CONFIG);
- u1bTmp |= RF_SW_CFG_SI; //reg08[1]=1 Serial Interface(SI)
- write_nic_byte(dev, RF_SW_CONFIG, u1bTmp);
- UshortBuffer = read_nic_word(dev, RFPinsOutput);
- oval = UshortBuffer & 0xfff8; // We shall clear bit0, 1, 2 first, 2005.10.28, by rcnjko.
-
- oval2 = read_nic_word(dev, RFPinsEnable);
- oval3 = read_nic_word(dev, RFPinsSelect);
-
- // <RJ_NOTE> 3-wire should be controled by HW when we finish SW 3-wire programming. 2005.08.10, by rcnjko.
- oval3 &= 0xfff8;
-
- write_nic_word(dev, RFPinsEnable, (oval2|0x0007)); // Set To Output Enable
- write_nic_word(dev, RFPinsSelect, (oval3|0x0007)); // Set To SW Switch
- udelay(10);
-
- // Add this to avoid hardware and software 3-wire conflict.
- // 2005.03.01, by rcnjko.
- twreg.longData = 0;
- twreg.struc.enableB = 1;
- write_nic_word(dev, RFPinsOutput, (twreg.longData|oval)); // Set SI_EN (RFLE)
- udelay(2);
- twreg.struc.enableB = 0;
- write_nic_word(dev, RFPinsOutput, (twreg.longData|oval)); // Clear SI_EN (RFLE)
- udelay(10);
-
- mask = (low2high)?0x01:((u32)0x01<<(totalLength-1));
-
- for(i=0; i<totalLength/2; i++)
- {
- twreg.struc.data = ((data2Write&mask)!=0) ? 1 : 0;
- write_nic_word(dev, RFPinsOutput, (twreg.longData|oval));
- twreg.struc.clk = 1;
- write_nic_word(dev, RFPinsOutput, (twreg.longData|oval));
- write_nic_word(dev, RFPinsOutput, (twreg.longData|oval));
-
- mask = (low2high)?(mask<<1):(mask>>1);
- twreg.struc.data = ((data2Write&mask)!=0) ? 1 : 0;
- write_nic_word(dev, RFPinsOutput, (twreg.longData|oval));
- write_nic_word(dev, RFPinsOutput, (twreg.longData|oval));
- twreg.struc.clk = 0;
- write_nic_word(dev, RFPinsOutput, (twreg.longData|oval));
- mask = (low2high)?(mask<<1):(mask>>1);
- }
-
- twreg.struc.enableB = 1;
- twreg.struc.clk = 0;
- twreg.struc.data = 0;
- write_nic_word(dev, RFPinsOutput, twreg.longData|oval);
- udelay(10);
-
- write_nic_word(dev, RFPinsOutput, oval|0x0004);
- write_nic_word(dev, RFPinsSelect, oval3|0x0000);
-
- SetOutputEnableOfRfPins(dev);
-}
-//by amy
-
-
-int
+static int
HwHSSIThreeWire(
struct net_device *dev,
u8 *pDataBuf,
@@ -469,420 +381,30 @@ HwHSSIThreeWire(
return bResult;
}
-//by amy
-
-int
-HwThreeWire(
- struct net_device *dev,
- u8 *pDataBuf,
- u8 nDataBufBitCnt,
- int bHold,
- int bWrite
- )
-{
- int bResult = 1;
- u8 TryCnt;
- u8 u1bTmp;
-
- do
- {
- // Check if WE and RE are cleared.
- for(TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++)
- {
- u1bTmp = read_nic_byte(dev, SW_3W_CMD1);
- if( (u1bTmp & (SW_3W_CMD1_RE|SW_3W_CMD1_WE)) == 0 )
- {
- break;
- }
- udelay(10);
- }
- if (TryCnt == TC_3W_POLL_MAX_TRY_CNT)
- panic("HwThreeWire(): CmdReg: %#X RE|WE bits are not clear!!\n", u1bTmp);
-
- // Fill up data buffer for write operation.
- if(nDataBufBitCnt == 16)
- {
- write_nic_word(dev, SW_3W_DB0, *((u16 *)pDataBuf));
- }
- else if(nDataBufBitCnt == 64)
- {
- write_nic_dword(dev, SW_3W_DB0, *((u32 *)pDataBuf));
- write_nic_dword(dev, SW_3W_DB1, *((u32 *)(pDataBuf + 4)));
- }
- else
- {
- int idx;
- int ByteCnt = nDataBufBitCnt / 8;
-
- if ((nDataBufBitCnt % 8) != 0)
- panic("HwThreeWire(): nDataBufBitCnt(%d) should be multiple of 8!!!\n",
- nDataBufBitCnt);
-
- if (nDataBufBitCnt > 64)
- panic("HwThreeWire(): nDataBufBitCnt(%d) should <= 64!!!\n",
- nDataBufBitCnt);
-
- for(idx = 0; idx < ByteCnt; idx++)
- {
- write_nic_byte(dev, (SW_3W_DB0+idx), *(pDataBuf+idx));
- }
- }
-
- // Fill up length field.
- u1bTmp = (u8)(nDataBufBitCnt - 1); // Number of bits - 1.
- if(bHold)
- u1bTmp |= SW_3W_CMD0_HOLD;
- write_nic_byte(dev, SW_3W_CMD0, u1bTmp);
-
- // Set up command: WE or RE.
- if(bWrite)
- {
- write_nic_byte(dev, SW_3W_CMD1, SW_3W_CMD1_WE);
- }
- else
- {
- write_nic_byte(dev, SW_3W_CMD1, SW_3W_CMD1_RE);
- }
-
- // Check if WE and RE are cleared and DONE is set.
- for(TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++)
- {
- u1bTmp = read_nic_byte(dev, SW_3W_CMD1);
- if( (u1bTmp & (SW_3W_CMD1_RE|SW_3W_CMD1_WE)) == 0 &&
- (u1bTmp & SW_3W_CMD1_DONE) != 0 )
- {
- break;
- }
- udelay(10);
- }
- if(TryCnt == TC_3W_POLL_MAX_TRY_CNT)
- {
- //RT_ASSERT(TryCnt != TC_3W_POLL_MAX_TRY_CNT,
- // ("HwThreeWire(): CmdReg: %#X RE|WE bits are not clear or DONE is not set!!\n", u1bTmp));
- // Workaround suggested by wcchu: clear WE here. 2006.07.07, by rcnjko.
- write_nic_byte(dev, SW_3W_CMD1, 0);
- }
-
- // Read back data for read operation.
- // <RJ_TODO> I am not sure if this is correct output format of a read operation.
- if(bWrite == 0)
- {
- if(nDataBufBitCnt == 16)
- {
- *((u16 *)pDataBuf) = read_nic_word(dev, SW_3W_DB0);
- }
- else if(nDataBufBitCnt == 64)
- {
- *((u32 *)pDataBuf) = read_nic_dword(dev, SW_3W_DB0);
- *((u32 *)(pDataBuf + 4)) = read_nic_dword(dev, SW_3W_DB1);
- }
- else
- {
- int idx;
- int ByteCnt = nDataBufBitCnt / 8;
-
- if ((nDataBufBitCnt % 8) != 0)
- panic("HwThreeWire(): nDataBufBitCnt(%d) should be multiple of 8!!!\n",
- nDataBufBitCnt);
-
- if (nDataBufBitCnt > 64)
- panic("HwThreeWire(): nDataBufBitCnt(%d) should <= 64!!!\n",
- nDataBufBitCnt);
-
- for(idx = 0; idx < ByteCnt; idx++)
- {
- *(pDataBuf+idx) = read_nic_byte(dev, (SW_3W_DB0+idx));
- }
- }
- }
-
- }while(0);
-
- return bResult;
-}
-
void
-RF_WriteReg(
- struct net_device *dev,
- u8 offset,
- u32 data
- )
+RF_WriteReg(struct net_device *dev, u8 offset, u32 data)
{
- //RFReg reg;
- u32 data2Write;
- u8 len;
- u8 low2high;
- //u32 RF_Read = 0;
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
-
- switch(priv->rf_chip)
- {
- case RFCHIPID_RTL8225:
- case RF_ZEBRA2: // Annie 2006-05-12.
- case RF_ZEBRA4: //by amy
- switch(priv->RegThreeWireMode)
- {
- case SW_THREE_WIRE:
- { // Perform SW 3-wire programming by driver.
- data2Write = (data << 4) | (u32)(offset & 0x0f);
- len = 16;
- low2high = 0;
- ZEBRA_RFSerialWrite(dev, data2Write, len, low2high);
- }
- break;
+ u32 data2Write;
+ u8 len;
- case HW_THREE_WIRE:
- { // Pure HW 3-wire.
- data2Write = (data << 4) | (u32)(offset & 0x0f);
- len = 16;
- HwThreeWire(
- dev,
- (u8 *)(&data2Write), // pDataBuf,
- len, // nDataBufBitCnt,
- 0, // bHold,
- 1); // bWrite
- }
- break;
- case HW_THREE_WIRE_PI: //Parallel Interface
- { // Pure HW 3-wire.
- data2Write = (data << 4) | (u32)(offset & 0x0f);
- len = 16;
- HwHSSIThreeWire(
- dev,
- (u8*)(&data2Write), // pDataBuf,
- len, // nDataBufBitCnt,
- 0, // bSI
- 1); // bWrite
-
- //printk("33333\n");
- }
- break;
-
- case HW_THREE_WIRE_SI: //Serial Interface
- { // Pure HW 3-wire.
- data2Write = (data << 4) | (u32)(offset & 0x0f);
- len = 16;
-// printk(" enter ZEBRA_RFSerialWrite\n ");
-// low2high = 0;
-// ZEBRA_RFSerialWrite(dev, data2Write, len, low2high);
-
- HwHSSIThreeWire(
- dev,
- (u8*)(&data2Write), // pDataBuf,
- len, // nDataBufBitCnt,
- 1, // bSI
- 1); // bWrite
-
-// printk(" exit ZEBRA_RFSerialWrite\n ");
- }
- break;
-
-
- default:
- DMESGE("RF_WriteReg(): invalid RegThreeWireMode(%d) !!!", priv->RegThreeWireMode);
- break;
- }
- break;
-
- default:
- DMESGE("RF_WriteReg(): unknown RFChipID: %#X", priv->rf_chip);
- break;
- }
-}
-
-
-void
-ZEBRA_RFSerialRead(
- struct net_device *dev,
- u32 data2Write,
- u8 wLength,
- u32 *data2Read,
- u8 rLength,
- u8 low2high
- )
-{
- ThreeWireReg twreg;
- int i;
- u16 oval,oval2,oval3,tmp, wReg80;
- u32 mask;
- u8 u1bTmp;
- ThreeWireReg tdata;
- //PHAL_DATA_8187 pHalData = GetHalData8187(pAdapter);
- { // RTL8187S HSSI Read/Write Function
- u1bTmp = read_nic_byte(dev, RF_SW_CONFIG);
- u1bTmp |= RF_SW_CFG_SI; //reg08[1]=1 Serial Interface(SI)
- write_nic_byte(dev, RF_SW_CONFIG, u1bTmp);
- }
-
- wReg80 = oval = read_nic_word(dev, RFPinsOutput);
- oval2 = read_nic_word(dev, RFPinsEnable);
- oval3 = read_nic_word(dev, RFPinsSelect);
-
- write_nic_word(dev, RFPinsEnable, oval2|0xf);
- write_nic_word(dev, RFPinsSelect, oval3|0xf);
-
- *data2Read = 0;
-
- // We must clear BIT0-3 here, otherwise,
- // SW_Enalbe will be true when we first call ZEBRA_RFSerialRead() after 8187MPVC open,
- // which will cause the value read become 0. 2005.04.11, by rcnjko.
- oval &= ~0xf;
-
- // Avoid collision with hardware three-wire.
- twreg.longData = 0;
- twreg.struc.enableB = 1;
- write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(4);
-
- twreg.longData = 0;
- twreg.struc.enableB = 0;
- twreg.struc.clk = 0;
- twreg.struc.read_write = 0;
- write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(5);
-
- mask = (low2high) ? 0x01 : ((u32)0x01<<(32-1));
- for(i = 0; i < wLength/2; i++)
- {
- twreg.struc.data = ((data2Write&mask) != 0) ? 1 : 0;
- write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(1);
- twreg.struc.clk = 1;
- write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
- write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
-
- mask = (low2high) ? (mask<<1): (mask>>1);
-
- if(i == 2)
- {
- // Commented out by Jackie, 2004.08.26. <RJ_NOTE> We must comment out the following two lines for we cannot pull down VCOPDN during RF Serail Read.
- //PlatformEFIOWrite2Byte(pAdapter, RFPinsEnable, 0xe); // turn off data enable
- //PlatformEFIOWrite2Byte(pAdapter, RFPinsSelect, 0xe);
-
- twreg.struc.read_write=1;
- write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
- twreg.struc.clk = 0;
- write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
- break;
- }
- twreg.struc.data = ((data2Write&mask) != 0) ? 1: 0;
- write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
- write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
-
- twreg.struc.clk = 0;
- write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(1);
-
- mask = (low2high) ? (mask<<1) : (mask>>1);
- }
-
- twreg.struc.clk = 0;
- twreg.struc.data = 0;
- write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
- mask = (low2high) ? 0x01 : ((u32)0x01 << (12-1));
-
- //
- // 061016, by rcnjko:
- // We must set data pin to HW controled, otherwise RF can't driver it and
- // value RF register won't be able to read back properly.
- //
- write_nic_word(dev, RFPinsEnable, ( ((oval2|0x0E) & (~0x01))) );
+ /* Pure HW 3-wire. */
+ data2Write = (data << 4) | (u32)(offset & 0x0f);
+ len = 16;
- for(i = 0; i < rLength; i++)
- {
- write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(1);
- twreg.struc.clk = 1;
- write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
- write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
- write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
- tmp = read_nic_word(dev, RFPinsInput);
- tdata.longData = tmp;
- *data2Read |= tdata.struc.clk ? mask : 0;
-
- twreg.struc.clk = 0;
- write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
-
- mask = (low2high) ? (mask<<1) : (mask>>1);
- }
- twreg.struc.enableB = 1;
- twreg.struc.clk = 0;
- twreg.struc.data = 0;
- twreg.struc.read_write = 1;
- write_nic_word(dev, RFPinsOutput, twreg.longData|oval); udelay(2);
-
- //PlatformEFIOWrite2Byte(pAdapter, RFPinsEnable, oval2|0x8); // Set To Output Enable
- write_nic_word(dev, RFPinsEnable, oval2); // Set To Output Enable, <RJ_NOTE> We cannot enable BIT3 here, otherwise, we will failed to switch channel. 2005.04.12.
- //PlatformEFIOWrite2Byte(pAdapter, RFPinsEnable, 0x1bff);
- write_nic_word(dev, RFPinsSelect, oval3); // Set To SW Switch
- //PlatformEFIOWrite2Byte(pAdapter, RFPinsSelect, 0x0488);
- write_nic_word(dev, RFPinsOutput, 0x3a0);
- //PlatformEFIOWrite2Byte(pAdapter, RFPinsOutput, 0x0480);
+ HwHSSIThreeWire(dev, (u8 *)(&data2Write), len, 1, 1);
}
-
-u32
-RF_ReadReg(
- struct net_device *dev,
- u8 offset
- )
+u32 RF_ReadReg(struct net_device *dev, u8 offset)
{
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- u32 data2Write;
- u8 wlen;
- u8 rlen;
- u8 low2high;
- u32 dataRead;
+ u32 data2Write;
+ u8 wlen;
+ u32 dataRead;
- switch(priv->rf_chip)
- {
- case RFCHIPID_RTL8225:
- case RF_ZEBRA2:
- case RF_ZEBRA4:
- switch(priv->RegThreeWireMode)
- {
- case HW_THREE_WIRE_PI: // For 87S Parallel Interface.
- {
- data2Write = ((u32)(offset&0x0f));
- wlen=16;
- HwHSSIThreeWire(
- dev,
- (u8*)(&data2Write), // pDataBuf,
- wlen, // nDataBufBitCnt,
- 0, // bSI
- 0); // bWrite
- dataRead= data2Write;
- }
- break;
-
- case HW_THREE_WIRE_SI: // For 87S Serial Interface.
- {
- data2Write = ((u32)(offset&0x0f)) ;
- wlen=16;
- HwHSSIThreeWire(
- dev,
- (u8*)(&data2Write), // pDataBuf,
- wlen, // nDataBufBitCnt,
- 1, // bSI
- 0 // bWrite
- );
- dataRead= data2Write;
- }
- break;
-
- // Perform SW 3-wire programming by driver.
- default:
- {
- data2Write = ((u32)(offset&0x1f)) << 27; // For Zebra E-cut. 2005.04.11, by rcnjko.
- wlen = 6;
- rlen = 12;
- low2high = 0;
- ZEBRA_RFSerialRead(dev, data2Write, wlen,&dataRead,rlen, low2high);
- }
- break;
- }
- break;
- default:
- dataRead = 0;
- break;
- }
+ data2Write = ((u32)(offset & 0x0f));
+ wlen = 16;
+ HwHSSIThreeWire(dev, (u8 *)(&data2Write), wlen, 1, 0);
+ dataRead = data2Write;
return dataRead;
}
@@ -1043,15 +565,12 @@ ZEBRA_Config_85BASIC_HardCode(
// Page0 : reg0-reg15
-// RF_WriteReg(dev, 0x00, 0x003f); mdelay(1);//1
RF_WriteReg(dev, 0x00, 0x009f); mdelay(1);// 1
RF_WriteReg(dev, 0x01, 0x06e0); mdelay(1);
-// RF_WriteReg(dev, 0x02, 0x004c); mdelay(1);//2
RF_WriteReg(dev, 0x02, 0x004d); mdelay(1);// 2
-// RF_WriteReg(dev, 0x03, 0x0000); mdelay(1);//3
RF_WriteReg(dev, 0x03, 0x07f1); mdelay(1);// 3
RF_WriteReg(dev, 0x04, 0x0975); mdelay(1);
@@ -1080,8 +599,6 @@ ZEBRA_Config_85BASIC_HardCode(
RF_WriteReg(dev, 0x07, 0x01A0); mdelay(1);
// Don't write RF23/RF24 to make a difference between 87S C cut and D cut. asked by SD3 stevenl.
-// RF_WriteReg(dev, 0x08, 0x0597); mdelay(1);
-// RF_WriteReg(dev, 0x09, 0x050a); mdelay(1);
RF_WriteReg(dev, 0x0a, 0x0001); mdelay(1);
RF_WriteReg(dev, 0x0b, 0x0418); mdelay(1);
@@ -1097,7 +614,6 @@ ZEBRA_Config_85BASIC_HardCode(
RF_WriteReg(dev, 0x0f, 0x0acc); mdelay(1);
-// RF_WriteReg(dev, 0x00, 0x017f); mdelay(1);//6
RF_WriteReg(dev, 0x00, 0x01d7); mdelay(1);// 6
RF_WriteReg(dev, 0x03, 0x0e00); mdelay(1);
@@ -1106,20 +622,14 @@ ZEBRA_Config_85BASIC_HardCode(
{
RF_WriteReg(dev, 0x01, i); mdelay(1);
RF_WriteReg(dev, 0x02, ZEBRA_RF_RX_GAIN_TABLE[i]); mdelay(1);
- //DbgPrint("RF - 0x%x = 0x%x", i, ZEBRA_RF_RX_GAIN_TABLE[i]);
}
RF_WriteReg(dev, 0x05, 0x0203); mdelay(1); /// 203, 343
- //RF_WriteReg(dev, 0x06, 0x0300); mdelay(1); // 400
RF_WriteReg(dev, 0x06, 0x0200); mdelay(1); // 400
RF_WriteReg(dev, 0x00, 0x0137); mdelay(1); // switch to reg16-reg30, and HSSI disable 137
mdelay(10); // Deay 10 ms. //0xfd
-// RF_WriteReg(dev, 0x0c, 0x09be); mdelay(1); // 7
- //RF_WriteReg(dev, 0x0c, 0x07be); mdelay(1);
- //mdelay(10); // Deay 10 ms. //0xfd
-
RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1); // Z4 synthesizer loop filter setting, 392
mdelay(10); // Deay 10 ms. //0xfd
@@ -1165,10 +675,8 @@ ZEBRA_Config_85BASIC_HardCode(
RF_WriteReg(dev, 0x0f, 0x0acc); mdelay(1);
}
//by amy 080312
-// RF_WriteReg(dev, 0x0f, 0x0acc); mdelay(1); //-by amy 080312
RF_WriteReg(dev, 0x00, 0x00bf); mdelay(1); // switch to reg0-reg15, and HSSI enable
-// RF_WriteReg(dev, 0x0d, 0x009f); mdelay(1); // Rx BB start calibration, 00c//-edward
RF_WriteReg(dev, 0x0d, 0x08df); mdelay(1); // Rx BB start calibration, 00c//+edward
RF_WriteReg(dev, 0x02, 0x004d); mdelay(1); // temperature meter off
RF_WriteReg(dev, 0x04, 0x0975); mdelay(1); // Rx mode
@@ -1217,13 +725,10 @@ ZEBRA_Config_85BASIC_HardCode(
// AGC.txt
//=============================================================================
-// PlatformIOWrite4Byte( dev, PhyAddr, 0x00001280); // Annie, 2006-05-05
write_phy_ofdm(dev, 0x00, 0x12);
- //WriteBBPortUchar(dev, 0x00001280);
for (i=0; i<128; i++)
{
- //DbgPrint("AGC - [%x+1] = 0x%x\n", i, ZEBRA_AGC[i+1]);
data = ZEBRA_AGC[i+1];
data = data << 8;
@@ -1239,7 +744,6 @@ ZEBRA_Config_85BASIC_HardCode(
}
PlatformIOWrite4Byte( dev, PhyAddr, 0x00001080); // Annie, 2006-05-05
- //WriteBBPortUchar(dev, 0x00001080);
//=============================================================================
@@ -1252,8 +756,6 @@ ZEBRA_Config_85BASIC_HardCode(
u4bRegOffset=i;
u4bRegValue=OFDM_CONFIG[i];
- //DbgPrint("OFDM - 0x%x = 0x%x\n", u4bRegOffset, u4bRegValue);
-
WriteBBPortUchar(dev,
(0x00000080 |
(u4bRegOffset & 0x7f) |
@@ -1277,9 +779,6 @@ UpdateInitialGain(
)
{
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- //unsigned char* IGTable;
- //u8 DIG_CurrentInitialGain = 4;
- //unsigned char u1Tmp;
//lzm add 080826
if(priv->eRFPowerState != eRfOn)
@@ -1291,81 +790,59 @@ UpdateInitialGain(
return;
}
- switch(priv->rf_chip)
- {
- case RF_ZEBRA4:
- // Dynamic set initial gain, follow 87B
- switch(priv->InitialGain)
- {
- case 1: //m861dBm
- //DMESG("RTL8187 + 8225 Initial Gain State 1: -82 dBm \n");
- write_phy_ofdm(dev, 0x17, 0x26); mdelay(1);
- write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
- write_phy_ofdm(dev, 0x05, 0xfa); mdelay(1);
- break;
-
- case 2: //m862dBm
- //DMESG("RTL8187 + 8225 Initial Gain State 2: -82 dBm \n");
- write_phy_ofdm(dev, 0x17, 0x36); mdelay(1);
- write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
- write_phy_ofdm(dev, 0x05, 0xfa); mdelay(1);
- break;
-
- case 3: //m863dBm
- //DMESG("RTL8187 + 8225 Initial Gain State 3: -82 dBm \n");
- write_phy_ofdm(dev, 0x17, 0x36); mdelay(1);
- write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
- write_phy_ofdm(dev, 0x05, 0xfb); mdelay(1);
- break;
-
- case 4: //m864dBm
- //DMESG("RTL8187 + 8225 Initial Gain State 4: -78 dBm \n");
- write_phy_ofdm(dev, 0x17, 0x46); mdelay(1);
- write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
- write_phy_ofdm(dev, 0x05, 0xfb); mdelay(1);
- break;
+ switch (priv->InitialGain) {
+ case 1: /* m861dBm */
+ write_phy_ofdm(dev, 0x17, 0x26); mdelay(1);
+ write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
+ write_phy_ofdm(dev, 0x05, 0xfa); mdelay(1);
+ break;
- case 5: //m82dBm
- //DMESG("RTL8187 + 8225 Initial Gain State 5: -74 dBm \n");
- write_phy_ofdm(dev, 0x17, 0x46); mdelay(1);
- write_phy_ofdm(dev, 0x24, 0x96); mdelay(1);
- write_phy_ofdm(dev, 0x05, 0xfb); mdelay(1);
- break;
+ case 2: /* m862dBm */
+ write_phy_ofdm(dev, 0x17, 0x36); mdelay(1);
+ write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
+ write_phy_ofdm(dev, 0x05, 0xfa); mdelay(1);
+ break;
- case 6: //m78dBm
- //DMESG ("RTL8187 + 8225 Initial Gain State 6: -70 dBm \n");
- write_phy_ofdm(dev, 0x17, 0x56); mdelay(1);
- write_phy_ofdm(dev, 0x24, 0x96); mdelay(1);
- write_phy_ofdm(dev, 0x05, 0xfc); mdelay(1);
- break;
+ case 3: /* m863dBm */
+ write_phy_ofdm(dev, 0x17, 0x36); mdelay(1);
+ write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
+ write_phy_ofdm(dev, 0x05, 0xfb); mdelay(1);
+ break;
- case 7: //m74dBm
- //DMESG("RTL8187 + 8225 Initial Gain State 7: -66 dBm \n");
- write_phy_ofdm(dev, 0x17, 0x56); mdelay(1);
- write_phy_ofdm(dev, 0x24, 0xa6); mdelay(1);
- write_phy_ofdm(dev, 0x05, 0xfc); mdelay(1);
- break;
+ case 4: /* m864dBm */
+ write_phy_ofdm(dev, 0x17, 0x46); mdelay(1);
+ write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
+ write_phy_ofdm(dev, 0x05, 0xfb); mdelay(1);
+ break;
- case 8:
- //DMESG("RTL8187 + 8225 Initial Gain State 8:\n");
- write_phy_ofdm(dev, 0x17, 0x66); mdelay(1);
- write_phy_ofdm(dev, 0x24, 0xb6); mdelay(1);
- write_phy_ofdm(dev, 0x05, 0xfc); mdelay(1);
- break;
+ case 5: /* m82dBm */
+ write_phy_ofdm(dev, 0x17, 0x46); mdelay(1);
+ write_phy_ofdm(dev, 0x24, 0x96); mdelay(1);
+ write_phy_ofdm(dev, 0x05, 0xfb); mdelay(1);
+ break;
+ case 6: /* m78dBm */
+ write_phy_ofdm(dev, 0x17, 0x56); mdelay(1);
+ write_phy_ofdm(dev, 0x24, 0x96); mdelay(1);
+ write_phy_ofdm(dev, 0x05, 0xfc); mdelay(1);
+ break;
- default: //MP
- //DMESG("RTL8187 + 8225 Initial Gain State 1: -82 dBm (default)\n");
- write_phy_ofdm(dev, 0x17, 0x26); mdelay(1);
- write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
- write_phy_ofdm(dev, 0x05, 0xfa); mdelay(1);
- break;
- }
+ case 7: /* m74dBm */
+ write_phy_ofdm(dev, 0x17, 0x56); mdelay(1);
+ write_phy_ofdm(dev, 0x24, 0xa6); mdelay(1);
+ write_phy_ofdm(dev, 0x05, 0xfc); mdelay(1);
break;
+ case 8:
+ write_phy_ofdm(dev, 0x17, 0x66); mdelay(1);
+ write_phy_ofdm(dev, 0x24, 0xb6); mdelay(1);
+ write_phy_ofdm(dev, 0x05, 0xfc); mdelay(1);
+ break;
- default:
- DMESG("UpdateInitialGain(): unknown RFChipID: %#X\n", priv->rf_chip);
+ default: /* MP */
+ write_phy_ofdm(dev, 0x17, 0x26); mdelay(1);
+ write_phy_ofdm(dev, 0x24, 0x86); mdelay(1);
+ write_phy_ofdm(dev, 0x05, 0xfa); mdelay(1);
break;
}
}
@@ -1379,13 +856,11 @@ InitTxPwrTracking87SE(
struct net_device *dev
)
{
- //struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
u32 u4bRfReg;
u4bRfReg = RF_ReadReg(dev, 0x02);
// Enable Thermal meter indication.
- //printk("InitTxPwrTracking87SE(): Enable thermal meter indication, Write RF[0x02] = %#x", u4bRfReg|PWR_METER_EN);
RF_WriteReg(dev, 0x02, u4bRfReg|PWR_METER_EN); mdelay(1);
}
@@ -1397,21 +872,14 @@ PhyConfig8185(
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
write_nic_dword(dev, RCR, priv->ReceiveConfig);
priv->RFProgType = read_nic_byte(dev, CONFIG4) & 0x03;
- // RF config
- switch(priv->rf_chip)
- {
- case RF_ZEBRA2:
- case RF_ZEBRA4:
- ZEBRA_Config_85BASIC_HardCode( dev);
- break;
- }
+ /* RF config */
+ ZEBRA_Config_85BASIC_HardCode(dev);
//{by amy 080312
// Set default initial gain state to 4, approved by SD3 DZ, by Bruce, 2007-06-06.
if(priv->bDigMechanism)
{
if(priv->InitialGain == 0)
priv->InitialGain = 4;
- //printk("PhyConfig8185(): DIG is enabled, set default initial gain index to %d\n", priv->InitialGain);
}
//
@@ -1429,34 +897,17 @@ PhyConfig8185(
return;
}
-
-
-
void
HwConfigureRTL8185(
struct net_device *dev
)
{
//RTL8185_TODO: Determine Retrylimit, TxAGC, AutoRateFallback control.
-// u8 bUNIVERSAL_CONTROL_RL = 1;
u8 bUNIVERSAL_CONTROL_RL = 0;
-
u8 bUNIVERSAL_CONTROL_AGC = 1;
u8 bUNIVERSAL_CONTROL_ANT = 1;
u8 bAUTO_RATE_FALLBACK_CTL = 1;
u8 val8;
- //struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- //struct ieee80211_device *ieee = priv->ieee80211;
- //if(IS_WIRELESS_MODE_A(dev) || IS_WIRELESS_MODE_G(dev))
-//{by amy 080312 if((ieee->mode == IEEE_G)||(ieee->mode == IEEE_A))
-// {
-// write_nic_word(dev, BRSR, 0xffff);
-// }
-// else
-// {
-// write_nic_word(dev, BRSR, 0x000f);
-// }
-//by amy 080312}
write_nic_word(dev, BRSR, 0x0fff);
// Retry limit
val8 = read_nic_byte(dev, CW_CONF);
@@ -1507,20 +958,11 @@ HwConfigureRTL8185(
val8 |= RATE_FALLBACK_CTL_ENABLE | RATE_FALLBACK_CTL_AUTO_STEP1;
// <RJ_TODO_8185B> We shall set up the ARFR according to user's setting.
- //write_nic_word(dev, ARFR, 0x0fff); // set 1M ~ 54M
-//by amy
- // Aadded by Roger, 2007.11.15.
PlatformIOWrite2Byte(dev, ARFR, 0x0fff); //set 1M ~ 54Mbps.
-//by amy
- }
- else
- {
}
write_nic_byte(dev, RATE_FALLBACK, val8);
}
-
-
static void
MacConfig_85BASIC_HardCode(
struct net_device *dev)
@@ -1548,14 +990,11 @@ MacConfig_85BASIC_HardCode(
{
u4bRegOffset |= (u4bPageIndex << 8);
}
- //DbgPrint("MAC - 0x%x = 0x%x\n", u4bRegOffset, u4bRegValue);
write_nic_byte(dev, u4bRegOffset, (u8)u4bRegValue);
}
//============================================================================
}
-
-
static void
MacConfig_85BASIC(
struct net_device *dev)
@@ -1578,8 +1017,6 @@ MacConfig_85BASIC(
PlatformIOWrite1Byte(dev, 0x1F8, 0x00);
// Asked for by SD3 CM Lin, 2006.06.27, by rcnjko.
- //PlatformIOWrite4Byte(dev, RFTiming, 0x00004001);
-//by amy
// power save parameter based on "87SE power save parameters 20071127.doc", as follow.
//Enable DA10 TX power saving
@@ -1598,35 +1035,18 @@ MacConfig_85BASIC(
write_nic_word(dev, 0x378, 0x0560);
write_nic_word(dev, 0x37A, 0x0560);
write_nic_word(dev, 0x37C, 0x00EC);
-// write_nic_word(dev, 0x37E, 0x00FE);//-edward
write_nic_word(dev, 0x37E, 0x00EC);//+edward
write_nic_byte(dev, 0x24E,0x01);
-//by amy
-
}
-
-
-
u8
GetSupportedWirelessMode8185(
struct net_device *dev
)
{
u8 btSupportedWirelessMode = 0;
- struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
-
- switch(priv->rf_chip)
- {
- case RF_ZEBRA2:
- case RF_ZEBRA4:
- btSupportedWirelessMode = (WIRELESS_MODE_B | WIRELESS_MODE_G);
- break;
- default:
- btSupportedWirelessMode = WIRELESS_MODE_B;
- break;
- }
+ btSupportedWirelessMode = (WIRELESS_MODE_B | WIRELESS_MODE_G);
return btSupportedWirelessMode;
}
@@ -1641,7 +1061,6 @@ ActUpdateChannelAccessSetting(
struct ieee80211_device *ieee = priv->ieee80211;
AC_CODING eACI;
AC_PARAM AcParam;
- //PSTA_QOS pStaQos = Adapter->MgntInfo.pStaQos;
u8 bFollowLegacySetting = 0;
u8 u1bAIFS;
@@ -1663,40 +1082,14 @@ ActUpdateChannelAccessSetting(
ChnlAccessSetting->CWmaxIndex = 7; // 2006.06.02, by rcnjko.
write_nic_byte(dev, SIFS, ChnlAccessSetting->SIFS_Timer);
- //Adapter->HalFunc.SetHwRegHandler( Adapter, HW_VAR_SLOT_TIME, &ChnlAccessSetting->SlotTimeTimer ); // Rewrited from directly use PlatformEFIOWrite1Byte(), by Annie, 2006-03-29.
write_nic_byte(dev, SLOT, ChnlAccessSetting->SlotTimeTimer); // Rewrited from directly use PlatformEFIOWrite1Byte(), by Annie, 2006-03-29.
u1bAIFS = aSifsTime + (2 * ChnlAccessSetting->SlotTimeTimer );
- //write_nic_byte(dev, AC_VO_PARAM, u1bAIFS);
- //write_nic_byte(dev, AC_VI_PARAM, u1bAIFS);
- //write_nic_byte(dev, AC_BE_PARAM, u1bAIFS);
- //write_nic_byte(dev, AC_BK_PARAM, u1bAIFS);
-
write_nic_byte(dev, EIFS, ChnlAccessSetting->EIFS_Timer);
write_nic_byte(dev, AckTimeOutReg, 0x5B); // <RJ_EXPR_QOS> Suggested by wcchu, it is the default value of EIFS register, 2005.12.08.
-#ifdef TODO
- // <RJ_TODO_NOW_8185B> Update ECWmin/ECWmax, AIFS, TXOP Limit of each AC to the value defined by SPEC.
- if( pStaQos->CurrentQosMode > QOS_DISABLE )
- { // QoS mode.
- if(pStaQos->QBssWirelessMode == WirelessMode)
- {
- // Follow AC Parameters of the QBSS.
- for(eACI = 0; eACI < AC_MAX; eACI++)
- {
- Adapter->HalFunc.SetHwRegHandler(Adapter, HW_VAR_AC_PARAM, (pu1Byte)(&(pStaQos->WMMParamEle.AcParam[eACI])) );
- }
- }
- else
- {
- // Follow Default WMM AC Parameters.
- bFollowLegacySetting = 1;
- }
- }
- else
-#endif
{ // Legacy 802.11.
bFollowLegacySetting = 1;
@@ -1719,14 +1112,12 @@ ActUpdateChannelAccessSetting(
AcParam.f.TXOPLimit = 0;
//lzm reserved 080826
-#if 1
// For turbo mode setting. port from 87B by Isaiah 2008-08-01
if( ieee->current_network.Turbo_Enable == 1 )
AcParam.f.TXOPLimit = 0x01FF;
// For 87SE with Intel 4965 Ad-Hoc mode have poor throughput (19MB)
if (ieee->iw_mode == IW_MODE_ADHOC)
AcParam.f.TXOPLimit = 0x0020;
-#endif
for(eACI = 0; eACI < AC_MAX; eACI++)
{
@@ -1770,18 +1161,13 @@ ActUpdateChannelAccessSetting(
// Cehck ACM bit.
// If it is set, immediately set ACM control bit to downgrading AC for passing WMM testplan. Annie, 2005-12-13.
- //write_nic_byte(dev, ACM_CONTROL, pAcParam->f.AciAifsn);
{
PACI_AIFSN pAciAifsn = (PACI_AIFSN)(&pAcParam->f.AciAifsn);
AC_CODING eACI = pAciAifsn->f.ACI;
//modified Joseph
//for 8187B AsynIORead issue
-#ifdef TODO
- u8 AcmCtrl = pHalData->AcmControl;
-#else
u8 AcmCtrl = 0;
-#endif
if( pAciAifsn->f.ACM )
{ // ACM bit is 1.
switch(eACI)
@@ -1823,19 +1209,10 @@ ActUpdateChannelAccessSetting(
break;
}
}
-
- //printk(KERN_WARNING "SetHwReg8185(): [HW_VAR_ACM_CTRL] Write 0x%X\n", AcmCtrl);
-
-#ifdef TO_DO
- pHalData->AcmControl = AcmCtrl;
-#endif
- //write_nic_byte(dev, ACM_CONTROL, AcmCtrl);
write_nic_byte(dev, ACM_CONTROL, 0);
}
}
}
-
-
}
}
@@ -1847,7 +1224,6 @@ ActSetWirelessMode8185(
{
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
struct ieee80211_device *ieee = priv->ieee80211;
- //PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
u8 btSupportedWirelessMode = GetSupportedWirelessMode8185(dev);
if( (btWirelessMode & btSupportedWirelessMode) == 0 )
@@ -1880,24 +1256,11 @@ ActSetWirelessMode8185(
}
}
-
- // 2. Swtich band: RF or BB specific actions,
- // for example, refresh tables in omc8255, or change initial gain if necessary.
- switch(priv->rf_chip)
- {
- case RF_ZEBRA2:
- case RF_ZEBRA4:
- {
- // Nothing to do for Zebra to switch band.
- // Update current wireless mode if we swtich to specified band successfully.
- ieee->mode = (WIRELESS_MODE)btWirelessMode;
- }
- break;
-
- default:
- DMESGW("ActSetWirelessMode8185(): unsupported RF: 0x%X !!!\n", priv->rf_chip);
- break;
- }
+ /* 2. Swtich band: RF or BB specific actions,
+ * for example, refresh tables in omc8255, or change initial gain if necessary.
+ * Nothing to do for Zebra to switch band.
+ * Update current wireless mode if we swtich to specified band successfully. */
+ ieee->mode = (WIRELESS_MODE)btWirelessMode;
// 3. Change related setting.
if( ieee->mode == WIRELESS_MODE_A ){
@@ -1909,7 +1272,6 @@ ActSetWirelessMode8185(
else if( ieee->mode == WIRELESS_MODE_G ){
DMESG("WIRELESS_MODE_G\n");
}
-
ActUpdateChannelAccessSetting( dev, ieee->mode, &priv->ChannelAccessSetting);
}
@@ -1927,11 +1289,7 @@ DrvIFIndicateDisassociation(
u16 reason
)
{
- //printk("==> DrvIFIndicateDisassociation()\n");
-
// nothing is needed after disassociation request.
-
- //printk("<== DrvIFIndicateDisassociation()\n");
}
void
MgntDisconnectIBSS(
@@ -1941,11 +1299,7 @@ MgntDisconnectIBSS(
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
u8 i;
- //printk("XXXXXXXXXX MgntDisconnect IBSS\n");
-
DrvIFIndicateDisassociation(dev, unspec_reason);
-
-// PlatformZeroMemory( pMgntInfo->Bssid, 6 );
for(i=0;i<6;i++) priv->ieee80211->current_network.bssid[i] = 0x55;
priv->ieee80211->state = IEEE80211_NOLINK;
@@ -1957,16 +1311,10 @@ MgntDisconnectIBSS(
// Because Bcn DMA isn't complete, mgnt queue would stuck until Bcn packet send.
// Disable Beacon Queue Own bit, suggested by jong
-// Adapter->HalFunc.SetTxDescOWNHandler(Adapter, BEACON_QUEUE, 0, 0);
ieee80211_stop_send_beacons(priv->ieee80211);
priv->ieee80211->link_change(dev);
notify_wx_assoc_event(priv->ieee80211);
-
- // Stop SW Beacon.Use hw beacon so do not need to do so.by amy
-
-// MgntIndicateMediaStatus( Adapter, RT_MEDIA_DISCONNECT, GENERAL_INDICATE );
-
}
void
MlmeDisassociateRequest(
@@ -1986,14 +1334,8 @@ MlmeDisassociateRequest(
DrvIFIndicateDisassociation(dev, unspec_reason);
- // pMgntInfo->AsocTimestamp = 0;
for(i=0;i<6;i++) priv->ieee80211->current_network.bssid[i] = 0x22;
-// pMgntInfo->mBrates.Length = 0;
-// Adapter->HalFunc.SetHwRegHandler( Adapter, HW_VAR_BASIC_RATE, (pu1Byte)(&pMgntInfo->mBrates) );
-
ieee80211_disassociate(priv->ieee80211);
-
-
}
}
@@ -2011,23 +1353,12 @@ MgntDisconnectAP(
// I move SecClearAllKeys() to MgntActSet_802_11_DISASSOCIATE().
//
// //2004/09/15, kcwu, the key should be cleared, or the new handshaking will not success
-// SecClearAllKeys(Adapter);
// In WPA WPA2 need to Clear all key ... because new key will set after new handshaking.
-#ifdef TODO
- if( pMgntInfo->SecurityInfo.AuthMode > RT_802_11AuthModeAutoSwitch ||
- (pMgntInfo->bAPSuportCCKM && pMgntInfo->bCCX8021xenable) ) // In CCKM mode will Clear key
- {
- SecClearAllKeys(Adapter);
- RT_TRACE(COMP_SEC, DBG_LOUD,("======>CCKM clear key..."))
- }
-#endif
// 2004.10.11, by rcnjko.
- //MlmeDisassociateRequest( Adapter, pMgntInfo->Bssid, disas_lv_ss );
MlmeDisassociateRequest( dev, priv->ieee80211->current_network.bssid, asRsn );
priv->ieee80211->state = IEEE80211_NOLINK;
-// pMgntInfo->AsocTimestamp = 0;
}
bool
MgntDisconnect(
@@ -2039,20 +1370,7 @@ MgntDisconnect(
//
// Schedule an workitem to wake up for ps mode, 070109, by rcnjko.
//
-#ifdef TODO
- if(pMgntInfo->mPss != eAwake)
- {
- //
- // Using AwkaeTimer to prevent mismatch ps state.
- // In the timer the state will be changed according to the RF is being awoke or not. By Bruce, 2007-10-31.
- //
- // PlatformScheduleWorkItem( &(pMgntInfo->AwakeWorkItem) );
- PlatformSetTimer( Adapter, &(pMgntInfo->AwakeTimer), 0 );
- }
-#endif
- // Indication of disassociation event.
- //DrvIFIndicateDisassociation(Adapter, asRsn);
if(IS_DOT11D_ENABLE(priv->ieee80211))
Dot11d_Reset(priv->ieee80211);
// In adhoc mode, update beacon frame.
@@ -2060,8 +1378,6 @@ MgntDisconnect(
{
if( priv->ieee80211->iw_mode == IW_MODE_ADHOC )
{
-// RT_TRACE(COMP_MLME, DBG_LOUD, ("MgntDisconnect() ===> MgntDisconnectIBSS\n"));
- //printk("MgntDisconnect() ===> MgntDisconnectIBSS\n");
MgntDisconnectIBSS(dev);
}
if( priv->ieee80211->iw_mode == IW_MODE_INFRA )
@@ -2071,17 +1387,10 @@ MgntDisconnect(
// e.g. OID_802_11_DISASSOCIATE in Windows while as MgntDisconnectAP() is
// used to handle disassociation related things to AP, e.g. send Disassoc
// frame to AP. 2005.01.27, by rcnjko.
-// SecClearAllKeys(Adapter);
-
-// RT_TRACE(COMP_MLME, DBG_LOUD, ("MgntDisconnect() ===> MgntDisconnectAP\n"));
- //printk("MgntDisconnect() ===> MgntDisconnectAP\n");
MgntDisconnectAP(dev, asRsn);
}
-
// Inidicate Disconnect, 2005.02.23, by rcnjko.
-// MgntIndicateMediaStatus( Adapter, RT_MEDIA_DISCONNECT, GENERAL_INDICATE);
}
-
return true;
}
//
@@ -2101,25 +1410,12 @@ SetRFPowerState(
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
bool bResult = false;
-// printk("---------> SetRFPowerState(): eRFPowerState(%d)\n", eRFPowerState);
if(eRFPowerState == priv->eRFPowerState)
{
-// printk("<--------- SetRFPowerState(): discard the request for eRFPowerState(%d) is the same.\n", eRFPowerState);
return bResult;
}
- switch(priv->rf_chip)
- {
- case RF_ZEBRA2:
- case RF_ZEBRA4:
- bResult = SetZebraRFPowerState8185(dev, eRFPowerState);
- break;
-
- default:
- printk("SetRFPowerState8185(): unknown RFChipID: 0x%X!!!\n", priv->rf_chip);
- break;;
-}
-// printk("<--------- SetRFPowerState(): bResult(%d)\n", bResult);
+ bResult = SetZebraRFPowerState8185(dev, eRFPowerState);
return bResult;
}
@@ -2149,33 +1445,25 @@ MgntActSet_RF_State(
RT_RF_POWER_STATE rtState;
u16 RFWaitCounter = 0;
unsigned long flag;
-// printk("===>MgntActSet_RF_State(): StateToSet(%d), ChangeSource(0x%x)\n",StateToSet, ChangeSource);
//
// Prevent the race condition of RF state change. By Bruce, 2007-11-28.
// Only one thread can change the RF state at one time, and others should wait to be executed.
//
-#if 1
while(true)
{
-// down(&priv->rf_state);
spin_lock_irqsave(&priv->rf_ps_lock,flag);
if(priv->RFChangeInProgress)
{
-// printk("====================>haha111111111\n");
-// up(&priv->rf_state);
-// RT_TRACE(COMP_RF, DBG_LOUD, ("MgntActSet_RF_State(): RF Change in progress! Wait to set..StateToSet(%d).\n", StateToSet));
spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
// Set RF after the previous action is done.
while(priv->RFChangeInProgress)
{
RFWaitCounter ++;
-// RT_TRACE(COMP_RF, DBG_LOUD, ("MgntActSet_RF_State(): Wait 1 ms (%d times)...\n", RFWaitCounter));
udelay(1000); // 1 ms
// Wait too long, return FALSE to avoid to be stuck here.
if(RFWaitCounter > 1000) // 1sec
{
-// RT_ASSERT(FALSE, ("MgntActSet_RF_State(): Wait too logn to set RF\n"));
printk("MgntActSet_RF_State(): Wait too long to set RF\n");
// TODO: Reset RF state?
return false;
@@ -2184,17 +1472,13 @@ MgntActSet_RF_State(
}
else
{
-// printk("========================>haha2\n");
priv->RFChangeInProgress = true;
-// up(&priv->rf_state);
spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
break;
}
}
-#endif
rtState = priv->eRFPowerState;
-
switch(StateToSet)
{
case eRfOn:
@@ -2215,7 +1499,6 @@ MgntActSet_RF_State(
}
}
else
-// RT_TRACE(COMP_RF, DBG_LOUD, ("MgntActSet_RF_State - eRfon reject pMgntInfo->RfOffReason= 0x%x, ChangeSource=0x%X\n", pMgntInfo->RfOffReason, ChangeSource));
;
break;
@@ -2232,38 +1515,26 @@ MgntActSet_RF_State(
//
// Calling MgntDisconnect() instead of MgntActSet_802_11_DISASSOCIATE(),
// because we do NOT need to set ssid to dummy ones.
- // Revised by Roger, 2007.12.04.
//
MgntDisconnect( dev, disas_lv_ss );
// Clear content of bssDesc[] and bssDesc4Query[] to avoid reporting old bss to UI.
- // 2007.05.28, by shien chang.
-// PlatformZeroMemory( pMgntInfo->bssDesc, sizeof(RT_WLAN_BSS)*MAX_BSS_DESC );
-// pMgntInfo->NumBssDesc = 0;
-// PlatformZeroMemory( pMgntInfo->bssDesc4Query, sizeof(RT_WLAN_BSS)*MAX_BSS_DESC );
-// pMgntInfo->NumBssDesc4Query = 0;
}
-
-
priv->RfOffReason |= ChangeSource;
bActionAllowed = true;
break;
-
case eRfSleep:
priv->RfOffReason |= ChangeSource;
bActionAllowed = true;
break;
-
default:
break;
}
if(bActionAllowed)
{
-// RT_TRACE(COMP_RF, DBG_LOUD, ("MgntActSet_RF_State(): Action is allowed.... StateToSet(%d), RfOffReason(%#X)\n", StateToSet, pMgntInfo->RfOffReason));
// Config HW to the specified mode.
-// printk("MgntActSet_RF_State(): Action is allowed.... StateToSet(%d), RfOffReason(%#X)\n", StateToSet, priv->RfOffReason);
SetRFPowerState(dev, StateToSet);
// Turn on RF.
@@ -2273,7 +1544,6 @@ MgntActSet_RF_State(
if(bConnectBySSID)
{
// by amy not supported
-// MgntActSet_802_11_SSID(Adapter, Adapter->MgntInfo.Ssid.Octet, Adapter->MgntInfo.Ssid.Length, TRUE );
}
}
// Turn off RF.
@@ -2282,18 +1552,11 @@ MgntActSet_RF_State(
HalDisableRx8185Dummy(dev);
}
}
- else
- {
- // printk("MgntActSet_RF_State(): Action is rejected.... StateToSet(%d), ChangeSource(%#X), RfOffReason(%#X)\n", StateToSet, ChangeSource, priv->RfOffReason);
- }
// Release RF spinlock
-// down(&priv->rf_state);
spin_lock_irqsave(&priv->rf_ps_lock,flag);
priv->RFChangeInProgress = false;
-// up(&priv->rf_state);
spin_unlock_irqrestore(&priv->rf_ps_lock,flag);
-// printk("<===MgntActSet_RF_State()\n");
return bActionAllowed;
}
void
@@ -2302,15 +1565,12 @@ InactivePowerSave(
)
{
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
- //u8 index = 0;
-
//
// This flag "bSwRfProcessing", indicates the status of IPS procedure, should be set if the IPS workitem
// is really scheduled.
// The old code, sets this flag before scheduling the IPS workitem and however, at the same time the
// previous IPS workitem did not end yet, fails to schedule the current workitem. Thus, bSwRfProcessing
// blocks the IPS procedure of switching RF.
- // By Bruce, 2007-12-25.
//
priv->bSwRfProcessing = true;
@@ -2326,7 +1586,6 @@ InactivePowerSave(
//
// Description:
// Enter the inactive power save mode. RF will be off
-// 2007.08.17, by shien chang.
//
void
IPSEnter(
@@ -2335,13 +1594,11 @@ IPSEnter(
{
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
RT_RF_POWER_STATE rtState;
- //printk("==============================>enter IPS\n");
if (priv->bInactivePs)
{
rtState = priv->eRFPowerState;
//
- // Added by Bruce, 2007-12-25.
// Do not enter IPS in the following conditions:
// (1) RF is already OFF or Sleep
// (2) bSwRfProcessing (indicates the IPS is still under going)
@@ -2352,12 +1609,10 @@ IPSEnter(
if (rtState == eRfOn && !priv->bSwRfProcessing
&& (priv->ieee80211->state != IEEE80211_LINKED ))
{
- // printk("IPSEnter(): Turn off RF.\n");
priv->eInactivePowerState = eRfOff;
InactivePowerSave(dev);
}
}
-// printk("priv->eRFPowerState is %d\n",priv->eRFPowerState);
}
void
IPSLeave(
@@ -2366,20 +1621,17 @@ IPSLeave(
{
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
RT_RF_POWER_STATE rtState;
- //printk("===================================>leave IPS\n");
if (priv->bInactivePs)
{
rtState = priv->eRFPowerState;
if ((rtState == eRfOff || rtState == eRfSleep) && (!priv->bSwRfProcessing) && priv->RfOffReason <= RF_CHANGE_BY_IPS)
{
-// printk("IPSLeave(): Turn on RF.\n");
priv->eInactivePowerState = eRfOn;
InactivePowerSave(dev);
}
}
-// printk("priv->eRFPowerState is %d\n",priv->eRFPowerState);
}
-//by amy for power save
+
void rtl8185b_adapter_start(struct net_device *dev)
{
struct r8180_priv *priv = ieee80211_priv(dev);
@@ -2388,75 +1640,45 @@ void rtl8185b_adapter_start(struct net_device *dev)
u8 SupportedWirelessMode;
u8 InitWirelessMode;
u8 bInvalidWirelessMode = 0;
- //int i;
u8 tmpu8;
- //u8 u1tmp,u2tmp;
u8 btCR9346;
u8 TmpU1b;
u8 btPSR;
- //rtl8180_rtx_disable(dev);
-//{by amy 080312
write_nic_byte(dev,0x24e, (BIT5|BIT6|BIT0));
-//by amy 080312}
rtl8180_reset(dev);
priv->dma_poll_mask = 0;
priv->dma_poll_stop_mask = 0;
- //rtl8180_beacon_tx_disable(dev);
-
HwConfigureRTL8185(dev);
-
write_nic_dword(dev, MAC0, ((u32*)dev->dev_addr)[0]);
write_nic_word(dev, MAC4, ((u32*)dev->dev_addr)[1] & 0xffff );
-
write_nic_byte(dev, MSR, read_nic_byte(dev, MSR) & 0xf3); // default network type to 'No Link'
-
- //write_nic_byte(dev, BRSR, 0x0); // Set BRSR= 1M
-
write_nic_word(dev, BcnItv, 100);
write_nic_word(dev, AtimWnd, 2);
-
- //PlatformEFIOWrite2Byte(dev, FEMR, 0xFFFF);
PlatformIOWrite2Byte(dev, FEMR, 0xFFFF);
-
write_nic_byte(dev, WPA_CONFIG, 0);
-
MacConfig_85BASIC(dev);
-
// Override the RFSW_CTRL (MAC offset 0x272-0x273), 2006.06.07, by rcnjko.
// BT_DEMO_BOARD type
PlatformIOWrite2Byte(dev, RFSW_CTRL, 0x569a);
-//by amy
-//#ifdef CONFIG_RTL818X_S
- // for jong required
-// PlatformIOWrite2Byte(dev, RFSW_CTRL, 0x9a56);
-//#endif
-//by amy
- //BT_QA_BOARD
- //PlatformIOWrite2Byte(dev, RFSW_CTRL, 0x9a56);
//-----------------------------------------------------------------------------
// Set up PHY related.
//-----------------------------------------------------------------------------
// Enable Config3.PARAM_En to revise AnaaParm.
write_nic_byte(dev, CR9346, 0xc0); // enable config register write
-//by amy
tmpu8 = read_nic_byte(dev, CONFIG3);
write_nic_byte(dev, CONFIG3, (tmpu8 |CONFIG3_PARM_En) );
-//by amy
// Turn on Analog power.
// Asked for by William, otherwise, MAC 3-wire can't work, 2006.06.27, by rcnjko.
write_nic_dword(dev, ANAPARAM2, ANAPARM2_ASIC_ON);
write_nic_dword(dev, ANAPARAM, ANAPARM_ASIC_ON);
-//by amy
write_nic_word(dev, ANAPARAM3, 0x0010);
-//by amy
write_nic_byte(dev, CONFIG3, tmpu8);
write_nic_byte(dev, CR9346, 0x00);
-//{by amy 080312 for led
// enable EEM0 and EEM1 in 9346CR
btCR9346 = read_nic_byte(dev, CR9346);
write_nic_byte(dev, CR9346, (btCR9346|0xC0) );
@@ -2474,7 +1696,6 @@ void rtl8185b_adapter_start(struct net_device *dev)
// B-cut RF Radio on/off 5e[3]=0
btPSR = read_nic_byte(dev, PSR);
write_nic_byte(dev, PSR, (btPSR | BIT3));
-//by amy 080312 for led}
// setup initial timing for RFE.
write_nic_word(dev, RFPinsOutput, 0x0480);
SetOutputEnableOfRfPins(dev);
@@ -2537,55 +1758,19 @@ void rtl8185b_adapter_start(struct net_device *dev)
InitWirelessMode = ieee->mode;
}
//by amy for power save
-// printk("initialize ENABLE_IPS\n");
priv->eRFPowerState = eRfOff;
priv->RfOffReason = 0;
{
- // u32 tmp2;
- // u32 tmp = jiffies;
MgntActSet_RF_State(dev, eRfOn, 0);
- // tmp2 = jiffies;
- // printk("rf on cost jiffies:%lx\n", (tmp2-tmp)*1000/HZ);
}
-// DrvIFIndicateCurrentPhyStatus(priv);
//
// If inactive power mode is enabled, disable rf while in disconnected state.
- // 2007.07.16, by shien chang.
//
if (priv->bInactivePs)
{
- // u32 tmp2;
- // u32 tmp = jiffies;
MgntActSet_RF_State(dev,eRfOff, RF_CHANGE_BY_IPS);
- // tmp2 = jiffies;
- // printk("rf off cost jiffies:%lx\n", (tmp2-tmp)*1000/HZ);
-
}
-// IPSEnter(dev);
//by amy for power save
-#ifdef TODO
- // Turn off RF if necessary. 2005.08.23, by rcnjko.
- // We shall turn off RF after setting CMDR, otherwise,
- // RF will be turnned on after we enable MAC Tx/Rx.
- if(Adapter->MgntInfo.RegRfOff == TRUE)
- {
- SetRFPowerState8185(Adapter, RF_OFF);
- }
- else
- {
- SetRFPowerState8185(Adapter, RF_ON);
- }
-#endif
-
-/* //these is equal with above TODO.
- write_nic_byte(dev, CR9346, 0xc0); // enable config register write
- write_nic_byte(dev, CONFIG3, read_nic_byte(dev, CONFIG3) | CONFIG3_PARM_En);
- RF_WriteReg(dev, 0x4, 0x9FF);
- write_nic_dword(dev, ANAPARAM2, ANAPARM2_ASIC_ON);
- write_nic_dword(dev, ANAPARAM, ANAPARM_ASIC_ON);
- write_nic_byte(dev, CONFIG3, (read_nic_byte(dev, CONFIG3)&(~CONFIG3_PARM_En)));
- write_nic_byte(dev, CR9346, 0x00);
-*/
ActSetWirelessMode8185(dev, (u8)(InitWirelessMode));
@@ -2594,14 +1779,11 @@ void rtl8185b_adapter_start(struct net_device *dev)
rtl8185b_irq_enable(dev);
netif_start_queue(dev);
-
}
-
void rtl8185b_rx_enable(struct net_device *dev)
{
u8 cmd;
- //u32 rxconf;
/* for now we accept data, management & ctl frame*/
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
@@ -2613,11 +1795,6 @@ void rtl8185b_rx_enable(struct net_device *dev)
priv->ReceiveConfig = priv->ReceiveConfig | RCR_AAP;
}
- /*if(priv->ieee80211->iw_mode == IW_MODE_MASTER){
- rxconf = rxconf | (1<<ACCEPT_ALLMAC_FRAME_SHIFT);
- rxconf = rxconf | (1<<RX_CHECK_BSSID_SHIFT);
- }*/
-
if(priv->ieee80211->iw_mode == IW_MODE_MONITOR){
priv->ReceiveConfig = priv->ReceiveConfig | RCR_ACF | RCR_APWRMGT | RCR_AICV;
}
@@ -2629,9 +1806,6 @@ void rtl8185b_rx_enable(struct net_device *dev)
fix_rx_fifo(dev);
-#ifdef DEBUG_RX
- DMESG("rxconf: %x %x",priv->ReceiveConfig ,read_nic_dword(dev,RCR));
-#endif
cmd=read_nic_byte(dev,CMD);
write_nic_byte(dev,CMD,cmd | (1<<CMD_RX_ENABLE_SHIFT));
@@ -2640,9 +1814,7 @@ void rtl8185b_rx_enable(struct net_device *dev)
void rtl8185b_tx_enable(struct net_device *dev)
{
u8 cmd;
- //u8 tx_agc_ctl;
u8 byte;
- //u32 txconf;
struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev);
write_nic_dword(dev, TCR, priv->TransmitConfig);
@@ -2652,21 +1824,7 @@ void rtl8185b_tx_enable(struct net_device *dev)
fix_tx_fifo(dev);
-#ifdef DEBUG_TX
- DMESG("txconf: %x %x",priv->TransmitConfig,read_nic_dword(dev,TCR));
-#endif
-
cmd=read_nic_byte(dev,CMD);
write_nic_byte(dev,CMD,cmd | (1<<CMD_TX_ENABLE_SHIFT));
-
- //write_nic_dword(dev,TX_CONF,txconf);
-
-
-/*
- rtl8180_set_mode(dev,EPROM_CMD_CONFIG);
- write_nic_byte(dev, TX_DMA_POLLING, priv->dma_poll_mask);
- rtl8180_set_mode(dev,EPROM_CMD_NORMAL);
- */
}
-
diff --git a/drivers/staging/rtl8192e/Makefile b/drivers/staging/rtl8192e/Makefile
index 5e4aa9546b5..e032c3e1e86 100644
--- a/drivers/staging/rtl8192e/Makefile
+++ b/drivers/staging/rtl8192e/Makefile
@@ -1,13 +1,15 @@
NIC_SELECT = RTL8192E
-
EXTRA_CFLAGS += -DRTL8192E
EXTRA_CFLAGS += -std=gnu89
EXTRA_CFLAGS += -O2
EXTRA_CFLAGS += -DTHOMAS_TURBO
EXTRA_CFLAGS += -DENABLE_DOT11D
-r8192_pci-objs := \
+EXTRA_CFLAGS += -DENABLE_IPS
+EXTRA_CFLAGS += -DENABLE_LPS
+
+r8192e_pci-objs := \
r8192E_core.o \
r8180_93cx6.o \
r8192E_wx.o \
@@ -31,4 +33,5 @@ r8192_pci-objs := \
ieee80211/ieee80211_crypt_ccmp.o \
ieee80211/ieee80211_crypt_wep.o
-obj-$(CONFIG_RTL8192E) += r8192_pci.o
+obj-$(CONFIG_RTL8192E) += r8192e_pci.o
+
diff --git a/drivers/staging/rtl8192e/dot11d.h b/drivers/staging/rtl8192e/dot11d.h
index 15b7a4ba37b..5b0e2dbc2bb 100644
--- a/drivers/staging/rtl8192e/dot11d.h
+++ b/drivers/staging/rtl8192e/dot11d.h
@@ -1,102 +1,96 @@
-#ifndef __INC_DOT11D_H
-#define __INC_DOT11D_H
+#ifndef INC_DOT11D_H
+#define INC_DOT11D_H
#ifdef ENABLE_DOT11D
#include "ieee80211.h"
-//#define ENABLE_DOT11D
-
-//#define DOT11D_MAX_CHNL_NUM 83
-
typedef struct _CHNL_TXPOWER_TRIPLE {
u8 FirstChnl;
u8 NumChnls;
u8 MaxTxPowerInDbm;
-}CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE;
+} CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE;
typedef enum _DOT11D_STATE {
DOT11D_STATE_NONE = 0,
DOT11D_STATE_LEARNED,
DOT11D_STATE_DONE,
-}DOT11D_STATE;
+} DOT11D_STATE;
+
+/**
+ * struct _RT_DOT11D_INFO
+ * @CountryIeLen: value greater than 0 if @CountryIeBuf contains
+ * valid country information element.
+ * @chanell_map: holds channel values
+ * 0 - invalid,
+ * 1 - valid (active scan),
+ * 2 - valid (passive scan)
+ * @CountryIeSrcAddr - Source AP of the country IE
+ */
typedef struct _RT_DOT11D_INFO {
- //DECLARE_RT_OBJECT(RT_DOT11D_INFO);
+ bool bEnabled;
- bool bEnabled; // dot11MultiDomainCapabilityEnabled
+ u16 CountryIeLen;
+ u8 CountryIeBuf[MAX_IE_LEN];
+ u8 CountryIeSrcAddr[6];
+ u8 CountryIeWatchdog;
- u16 CountryIeLen; // > 0 if CountryIeBuf[] contains valid country information element.
- u8 CountryIeBuf[MAX_IE_LEN];
- u8 CountryIeSrcAddr[6]; // Source AP of the country IE.
- u8 CountryIeWatchdog;
-
- u8 channel_map[MAX_CHANNEL_NUMBER+1]; //!!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan)
- //u8 ChnlListLen; // #Bytes valid in ChnlList[].
- //u8 ChnlList[DOT11D_MAX_CHNL_NUM];
- u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1];
+ u8 channel_map[MAX_CHANNEL_NUMBER+1];
+ u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1];
DOT11D_STATE State;
-}RT_DOT11D_INFO, *PRT_DOT11D_INFO;
-#define eqMacAddr(a,b) ( ((a)[0]==(b)[0] && (a)[1]==(b)[1] && (a)[2]==(b)[2] && (a)[3]==(b)[3] && (a)[4]==(b)[4] && (a)[5]==(b)[5]) ? 1:0 )
-#define cpMacAddr(des,src) ((des)[0]=(src)[0],(des)[1]=(src)[1],(des)[2]=(src)[2],(des)[3]=(src)[3],(des)[4]=(src)[4],(des)[5]=(src)[5])
-#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo))
+} RT_DOT11D_INFO, *PRT_DOT11D_INFO;
+
+#define eqMacAddr(a, b) (((a)[0] == (b)[0] && (a)[1] == (b)[1] && (a)[2] == \
+ (b)[2] && (a)[3] == (b)[3] && (a)[4] == (b)[4] && \
+ (a)[5] == (b)[5]) ? 1 : 0)
+
+#define cpMacAddr(des, src) ((des)[0] = (src)[0], (des)[1] = (src)[1], \
+ (des)[2] = (src)[2], (des)[3] = (src)[3], \
+ (des)[4] = (src)[4], (des)[5] = (src)[5])
+
+#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO) \
+ ((__pIeeeDev)->pDot11dInfo))
#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled
-#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0)
+#define IS_COUNTRY_IE_VALID(__pIeeeDev) \
+ (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0)
-#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
-#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
+#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) \
+ eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
+
+#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) \
+ cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \
- (((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \
- FALSE : \
- (!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length)))
+ (((__Ie).Length == 0 || (__Ie).Length != \
+ GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? FALSE : \
+ (!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, \
+ (__Ie).Octet, (__Ie).Length)))
#define CIE_WATCHDOG_TH 1
#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog
#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0
#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev)
-#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
-
-
-void
-Dot11d_Init(
- struct ieee80211_device *dev
- );
-
-void
-Dot11d_Reset(
- struct ieee80211_device *dev
- );
-
-void
-Dot11d_UpdateCountryIe(
- struct ieee80211_device *dev,
- u8 * pTaddr,
- u16 CoutryIeLen,
- u8 * pCoutryIe
- );
-
-u8
-DOT11D_GetMaxTxPwrInDbm(
- struct ieee80211_device *dev,
- u8 Channel
- );
-
-void
-DOT11D_ScanComplete(
- struct ieee80211_device * dev
- );
-
-int IsLegalChannel(
- struct ieee80211_device * dev,
- u8 channel
-);
-
-int ToLegalChannel(
- struct ieee80211_device * dev,
- u8 channel
-);
-#endif //ENABLE_DOT11D
-#endif // #ifndef __INC_DOT11D_H
+#define IS_DOT11D_STATE_DONE(__pIeeeDev) \
+ (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
+
+
+void Dot11d_Init(struct ieee80211_device *dev);
+
+void Dot11d_Reset(struct ieee80211_device *dev);
+
+void Dot11d_UpdateCountryIe(struct ieee80211_device *dev, u8 *pTaddr,
+ u16 CoutryIeLen, u8 *pCoutryIe);
+
+u8 DOT11D_GetMaxTxPwrInDbm(struct ieee80211_device *dev, u8 channel);
+
+void DOT11D_ScanComplete(struct ieee80211_device *dev);
+
+int IsLegalChannel(struct ieee80211_device *dev, u8 channel);
+
+int ToLegalChannel(struct ieee80211_device *dev, u8 channel);
+
+#endif /* ENABLE_DOT11D */
+#endif /* INC_DOT11D_H */
diff --git a/drivers/staging/rtl8192e/ieee80211.h b/drivers/staging/rtl8192e/ieee80211.h
index 3ba9e9e90bd..c39249eb54b 100644
--- a/drivers/staging/rtl8192e/ieee80211.h
+++ b/drivers/staging/rtl8192e/ieee80211.h
@@ -547,9 +547,6 @@ do { if (ieee80211_debug_level & (level)) \
/* debug macros not dependent on CONFIG_IEEE80211_DEBUG */
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]
-
/*
* To use the debug system;
*
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211.h b/drivers/staging/rtl8192e/ieee80211/ieee80211.h
index aa76390487b..1f613a28152 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211.h
@@ -35,6 +35,7 @@
#endif
#include <linux/timer.h>
#include <linux/sched.h>
+#include <linux/semaphore.h>
#include <linux/delay.h>
#include <linux/wireless.h>
@@ -180,6 +181,8 @@ typedef struct cb_desc {
u8 DrvAggrNum;
u16 pkt_size;
u8 reserved12;
+
+ u8 bdhcp;
}cb_desc, *pcb_desc;
/*--------------------------Define -------------------------------------------*/
@@ -615,9 +618,6 @@ do { if (ieee80211_debug_level & (level)) \
/* debug macros not dependent on CONFIG_IEEE80211_DEBUG */
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]
-
/*
* To use the debug system;
*
@@ -743,6 +743,8 @@ struct ieee80211_snap_hdr {
#define WLAN_FC_GET_VERS(fc) ((fc) & IEEE80211_FCTL_VERS)
#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE)
#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE)
+#define WLAN_FC_MORE_DATA(fc) ((fc) & IEEE80211_FCTL_MOREDATA)
+
#define WLAN_FC_GET_FRAMETYPE(fc) ((fc) & IEEE80211_FCTL_FRAMETYPE)
#define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG)
@@ -1055,7 +1057,7 @@ struct ieee80211_device;
#define SEC_ALG_NONE 0
#define SEC_ALG_WEP 1
#define SEC_ALG_TKIP 2
-#define SEC_ALG_CCMP 3
+#define SEC_ALG_CCMP 4
#define WEP_KEYS 4
#define WEP_KEY_LEN 13
@@ -1124,6 +1126,14 @@ enum ieee80211_mfie {
/* Minimal header; can be used for passing 802.11 frames with sufficient
* information to determine what type of underlying data type is actually
* stored in the data. */
+ struct ieee80211_pspoll_hdr {
+ __le16 frame_ctl;
+ __le16 aid;
+ u8 bssid[ETH_ALEN];
+ u8 ta[ETH_ALEN];
+ //u8 payload[0];
+} __attribute__ ((packed));
+
struct ieee80211_hdr {
__le16 frame_ctl;
__le16 duration_id;
@@ -1660,6 +1670,7 @@ struct ieee80211_network {
bool ralink_cap_exist;
bool atheros_cap_exist;
bool cisco_cap_exist;
+ bool marvell_cap_exist;
bool unknown_cap_exist;
// u8 berp_info;
bool berp_info_valid;
@@ -1865,6 +1876,19 @@ typedef struct _RT_POWER_SAVE_CONTROL
// Leisre Poswer Save : Disable RF if connected but traffic is not busy
//
bool bLeisurePs;
+ u32 PowerProfile;
+ u8 LpsIdleCount;
+ u8 RegMaxLPSAwakeIntvl;
+ u8 LPSAwakeIntvl;
+
+ u32 CurPsLevel;
+ u32 RegRfPsLevel;
+
+ bool bFwCtrlLPS;
+ u8 FWCtrlPSMode;
+
+ bool LinkReqInIPSRFOffPgs;
+ bool BufConnectinfoBefore;
}RT_POWER_SAVE_CONTROL,*PRT_POWER_SAVE_CONTROL;
@@ -1905,14 +1929,121 @@ typedef struct _RT_LINK_DETECT_T{
u32 NumTxOkInPeriod;
u32 NumRxOkInPeriod;
+ u32 NumRxUnicastOkInPeriod;
bool bBusyTraffic;
}RT_LINK_DETECT_T, *PRT_LINK_DETECT_T;
+//added by amy 090330
+typedef enum _HW_VARIABLES{
+ HW_VAR_ETHER_ADDR,
+ HW_VAR_MULTICAST_REG,
+ HW_VAR_BASIC_RATE,
+ HW_VAR_BSSID,
+ HW_VAR_MEDIA_STATUS,
+ HW_VAR_SECURITY_CONF,
+ HW_VAR_BEACON_INTERVAL,
+ HW_VAR_ATIM_WINDOW,
+ HW_VAR_LISTEN_INTERVAL,
+ HW_VAR_CS_COUNTER,
+ HW_VAR_DEFAULTKEY0,
+ HW_VAR_DEFAULTKEY1,
+ HW_VAR_DEFAULTKEY2,
+ HW_VAR_DEFAULTKEY3,
+ HW_VAR_SIFS,
+ HW_VAR_DIFS,
+ HW_VAR_EIFS,
+ HW_VAR_SLOT_TIME,
+ HW_VAR_ACK_PREAMBLE,
+ HW_VAR_CW_CONFIG,
+ HW_VAR_CW_VALUES,
+ HW_VAR_RATE_FALLBACK_CONTROL,
+ HW_VAR_CONTENTION_WINDOW,
+ HW_VAR_RETRY_COUNT,
+ HW_VAR_TR_SWITCH,
+ HW_VAR_COMMAND, // For Command Register, Annie, 2006-04-07.
+ HW_VAR_WPA_CONFIG, //2004/08/23, kcwu, for 8187 Security config
+ HW_VAR_AMPDU_MIN_SPACE, // The spacing between sub-frame. Roger, 2008.07.04.
+ HW_VAR_SHORTGI_DENSITY, // The density for shortGI. Roger, 2008.07.04.
+ HW_VAR_AMPDU_FACTOR,
+ HW_VAR_MCS_RATE_AVAILABLE,
+ HW_VAR_AC_PARAM, // For AC Parameters, 2005.12.01, by rcnjko.
+ HW_VAR_ACM_CTRL, // For ACM Control, Annie, 2005-12-13.
+ HW_VAR_DIS_Req_Qsize, // For DIS_Reg_Qsize, Joseph
+ HW_VAR_CCX_CHNL_LOAD, // For CCX 2 channel load request, 2006.05.04.
+ HW_VAR_CCX_NOISE_HISTOGRAM, // For CCX 2 noise histogram request, 2006.05.04.
+ HW_VAR_CCX_CLM_NHM, // For CCX 2 parallel channel load request and noise histogram request, 2006.05.12.
+ HW_VAR_TxOPLimit, // For turbo mode related settings, added by Roger, 2006.12.07
+ HW_VAR_TURBO_MODE, // For turbo mode related settings, added by Roger, 2006.12.15.
+ HW_VAR_RF_STATE, // For change or query RF power state, 061214, rcnjko.
+ HW_VAR_RF_OFF_BY_HW, // For UI to query if external HW signal disable RF, 061229, rcnjko.
+ HW_VAR_BUS_SPEED, // In unit of bps. 2006.07.03, by rcnjko.
+ HW_VAR_SET_DEV_POWER, // Set to low power, added by LanHsin, 2007.
+
+ //1!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ //1Attention Please!!!<11n or 8190 specific code should be put below this line>
+ //1!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ HW_VAR_RCR, //for RCR, David 2006,05,11
+ HW_VAR_RATR_0,
+ HW_VAR_RRSR,
+ HW_VAR_CPU_RST,
+ HW_VAR_CECHK_BSSID,
+ HW_VAR_LBK_MODE, // Set lookback mode, 2008.06.11. added by Roger.
+ // Set HW related setting for 11N AES bug.
+ HW_VAR_AES_11N_FIX,
+ // Set Usb Rx Aggregation
+ HW_VAR_USB_RX_AGGR,
+ HW_VAR_USER_CONTROL_TURBO_MODE,
+ HW_VAR_RETRY_LIMIT,
+#ifndef _RTL8192_EXT_PATCH_
+ HW_VAR_INIT_TX_RATE, //Get Current Tx rate register. 2008.12.10. Added by tynli
+#endif
+ HW_VAR_TX_RATE_REG, //Get Current Tx rate register. 2008.12.10. Added by tynli
+ HW_VAR_EFUSE_USAGE, //Get current EFUSE utilization. 2008.12.19. Added by Roger.
+ HW_VAR_EFUSE_BYTES,
+ HW_VAR_AUTOLOAD_STATUS, //Get current autoload status, 0: autoload success, 1: autoload fail. 2008.12.19. Added by Roger.
+ HW_VAR_RF_2R_DISABLE, // 2R disable
+ HW_VAR_SET_RPWM,
+ HW_VAR_H2C_FW_PWRMODE, // For setting FW related H2C cmd structure. by tynli. 2009.2.18
+ HW_VAR_H2C_FW_JOINBSSRPT, // For setting FW related H2C cmd structure. by tynli. 2009.2.18
+ HW_VAR_1X1_RECV_COMBINE, // For 1T2R but only 1SS, Add by hpfan 2009.04.16 hpfan
+ HW_VAR_STOP_SEND_BEACON,
+ HW_VAR_TSF_TIMER, // Read from TSF register to get the current TSF timer, by Bruce, 2009-07-22.
+ HW_VAR_IO_CMD,
+ HW_VAR_HANDLE_FW_C2H, //Added by tynli. For handling FW C2H command. 2009.10.07.
+ HW_VAR_DL_FW_RSVD_PAGE, //Added by tynli. Download the packets that FW will use to RSVD page. 2009.10.14.
+ HW_VAR_AID, //Added by tynli.
+ HW_VAR_HW_SEQ_ENABLE, //Added by tynli. 2009.10.20.
+ HW_VAR_UPDATE_TSF, //Added by tynli. 2009.10.22. For Hw count TBTT time.
+ HW_VAR_BCN_VALID, //Added by tynli.
+ HW_VAR_FWLPS_RF_ON //Added by tynli. 2009.11.09. For checking if Fw finishs RF on sequence.
+}HW_VARIABLES;
+
+#define RT_CHECK_FOR_HANG_PERIOD 2
struct ieee80211_device {
struct net_device *dev;
struct ieee80211_security sec;
+ bool need_sw_enc;
+#ifdef ENABLE_LPS
+ bool bAwakePktSent;
+ u8 LPSDelayCnt;
+ bool bIsAggregateFrame;
+ bool polling;
+ void (*LeisurePSLeave)(struct net_device *dev);
+#endif
+
+#ifdef ENABLE_IPS
+ bool proto_stoppping;
+ bool wx_set_enc;
+ struct semaphore ips_sem;
+ struct work_struct ips_leave_wq;
+ void (*ieee80211_ips_leave_wq) (struct net_device *dev);
+ void (*ieee80211_ips_leave)(struct net_device *dev);
+#endif
+ void (*SetHwRegHandler)(struct net_device *dev,u8 variable,u8* val);
+ u8 (*rtllib_ap_sec_type)(struct ieee80211_device *ieee);
+
//hw security related
// u8 hwsec_support; //support?
u8 hwsec_active; //hw security active.
@@ -2319,7 +2450,7 @@ struct ieee80211_device {
* stop_send_bacons is NOT guaranteed to be called only
* after start_send_beacons.
*/
- void (*start_send_beacons) (struct net_device *dev,u16 tx_rate);
+ void (*start_send_beacons) (struct net_device *dev);
void (*stop_send_beacons) (struct net_device *dev);
/* power save mode related */
@@ -2373,6 +2504,19 @@ struct ieee80211_device {
u8 priv[0];
};
+#define RT_RF_OFF_LEVL_ASPM BIT0 // PCI ASPM
+#define RT_RF_OFF_LEVL_CLK_REQ BIT1 // PCI clock request
+#define RT_RF_OFF_LEVL_PCI_D3 BIT2 // PCI D3 mode
+#define RT_RF_OFF_LEVL_HALT_NIC BIT3 // NIC halt, re-initialize hw parameters
+#define RT_RF_OFF_LEVL_FREE_FW BIT4 // FW free, re-download the FW
+#define RT_RF_OFF_LEVL_FW_32K BIT5 // FW in 32k
+#define RT_RF_PS_LEVEL_ALWAYS_ASPM BIT6 // Always enable ASPM and Clock Req in initialization.
+#define RT_RF_LPS_DISALBE_2R BIT30 // When LPS is on, disable 2R if no packet is received or transmittd.
+#define RT_RF_LPS_LEVEL_ASPM BIT31 // LPS with ASPM
+#define RT_IN_PS_LEVEL(pPSC, _PS_FLAG) ((pPSC->CurPsLevel & _PS_FLAG) ? true : false)
+#define RT_CLEAR_PS_LEVEL(pPSC, _PS_FLAG) (pPSC->CurPsLevel &= (~(_PS_FLAG)))
+#define RT_SET_PS_LEVEL(pPSC, _PS_FLAG) (pPSC->CurPsLevel |= _PS_FLAG)
+
#define IEEE_A (1<<0)
#define IEEE_B (1<<1)
#define IEEE_G (1<<2)
@@ -2609,9 +2753,9 @@ extern void ieee80211_stop_scan(struct ieee80211_device *ieee);
extern void ieee80211_start_scan_syncro(struct ieee80211_device *ieee);
extern void ieee80211_check_all_nets(struct ieee80211_device *ieee);
extern void ieee80211_start_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_stop_protocol(struct ieee80211_device *ieee);
+extern void ieee80211_stop_protocol(struct ieee80211_device *ieee,u8 shutdown);
extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee);
+extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee,u8 shutdown);
extern void ieee80211_reset_queue(struct ieee80211_device *ieee);
extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee);
extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee);
@@ -2798,5 +2942,7 @@ extern int ieee80211_parse_info_param(struct ieee80211_device *ieee,
struct ieee80211_rx_stats *stats);
void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_rxb** prxbIndicateArray,u8 index);
+void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr);
+void ieee80211_sta_ps_send_pspoll_frame(struct ieee80211_device *ieee);
#define RT_ASOC_RETRY_LIMIT 5
#endif /* IEEE80211_H */
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c
index b1c54932da3..b3c9bf4b4ea 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c
@@ -225,7 +225,7 @@ out:
}
-void __exit ieee80211_crypto_deinit(void)
+void ieee80211_crypto_deinit(void)
{
struct list_head *ptr, *n;
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c
index ab871b360b5..1776f7e69bf 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_ccmp.c
@@ -331,7 +331,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (!(keyidx & (1 << 5))) {
if (net_ratelimit()) {
printk(KERN_DEBUG "CCMP: received packet without ExtIV"
- " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
+ " flag from %pM\n", hdr->addr2);
}
key->dot11RSNAStatsCCMPFormatErrors++;
return -2;
@@ -344,9 +344,9 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
}
if (!key->key_set) {
if (net_ratelimit()) {
- printk(KERN_DEBUG "CCMP: received packet from " MAC_FMT
+ printk(KERN_DEBUG "CCMP: received packet from %pM"
" with keyid=%d that does not have a configured"
- " key\n", MAC_ARG(hdr->addr2), keyidx);
+ " key\n", hdr->addr2, keyidx);
}
return -3;
}
@@ -361,11 +361,9 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
if (net_ratelimit()) {
- printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT
- " previous PN %02x%02x%02x%02x%02x%02x "
- "received PN %02x%02x%02x%02x%02x%02x\n",
- MAC_ARG(hdr->addr2), MAC_ARG(key->rx_pn),
- MAC_ARG(pn));
+ //printk(KERN_DEBUG "CCMP: replay detected: STA=%pM"
+ // " previous PN %pm received PN %pm\n",
+ // hdr->addr2, key->rx_pn, pn);
}
key->dot11RSNAStatsCCMPReplays++;
return -4;
@@ -402,7 +400,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
if (net_ratelimit()) {
printk(KERN_DEBUG "CCMP: decrypt failed: STA="
- MAC_FMT "\n", MAC_ARG(hdr->addr2));
+ "%pM\n", hdr->addr2);
}
key->dot11RSNAStatsCCMPDecryptErrors++;
return -5;
@@ -477,12 +475,19 @@ static int ieee80211_ccmp_get_key(void *key, int len, u8 *seq, void *priv)
static char * ieee80211_ccmp_print_stats(char *p, void *priv)
{
struct ieee80211_ccmp_data *ccmp = priv;
- p += sprintf(p, "key[%d] alg=CCMP key_set=%d "
- "tx_pn=%02x%02x%02x%02x%02x%02x "
- "rx_pn=%02x%02x%02x%02x%02x%02x "
- "format_errors=%d replays=%d decrypt_errors=%d\n",
- ccmp->key_idx, ccmp->key_set,
- MAC_ARG(ccmp->tx_pn), MAC_ARG(ccmp->rx_pn),
+ int i;
+
+ p += sprintf(p, "key[%d] alg=CCMP key_set=%d tx_pn=",
+ ccmp->key_idx, ccmp->key_set);
+
+ for (i = 0; i < ARRAY_SIZE(ccmp->tx_pn); i++)
+ p += sprintf(p, "%02x", ccmp->tx_pn[i]);
+
+ sprintf(p, " rx_pn=");
+ for (i = 0; i < ARRAY_SIZE(ccmp->rx_pn); i++)
+ p += sprintf(p, "%02x", ccmp->tx_pn[i]);
+
+ p += sprintf(p, " format_errors=%d replays=%d decrypt_errors=%d\n",
ccmp->dot11RSNAStatsCCMPFormatErrors,
ccmp->dot11RSNAStatsCCMPReplays,
ccmp->dot11RSNAStatsCCMPDecryptErrors);
@@ -519,7 +524,7 @@ int __init ieee80211_crypto_ccmp_init(void)
}
-void __exit ieee80211_crypto_ccmp_exit(void)
+void ieee80211_crypto_ccmp_exit(void)
{
ieee80211_unregister_crypto_ops(&ieee80211_crypt_ccmp);
}
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c
index 7a1797e6cbe..03cb21eb065 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt_tkip.c
@@ -520,7 +520,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (!(keyidx & (1 << 5))) {
if (net_ratelimit()) {
printk(KERN_DEBUG "TKIP: received packet without ExtIV"
- " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
+ " flag from %pM\n", hdr->addr2);
}
return -2;
}
@@ -532,9 +532,9 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
}
if (!tkey->key_set) {
if (net_ratelimit()) {
- printk(KERN_DEBUG "TKIP: received packet from " MAC_FMT
+ printk(KERN_DEBUG "TKIP: received packet from %pM"
" with keyid=%d that does not have a configured"
- " key\n", MAC_ARG(hdr->addr2), keyidx);
+ " key\n", hdr->addr2, keyidx);
}
return -3;
}
@@ -547,9 +547,9 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (iv32 < tkey->rx_iv32 ||
(iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
if (net_ratelimit()) {
- printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT
+ printk(KERN_DEBUG "TKIP: replay detected: STA=%pM"
" previous TSC %08x%04x received TSC "
- "%08x%04x\n", MAC_ARG(hdr->addr2),
+ "%08x%04x\n", hdr->addr2,
tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
}
tkey->dot11RSNAStatsTKIPReplays++;
@@ -582,8 +582,8 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
if (net_ratelimit()) {
printk(KERN_DEBUG ": TKIP: failed to decrypt "
- "received packet from " MAC_FMT "\n",
- MAC_ARG(hdr->addr2));
+ "received packet from %pM\n",
+ hdr->addr2);
}
return -7;
}
@@ -606,8 +606,9 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
tkey->rx_phase1_done = 0;
}
if (net_ratelimit()) {
- printk(KERN_DEBUG "TKIP: ICV error detected: STA="
- MAC_FMT "\n", MAC_ARG(hdr->addr2));
+ printk(KERN_DEBUG
+ "TKIP: ICV error detected: STA=%pM\n",
+ hdr->addr2);
}
tkey->dot11RSNAStatsTKIPICVErrors++;
return -5;
@@ -816,8 +817,8 @@ static void ieee80211_michael_mic_failure(struct net_device *dev,
/* TODO: needed parameters: count, keyid, key type, TSC */
sprintf(buf, "MLME-MICHAELMICFAILURE.indication(keyid=%d %scast addr="
- MAC_FMT ")", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
- MAC_ARG(hdr->addr2));
+ "%pM)", keyidx, hdr->addr1[0] & 0x01 ? "broad" : "uni",
+ hdr->addr2);
memset(&wrqu, 0, sizeof(wrqu));
wrqu.data.length = strlen(buf);
wireless_send_event(dev, IWEVCUSTOM, &wrqu, buf);
@@ -862,8 +863,8 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
struct ieee80211_hdr_4addr *hdr;
hdr = (struct ieee80211_hdr_4addr *) skb->data;
printk(KERN_DEBUG "%s: Michael MIC verification failed for "
- "MSDU from " MAC_FMT " keyidx=%d\n",
- skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2),
+ "MSDU from %pM keyidx=%d\n",
+ skb->dev ? skb->dev->name : "N/A", hdr->addr2,
keyidx);
if (skb->dev)
ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);
@@ -1011,7 +1012,7 @@ int __init ieee80211_crypto_tkip_init(void)
}
-void __exit ieee80211_crypto_tkip_exit(void)
+void ieee80211_crypto_tkip_exit(void)
{
ieee80211_unregister_crypto_ops(&ieee80211_crypt_tkip);
}
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
index 06d91715143..ce265ae5fe1 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c
@@ -312,6 +312,17 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
if (skb->len < 24)
return 0;
+#if 1
+ if (ieee->hwsec_active)
+ {
+ cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE);
+ tcb_desc->bHwSec = 1;
+
+ if(ieee->need_sw_enc)
+ tcb_desc->bHwSec = 0;
+ }
+#endif
+
hdr = (struct ieee80211_hdr_4addr *) skb->data;
fc = le16_to_cpu(hdr->frame_ctl);
@@ -366,8 +377,8 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
strcmp(crypt->ops->name, "TKIP") == 0) {
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
- "received packet from " MAC_FMT "\n",
- ieee->dev->name, MAC_ARG(hdr->addr2));
+ "received packet from %pM\n",
+ ieee->dev->name, hdr->addr2);
}
return -1;
}
@@ -378,8 +389,8 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
atomic_dec(&crypt->refcnt);
if (res < 0) {
IEEE80211_DEBUG_DROP(
- "decryption failed (SA=" MAC_FMT
- ") res=%d\n", MAC_ARG(hdr->addr2), res);
+ "decryption failed (SA=%pM"
+ ") res=%d\n", hdr->addr2, res);
if (res == -2)
IEEE80211_DEBUG_DROP("Decryption failed ICV "
"mismatch (key %d)\n",
@@ -406,6 +417,10 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device* ieee, struct sk_buff *s
{
cb_desc *tcb_desc = (cb_desc *)(skb->cb+ MAX_DEV_ADDR_SIZE);
tcb_desc->bHwSec = 1;
+
+ if(ieee->need_sw_enc)
+ tcb_desc->bHwSec = 0;
+
}
hdr = (struct ieee80211_hdr_4addr *) skb->data;
@@ -416,8 +431,8 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device* ieee, struct sk_buff *s
atomic_dec(&crypt->refcnt);
if (res < 0) {
printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
- " (SA=" MAC_FMT " keyidx=%d)\n",
- ieee->dev->name, MAC_ARG(hdr->addr2), keyidx);
+ " (SA=%pM keyidx=%d)\n",
+ ieee->dev->name, hdr->addr2, keyidx);
return -1;
}
@@ -799,7 +814,7 @@ void RxReorderIndicatePacket( struct ieee80211_device *ieee,
#endif
}
-u8 parse_subframe(struct sk_buff *skb,
+u8 parse_subframe(struct ieee80211_device* ieee,struct sk_buff *skb,
struct ieee80211_rx_stats *rx_stats,
struct ieee80211_rxb *rxb,u8* src,u8* dst)
{
@@ -839,6 +854,7 @@ u8 parse_subframe(struct sk_buff *skb,
}
skb_pull(skb, LLCOffset);
+ ieee->bIsAggregateFrame = bIsAggregateFrame;//added by amy for Leisure PS
if(!bIsAggregateFrame) {
rxb->nr_subframes = 1;
@@ -940,6 +956,7 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
u8 TID = 0;
u16 SeqNum = 0;
PRX_TS_RECORD pTS = NULL;
+ bool unicast_packet = false;
//bool bIsAggregateFrame = false;
//added by amy for reorder
#ifdef NOT_YET
@@ -1045,8 +1062,8 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
* frames silently instead of filling system log with
* these reports. */
IEEE80211_DEBUG_DROP("Decryption failed (not set)"
- " (SA=" MAC_FMT ")\n",
- MAC_ARG(hdr->addr2));
+ " (SA=%pM)\n",
+ hdr->addr2);
ieee->ieee_stats.rx_discards_undecryptable++;
goto rx_dropped;
}
@@ -1114,8 +1131,8 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
(keyidx = hostap_rx_frame_decrypt(ieee, skb, crypt)) < 0)
{
printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth "
- "from " MAC_FMT "\n", dev->name,
- MAC_ARG(hdr->addr2));
+ "from %pM\n", dev->name,
+ hdr->addr2);
/* TODO: could inform hostapd about this so that it
* could send auth failure report */
goto rx_dropped;
@@ -1215,6 +1232,24 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN))
goto rx_dropped;
+#ifdef ENABLE_LPS
+ if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->sta_sleep == 1)
+ && (ieee->polling)) {
+ if (WLAN_FC_MORE_DATA(fc)) {
+ /* more data bit is set, let's request a new frame from the AP */
+ ieee80211_sta_ps_send_pspoll_frame(ieee);
+ } else {
+ ieee->polling = false;
+ }
+ }
+#endif
+
+ ieee->need_sw_enc = 0;
+
+ if((!rx_stats->Decrypted)){
+ ieee->need_sw_enc = 1;
+ }
+
/* skb: hdr + (possibly fragmented, possibly encrypted) payload */
if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) &&
@@ -1296,6 +1331,9 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
ieee->LinkDetectInfo.NumRxOkInPeriod++;
hdr = (struct ieee80211_hdr_4addr *) skb->data;
+ if((!is_multicast_ether_addr(hdr->addr1)) && (!is_broadcast_ether_addr(hdr->addr1)))
+ unicast_packet = true;
+
if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep) {
if (/*ieee->ieee802_1x &&*/
ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
@@ -1311,8 +1349,8 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
} else {
IEEE80211_DEBUG_DROP(
"encryption configured, but RX "
- "frame not encrypted (SA=" MAC_FMT ")\n",
- MAC_ARG(hdr->addr2));
+ "frame not encrypted (SA=%pM)\n",
+ hdr->addr2);
goto rx_dropped;
}
}
@@ -1331,9 +1369,9 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
!ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
IEEE80211_DEBUG_DROP(
"dropped unencrypted RX data "
- "frame from " MAC_FMT
+ "frame from %pM"
" (drop_unencrypted=1)\n",
- MAC_ARG(hdr->addr2));
+ hdr->addr2);
goto rx_dropped;
}
/*
@@ -1367,7 +1405,7 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
}
/* to parse amsdu packets */
/* qos data packets & reserved bit is 1 */
- if(parse_subframe(skb,rx_stats,rxb,src,dst) == 0) {
+ if(parse_subframe(ieee, skb,rx_stats,rxb,src,dst) == 0) {
/* only to free rxb, and not submit the packets to upper layer */
for(i =0; i < rxb->nr_subframes; i++) {
dev_kfree_skb(rxb->subframes[i]);
@@ -1377,6 +1415,32 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
goto rx_dropped;
}
+#ifdef ENABLE_LPS
+ if(unicast_packet)
+ {
+ if (type == IEEE80211_FTYPE_DATA)
+ {
+
+ if(ieee->bIsAggregateFrame)
+ ieee->LinkDetectInfo.NumRxUnicastOkInPeriod+=rxb->nr_subframes;
+ else
+ ieee->LinkDetectInfo.NumRxUnicastOkInPeriod++;
+
+ // 2009.03.03 Leave DC mode immediately when detect high traffic
+ // DbgPrint("ending Seq %d\n", Frame_SeqNum(pduOS));
+ if((ieee->state == IEEE80211_LINKED) /*&& !MgntInitAdapterInProgress(pMgntInfo)*/)
+ {
+ if( ((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod +ieee->LinkDetectInfo.NumTxOkInPeriod) > 8 ) ||
+ (ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2) )
+ {
+ if(ieee->LeisurePSLeave)
+ ieee->LeisurePSLeave(dev);
+ }
+ }
+ }
+ }
+#endif
+
ieee->last_rx_ps_time = jiffies;
//added by amy for reorder
if(ieee->pHTInfo->bCurRxReorderEnable == false ||pTS == NULL){
@@ -2013,12 +2077,22 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee,
info_element->data[1] == 0x13 &&
info_element->data[2] == 0x74))
{
- printk("========>%s(): athros AP is exist\n",__FUNCTION__);
+ //printk("========>%s(): athros AP is exist\n",__FUNCTION__);
network->atheros_cap_exist = true;
}
else
network->atheros_cap_exist = false;
+ if ((info_element->len >= 3 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0x50 &&
+ info_element->data[2] == 0x43) )
+ {
+ network->marvell_cap_exist = true;
+ //printk("========>%s(): marvel AP is exist\n",__FUNCTION__);
+ }
+
+
if(info_element->len >= 3 &&
info_element->data[0] == 0x00 &&
info_element->data[1] == 0x40 &&
@@ -2219,7 +2293,8 @@ int ieee80211_parse_info_param(struct ieee80211_device *ieee,
}
if(!network->atheros_cap_exist && !network->broadcom_cap_exist &&
- !network->cisco_cap_exist && !network->ralink_cap_exist && !network->bssht.bdRT2RTAggregation)
+ !network->cisco_cap_exist && !network->ralink_cap_exist && !network->bssht.bdRT2RTAggregation &&
+ !network->marvell_cap_exist)
{
network->unknown_cap_exist = true;
}
@@ -2333,6 +2408,7 @@ static inline int ieee80211_network_init(
network->broadcom_cap_exist = false;
network->ralink_cap_exist = false;
network->atheros_cap_exist = false;
+ network->marvell_cap_exist = false;
network->cisco_cap_exist = false;
network->unknown_cap_exist = false;
#ifdef THOMAS_TURBO
@@ -2369,11 +2445,11 @@ static inline int ieee80211_network_init(
}
if (network->mode == 0) {
- IEEE80211_DEBUG_SCAN("Filtered out '%s (" MAC_FMT ")' "
+ IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' "
"network.\n",
escape_essid(network->ssid,
network->ssid_len),
- MAC_ARG(network->bssid));
+ network->bssid);
return 1;
}
@@ -2463,6 +2539,7 @@ static inline void update_network(struct ieee80211_network *dst,
dst->broadcom_cap_exist = src->broadcom_cap_exist;
dst->ralink_cap_exist = src->ralink_cap_exist;
dst->atheros_cap_exist = src->atheros_cap_exist;
+ dst->marvell_cap_exist = src->marvell_cap_exist;
dst->cisco_cap_exist = src->cisco_cap_exist;
dst->unknown_cap_exist = src->unknown_cap_exist;
memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
@@ -2557,9 +2634,9 @@ static inline void ieee80211_process_probe_response(
memset(&network, 0, sizeof(struct ieee80211_network));
IEEE80211_DEBUG_SCAN(
- "'%s' (" MAC_FMT "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
+ "'%s' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
escape_essid(info_element->data, info_element->len),
- MAC_ARG(beacon->header.addr3),
+ beacon->header.addr3,
(beacon->capability & (1<<0xf)) ? '1' : '0',
(beacon->capability & (1<<0xe)) ? '1' : '0',
(beacon->capability & (1<<0xd)) ? '1' : '0',
@@ -2578,10 +2655,10 @@ static inline void ieee80211_process_probe_response(
(beacon->capability & (1<<0x0)) ? '1' : '0');
if (ieee80211_network_init(ieee, beacon, &network, stats)) {
- IEEE80211_DEBUG_SCAN("Dropped '%s' (" MAC_FMT ") via %s.\n",
+ IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
escape_essid(info_element->data,
info_element->len),
- MAC_ARG(beacon->header.addr3),
+ beacon->header.addr3,
WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
IEEE80211_STYPE_PROBE_RESP ?
"PROBE RESPONSE" : "BEACON");
@@ -2692,11 +2769,11 @@ static inline void ieee80211_process_probe_response(
/* If there are no more slots, expire the oldest */
list_del(&oldest->list);
target = oldest;
- IEEE80211_DEBUG_SCAN("Expired '%s' (" MAC_FMT ") from "
+ IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from "
"network list.\n",
escape_essid(target->ssid,
target->ssid_len),
- MAC_ARG(target->bssid));
+ target->bssid);
} else {
/* Otherwise just pull from the free list */
target = list_entry(ieee->network_free_list.next,
@@ -2706,10 +2783,10 @@ static inline void ieee80211_process_probe_response(
#ifdef CONFIG_IEEE80211_DEBUG
- IEEE80211_DEBUG_SCAN("Adding '%s' (" MAC_FMT ") via %s.\n",
+ IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
escape_essid(network.ssid,
network.ssid_len),
- MAC_ARG(network.bssid),
+ network.bssid,
WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
IEEE80211_STYPE_PROBE_RESP ?
"PROBE RESPONSE" : "BEACON");
@@ -2719,10 +2796,10 @@ static inline void ieee80211_process_probe_response(
if(ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)
ieee80211_softmac_new_net(ieee,&network);
} else {
- IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n",
+ IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
escape_essid(target->ssid,
target->ssid_len),
- MAC_ARG(target->bssid),
+ target->bssid,
WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
IEEE80211_STYPE_PROBE_RESP ?
"PROBE RESPONSE" : "BEACON");
@@ -2761,12 +2838,14 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
struct ieee80211_hdr_4addr *header,
struct ieee80211_rx_stats *stats)
{
+#if 0
if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
ieee->iw_mode == IW_MODE_INFRA &&
ieee->state == IEEE80211_LINKED))
{
tasklet_schedule(&ieee->ps_task);
}
+#endif
if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
@@ -2780,6 +2859,15 @@ void ieee80211_rx_mgt(struct ieee80211_device *ieee,
IEEE80211_DEBUG_SCAN("Beacon\n");
ieee80211_process_probe_response(
ieee, (struct ieee80211_probe_response *)header, stats);
+
+ //printk("----------->%s()\n", __func__);
+ if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
+ ieee->iw_mode == IW_MODE_INFRA &&
+ ieee->state == IEEE80211_LINKED))
+ {
+ tasklet_schedule(&ieee->ps_task);
+ }
+
break;
case IEEE80211_STYPE_PROBE_RESP:
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
index 6d1ddec39f0..ea96c495693 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
@@ -646,7 +646,7 @@ void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
{
if(ieee->start_send_beacons)
- ieee->start_send_beacons(ieee->dev,ieee->basic_rate);
+ ieee->start_send_beacons(ieee->dev);
if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
ieee80211_beacons_start(ieee);
}
@@ -686,6 +686,11 @@ void ieee80211_stop_scan(struct ieee80211_device *ieee)
/* called with ieee->lock held */
void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
{
+#ifdef ENABLE_IPS
+ if(ieee->ieee80211_ips_leave_wq != NULL)
+ ieee->ieee80211_ips_leave_wq(ieee->dev);
+#endif
+
#ifdef ENABLE_DOT11D
if(IS_DOT11D_ENABLE(ieee) )
{
@@ -1093,6 +1098,40 @@ struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr)
}
+struct sk_buff* ieee80211_pspoll_func(struct ieee80211_device *ieee)
+{
+ struct sk_buff *skb;
+ struct ieee80211_pspoll_hdr* hdr;
+
+#ifdef USB_USE_ALIGNMENT
+ u32 Tmpaddr=0;
+ int alignment=0;
+ skb = dev_alloc_skb(sizeof(struct ieee80211_pspoll_hdr) + ieee->tx_headroom + USB_512B_ALIGNMENT_SIZE);
+#else
+ skb = dev_alloc_skb(sizeof(struct ieee80211_pspoll_hdr)+ieee->tx_headroom);
+#endif
+ if (!skb)
+ return NULL;
+
+#ifdef USB_USE_ALIGNMENT
+ Tmpaddr = (u32)skb->data;
+ alignment = Tmpaddr & 0x1ff;
+ skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
+#endif
+ skb_reserve(skb, ieee->tx_headroom);
+
+ hdr = (struct ieee80211_pspoll_hdr*)skb_put(skb,sizeof(struct ieee80211_pspoll_hdr));
+
+ memcpy(hdr->bssid, ieee->current_network.bssid, ETH_ALEN);
+ memcpy(hdr->ta, ieee->dev->dev_addr, ETH_ALEN);
+
+ hdr->aid = cpu_to_le16(ieee->assoc_id | 0xc000);
+ hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_CTL |IEEE80211_STYPE_PSPOLL | IEEE80211_FCTL_PM);
+
+ return skb;
+
+}
+
void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest)
{
@@ -1582,6 +1621,11 @@ void ieee80211_associate_procedure_wq(struct ieee80211_device *ieee)
{
#endif
ieee->sync_scan_hurryup = 1;
+#ifdef ENABLE_IPS
+ if(ieee->ieee80211_ips_leave != NULL)
+ ieee->ieee80211_ips_leave(ieee->dev);
+#endif
+
down(&ieee->wx_sem);
if (ieee->data_hard_stop)
@@ -1592,6 +1636,17 @@ void ieee80211_associate_procedure_wq(struct ieee80211_device *ieee)
//ieee->set_chan(ieee->dev, ieee->current_network.channel);
HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
+#ifdef ENABLE_IPS
+ if(ieee->eRFPowerState == eRfOff)
+ {
+ if(ieee->ieee80211_ips_leave_wq != NULL)
+ ieee->ieee80211_ips_leave_wq(ieee->dev);
+
+ up(&ieee->wx_sem);
+ return;
+ }
+#endif
+
ieee->associate_seq = 1;
ieee80211_associate_step1(ieee);
@@ -1897,7 +1952,7 @@ ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
ieee80211_resp_to_assoc_rq(ieee, dest);
}
- printk(KERN_INFO"New client associated: "MAC_FMT"\n", MAC_ARG(dest));
+ printk(KERN_INFO"New client associated: %pM\n", dest);
//FIXME
#if 0
spin_lock_irqsave(&ieee->lock,flags);
@@ -1918,43 +1973,92 @@ void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
}
+void ieee80211_sta_ps_send_pspoll_frame(struct ieee80211_device *ieee)
+{
+
+ struct sk_buff *buf = ieee80211_pspoll_func(ieee);
+
+ if (buf)
+ softmac_ps_mgmt_xmit(buf, ieee);
+
+}
short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l)
{
int timeout = ieee->ps_timeout;
u8 dtim;
- /*if(ieee->ps == IEEE80211_PS_DISABLED ||
- ieee->iw_mode != IW_MODE_INFRA ||
- ieee->state != IEEE80211_LINKED)
+ PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(ieee->PowerSaveControl));
+ if(ieee->LPSDelayCnt)
+ {
+ //printk("===============>Delay enter LPS for DHCP and ARP packets...\n");
+ ieee->LPSDelayCnt --;
return 0;
- */
+ }
+
dtim = ieee->current_network.dtim_data;
- //printk("DTIM\n");
+// printk("%s():DTIM:%d\n",__FUNCTION__,dtim);
if(!(dtim & IEEE80211_DTIM_VALID))
return 0;
timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
//printk("VALID\n");
ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
-
- if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps))
+ /* there's no need to nofity AP that I find you buffered with broadcast packet */
+ if(dtim & (IEEE80211_DTIM_UCAST & ieee->ps))
return 2;
- if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout)))
+ if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout))){
+// printk("%s():111Oh Oh ,it is not time out return 0\n",__FUNCTION__);
return 0;
-
- if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout)))
+ }
+ if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout))){
+// printk("%s():222Oh Oh ,it is not time out return 0\n",__FUNCTION__);
return 0;
-
+ }
if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
(ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
return 0;
if(time_l){
+ if(ieee->bAwakePktSent == true) {
+ pPSC->LPSAwakeIntvl = 1;//tx wake one beacon
+ } else {
+ u8 MaxPeriod = 1;
+
+ if(pPSC->LPSAwakeIntvl == 0)
+ pPSC->LPSAwakeIntvl = 1;
+ //pNdisCommon->RegLPSMaxIntvl /// 0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl
+ if(pPSC->RegMaxLPSAwakeIntvl == 0) // Default (0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl)
+ MaxPeriod = 1; // 1 Beacon interval
+ else if(pPSC->RegMaxLPSAwakeIntvl == 0xFF) // DTIM
+ MaxPeriod = ieee->current_network.dtim_period;
+ else
+ MaxPeriod = pPSC->RegMaxLPSAwakeIntvl;
+ pPSC->LPSAwakeIntvl = (pPSC->LPSAwakeIntvl >= MaxPeriod) ? MaxPeriod : (pPSC->LPSAwakeIntvl + 1);
+ }
+ {
+ u8 LPSAwakeIntvl_tmp = 0;
+ u8 period = ieee->current_network.dtim_period;
+ u8 count = ieee->current_network.tim.tim_count;
+ if(count == 0 ) {
+ if(pPSC->LPSAwakeIntvl > period)
+ LPSAwakeIntvl_tmp = period + (pPSC->LPSAwakeIntvl - period) -((pPSC->LPSAwakeIntvl-period)%period);
+ else
+ LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;
+
+ } else {
+ if(pPSC->LPSAwakeIntvl > ieee->current_network.tim.tim_count)
+ LPSAwakeIntvl_tmp = count + (pPSC->LPSAwakeIntvl - count) -((pPSC->LPSAwakeIntvl-count)%period);
+ else
+ LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;//ieee->current_network.tim.tim_count;//pPSC->LPSAwakeIntvl;
+ }
+ //printk("=========>%s()assoc_id:%d(%#x),bAwakePktSent:%d,DTIM:%d, sleep interval:%d, LPSAwakeIntvl_tmp:%d, count:%d\n",__func__,ieee->assoc_id,cpu_to_le16(ieee->assoc_id),ieee->bAwakePktSent,ieee->current_network.dtim_period,pPSC->LPSAwakeIntvl,LPSAwakeIntvl_tmp,count);
+
*time_l = ieee->current_network.last_dtim_sta_time[0]
- + (ieee->current_network.beacon_interval);
+ + MSECS(ieee->current_network.beacon_interval * LPSAwakeIntvl_tmp);
// * ieee->current_network.dtim_period) * 1000;
}
+ }
if(time_h){
*time_h = ieee->current_network.last_dtim_sta_time[1];
@@ -1982,6 +2086,8 @@ inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
ieee->state != IEEE80211_LINKED)){
// #warning CHECK_LOCK_HERE
+ printk("=====>%s(): no need to ps,wake up!! ieee->ps is %d,ieee->iw_mode is %d,ieee->state is %d\n",
+ __FUNCTION__,ieee->ps,ieee->iw_mode,ieee->state);
spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
ieee80211_sta_wakeup(ieee, 1);
@@ -1991,27 +2097,27 @@ inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
/* 2 wake, 1 sleep, 0 do nothing */
- if(sleep == 0)
+ if(sleep == 0)//it is not time out or dtim is not valid
+ {
+ //printk("===========>sleep is 0,do nothing\n");
goto out;
-
+ }
if(sleep == 1){
-
- if(ieee->sta_sleep == 1)
+ //printk("===========>sleep is 1,to sleep\n");
+ if(ieee->sta_sleep == 1){
+ //printk("%s(1): sta_sleep = 1, sleep again ++++++++++ \n", __func__);
ieee->enter_sleep_state(ieee->dev,th,tl);
+ }
else if(ieee->sta_sleep == 0){
// printk("send null 1\n");
spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
if(ieee->ps_is_queue_empty(ieee->dev)){
-
-
ieee->sta_sleep = 2;
-
ieee->ack_tx_to_ieee = 1;
-
+ //printk("%s(2): sta_sleep = 0, notify AP we will sleeped ++++++++++ SendNullFunctionData\n", __func__);
ieee80211_sta_ps_send_null_frame(ieee,1);
-
ieee->ps_th = th;
ieee->ps_tl = tl;
}
@@ -2019,11 +2125,13 @@ inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
}
+ ieee->bAwakePktSent = false;//after null to power save we set it to false. not listen every beacon.
}else if(sleep == 2){
-//#warning CHECK_LOCK_HERE
+ //printk("==========>sleep is 2,to wakeup\n");
spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
+ //printk("%s(3): pkt buffered in ap will awake ++++++++++ ieee80211_sta_wakeup\n", __func__);
ieee80211_sta_wakeup(ieee,1);
spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
@@ -2038,9 +2146,19 @@ void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
{
if(ieee->sta_sleep == 0){
if(nl){
- printk("Warning: driver is probably failing to report TX ps error\n");
- ieee->ack_tx_to_ieee = 1;
- ieee80211_sta_ps_send_null_frame(ieee, 0);
+ if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
+ {
+ //printk("%s(1): notify AP we are awaked ++++++++++ SendNullFunctionData\n", __func__);
+ //printk("Warning: driver is probably failing to report TX ps error\n");
+ ieee->ack_tx_to_ieee = 1;
+ ieee80211_sta_ps_send_null_frame(ieee, 0);
+ }
+ else
+ {
+ ieee->ack_tx_to_ieee = 1;
+ //printk("%s(2): notify AP we are awaked ++++++++++ Send PS-Poll\n", __func__);
+ ieee80211_sta_ps_send_pspoll_frame(ieee);
+ }
}
return;
@@ -2048,12 +2166,27 @@ void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
if(ieee->sta_sleep == 1)
ieee->sta_wake_up(ieee->dev);
+ if(nl){
- ieee->sta_sleep = 0;
+ if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
+ {
+ //printk("%s(3): notify AP we are awaked ++++++++++ SendNullFunctionData\n", __func__);
+ //printk("Warning: driver is probably failing to report TX ps error\n");
+ ieee->ack_tx_to_ieee = 1;
+ ieee80211_sta_ps_send_null_frame(ieee, 0);
+ }
+ else
+ {
+ ieee->ack_tx_to_ieee = 1;
+ ieee->polling = true;
+ //printk("%s(4): notify AP we are awaked ++++++++++ Send PS-Poll\n", __func__);
+ //ieee80211_sta_ps_send_null_frame(ieee, 0);
+ ieee80211_sta_ps_send_pspoll_frame(ieee);
+ }
- if(nl){
- ieee->ack_tx_to_ieee = 1;
- ieee80211_sta_ps_send_null_frame(ieee, 0);
+ } else {
+ ieee->sta_sleep = 0;
+ ieee->polling = false;
}
}
@@ -2067,23 +2200,30 @@ void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
/* Null frame with PS bit set */
if(success){
ieee->sta_sleep = 1;
+ //printk("notify AP we will sleep and send null ok, so sleep now++++++++++ enter_sleep_state\n");
ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
}
- /* if the card report not success we can't be sure the AP
- * has not RXed so we can't assume the AP believe us awake
- */
- }
- /* 21112005 - tx again null without PS bit if lost */
- else {
+ } else {/* 21112005 - tx again null without PS bit if lost */
if((ieee->sta_sleep == 0) && !success){
spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
- ieee80211_sta_ps_send_null_frame(ieee, 0);
+ //ieee80211_sta_ps_send_null_frame(ieee, 0);
+ if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
+ {
+ //printk("notify AP we will sleep but send bull failed, so resend++++++++++ SendNullFunctionData\n");
+ ieee80211_sta_ps_send_null_frame(ieee, 0);
+ }
+ else
+ {
+ //printk("notify AP we are awaked but send pspoll failed, so resend++++++++++ Send PS-Poll\n");
+ ieee80211_sta_ps_send_pspoll_frame(ieee);
+ }
spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
}
}
spin_unlock_irqrestore(&ieee->lock, flags);
}
+
void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb)
{
struct ieee80211_hdr* header = (struct ieee80211_hdr*)skb->data;
@@ -2227,7 +2367,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
{
if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
{
- // WEP or TKIP encryption
+ // WEP or TKIP encryption
if(IsHTHalfNmodeAPs(ieee))
{
bSupportNmode = true;
@@ -2238,7 +2378,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
bSupportNmode = false;
bHalfSupportNmode = false;
}
- printk("==========>to link with AP using SEC(%d, %d)", bSupportNmode, bHalfSupportNmode);
+ printk("==========>to link with AP using SEC(%d, %d)\n", bSupportNmode, bHalfSupportNmode);
}
}
/* Dummy wirless mode setting to avoid encryption issue */
@@ -2574,6 +2714,7 @@ void ieee80211_start_ibss_wq(struct ieee80211_device *ieee)
ieee->ssid_set = 1;
}
+ ieee->state = IEEE80211_NOLINK;
/* check if we have this cell in our network list */
ieee80211_softmac_check_all_nets(ieee);
@@ -2705,6 +2846,10 @@ void ieee80211_start_bss(struct ieee80211_device *ieee)
spin_lock_irqsave(&ieee->lock, flags);
if (ieee->state == IEEE80211_NOLINK){
+#ifdef ENABLE_IPS
+ if(ieee->ieee80211_ips_leave_wq != NULL)
+ ieee->ieee80211_ips_leave_wq(ieee->dev);
+#endif
ieee->actscanning = true;
ieee80211_rtl_start_scan(ieee);
}
@@ -2823,21 +2968,23 @@ struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
return skb;
}
-void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
+void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
{
ieee->sync_scan_hurryup = 1;
down(&ieee->wx_sem);
- ieee80211_stop_protocol(ieee);
+ ieee80211_stop_protocol(ieee, shutdown);
up(&ieee->wx_sem);
}
-void ieee80211_stop_protocol(struct ieee80211_device *ieee)
+void ieee80211_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
{
if (!ieee->proto_started)
return;
- ieee->proto_started = 0;
+ if(shutdown)
+ ieee->proto_started = 0;
+ ieee->proto_stoppping = 1;
ieee80211_stop_send_beacons(ieee);
del_timer_sync(&ieee->associate_timer);
@@ -2849,6 +2996,8 @@ void ieee80211_stop_protocol(struct ieee80211_device *ieee)
ieee80211_disassociate(ieee);
RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
+
+ ieee->proto_stoppping = 0;
}
void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
@@ -2894,6 +3043,8 @@ void ieee80211_start_protocol(struct ieee80211_device *ieee)
ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
+ ieee->state = IEEE80211_NOLINK;
+
/* if the user set the MAC of the ad-hoc cell and then
* switch to managed mode, shall we make sure that association
@@ -3013,7 +3164,9 @@ void ieee80211_softmac_init(struct ieee80211_device *ieee)
#endif
sema_init(&ieee->wx_sem, 1);
sema_init(&ieee->scan_sem, 1);
-
+#ifdef ENABLE_IPS
+ sema_init(&ieee->ips_sem,1);
+#endif
spin_lock_init(&ieee->mgmt_tx_lock);
spin_lock_init(&ieee->beacon_lock);
@@ -3537,5 +3690,6 @@ EXPORT_SYMBOL_NOVERS(ieee80211_stop_scan);
EXPORT_SYMBOL_NOVERS(ieee80211_send_probe_requests);
EXPORT_SYMBOL_NOVERS(ieee80211_softmac_scan_syncro);
EXPORT_SYMBOL_NOVERS(ieee80211_start_scan_syncro);
+EXPORT_SYMBOL_NOVERS(ieee80211_sta_ps_send_null_frame);
+EXPORT_SYMBOL_NOVERS(ieee80211_sta_ps_send_pspoll_frame);
#endif
-//EXPORT_SYMBOL(ieee80211_sta_ps_send_null_frame);
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c
index 7c21aaab906..1bbd49f1d6f 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac_wx.c
@@ -160,7 +160,7 @@ int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
}
if (ifup)
- ieee80211_stop_protocol(ieee);
+ ieee80211_stop_protocol(ieee,true);
/* just to avoid to give inconsistent infos in the
* get wx method. not really needed otherwise
@@ -302,7 +302,7 @@ int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info
if (!ieee->proto_started){
ieee->iw_mode = wrqu->mode;
}else{
- ieee80211_stop_protocol(ieee);
+ ieee80211_stop_protocol(ieee,true);
ieee->iw_mode = wrqu->mode;
ieee80211_start_protocol(ieee);
}
@@ -326,6 +326,17 @@ void ieee80211_wx_sync_scan_wq(struct ieee80211_device *ieee)
int b40M = 0;
static int count = 0;
chan = ieee->current_network.channel;
+
+#ifdef ENABLE_LPS
+ if (ieee->LeisurePSLeave) {
+ ieee->LeisurePSLeave(ieee->dev);
+ }
+
+ /* notify AP to be in PS mode */
+ ieee80211_sta_ps_send_null_frame(ieee, 1);
+ ieee80211_sta_ps_send_null_frame(ieee, 1);
+#endif
+
netif_carrier_off(ieee->dev);
if (ieee->data_hard_stop)
@@ -360,6 +371,12 @@ void ieee80211_wx_sync_scan_wq(struct ieee80211_device *ieee)
ieee->InitialGainHandler(ieee->dev,IG_Restore);
ieee->state = IEEE80211_LINKED;
ieee->link_change(ieee->dev);
+
+#ifdef ENABLE_LPS
+ /* Notify AP that I wake up again */
+ ieee80211_sta_ps_send_null_frame(ieee, 0);
+#endif
+
// To prevent the immediately calling watch_dog after scan.
if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
{
@@ -429,8 +446,9 @@ int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
goto out;
}
- if(proto_started)
- ieee80211_stop_protocol(ieee);
+ if(proto_started){
+ ieee80211_stop_protocol(ieee,true);
+ }
/* this is just to be sure that the GET wx callback
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
index 798fb4154c2..a75f3668a40 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c
@@ -200,8 +200,8 @@ int ieee80211_encrypt_fragment(
header = (struct ieee80211_hdr *) frag->data;
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
- "TX packet to " MAC_FMT "\n",
- ieee->dev->name, MAC_ARG(header->addr1));
+ "TX packet to %pM\n",
+ ieee->dev->name, header->addr1);
}
return -1;
}
@@ -334,6 +334,13 @@ void ieee80211_tx_query_agg_cap(struct ieee80211_device* ieee, struct sk_buff* s
if(!Adapter->HalFunc.GetNmodeSupportBySecCfgHandler(Adapter))
return;
#endif
+
+ if(tcb_desc->bdhcp)// || ieee->CntAfterLink<2)
+ {
+ return;
+ }
+
+
#if 1
if(!ieee->GetNmodeSupportBySecCfg(ieee->dev))
{
@@ -628,6 +635,7 @@ int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
int qos_actived = ieee->current_network.qos_data.active;
struct ieee80211_crypt_data* crypt;
+ bool bdhcp =false;
cb_desc *tcb_desc;
@@ -672,6 +680,55 @@ int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
}
#endif
+ // The following is for DHCP and ARP packet, we use cck1M to tx these packets and let LPS awake some time
+ // to prevent DHCP protocol fail
+ if (skb->len > 282){//MINIMUM_DHCP_PACKET_SIZE) {
+ if (ETH_P_IP == ether_type) {// IP header
+ const struct iphdr *ip = (struct iphdr *)((u8 *)skb->data+14);
+ if (IPPROTO_UDP == ip->protocol) {//FIXME windows is 11 but here UDP in linux kernel is 17.
+ struct udphdr *udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2));
+ //if(((ntohs(udp->source) == 68) && (ntohs(udp->dest) == 67)) ||
+ /// ((ntohs(udp->source) == 67) && (ntohs(udp->dest) == 68))) {
+ if(((((u8 *)udp)[1] == 68) && (((u8 *)udp)[3] == 67)) ||
+ ((((u8 *)udp)[1] == 67) && (((u8 *)udp)[3] == 68))) {
+ // 68 : UDP BOOTP client
+ // 67 : UDP BOOTP server
+ printk("DHCP pkt src port:%d, dest port:%d!!\n", ((u8 *)udp)[1],((u8 *)udp)[3]);
+ // Use low rate to send DHCP packet.
+ //if(pMgntInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)
+ //{
+ // tcb_desc->DataRate = MgntQuery_TxRateExcludeCCKRates(ieee);//0xc;//ofdm 6m
+ // tcb_desc->bTxDisableRateFallBack = false;
+ //}
+ //else
+ //pTcb->DataRate = Adapter->MgntInfo.LowestBasicRate;
+ //RTPRINT(FDM, WA_IOT, ("DHCP TranslateHeader(), pTcb->DataRate = 0x%x\n", pTcb->DataRate));
+
+ bdhcp = true;
+#ifdef _RTL8192_EXT_PATCH_
+ ieee->LPSDelayCnt = 100;//pPSC->LPSAwakeIntvl*2; //AMY,090701
+#else
+ ieee->LPSDelayCnt = 100;//pPSC->LPSAwakeIntvl*2;
+#endif
+ }
+ }
+ }else if(ETH_P_ARP == ether_type){// IP ARP packet
+ printk("=================>DHCP Protocol start tx ARP pkt!!\n");
+ bdhcp = true;
+ ieee->LPSDelayCnt = ieee->current_network.tim.tim_count;
+
+ //if(pMgntInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)
+ //{
+ // tcb_desc->DataRate = MgntQuery_TxRateExcludeCCKRates(Adapter->MgntInfo.mBrates);//0xc;//ofdm 6m
+ // tcb_desc->bTxDisableRateFallBack = FALSE;
+ //}
+ //else
+ // tcb_desc->DataRate = Adapter->MgntInfo.LowestBasicRate;
+ //RTPRINT(FDM, WA_IOT, ("ARP TranslateHeader(), pTcb->DataRate = 0x%x\n", pTcb->DataRate));
+
+ }
+ }
+
/* Save source and destination addresses */
memcpy(&dest, skb->data, ETH_ALEN);
memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN);
@@ -895,6 +952,25 @@ int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev)
else
//tcb_desc->data_rate = CURRENT_RATE(ieee->current_network.mode, ieee->rate, ieee->HTCurrentOperaRate);
tcb_desc->data_rate = CURRENT_RATE(ieee->mode, ieee->rate, ieee->HTCurrentOperaRate);
+
+ if(bdhcp == true){
+ // Use low rate to send DHCP packet.
+ //if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom) {
+ // tcb_desc->data_rate = MGN_1M;//MgntQuery_TxRateExcludeCCKRates(ieee);//0xc;//ofdm 6m
+ // tcb_desc->bTxDisableRateFallBack = false;
+ //}
+ //else
+ {
+ tcb_desc->data_rate = MGN_1M;
+ tcb_desc->bTxDisableRateFallBack = 1;
+ }
+
+ tcb_desc->RATRIndex = 7;
+ tcb_desc->bTxUseDriverAssingedRate = 1;
+ tcb_desc->bdhcp = 1;
+ }
+
+
ieee80211_qurey_ShortPreambleMode(ieee, tcb_desc);
ieee80211_tx_query_agg_cap(ieee, txb->fragments[0], tcb_desc);
ieee80211_query_HTCapShortGI(ieee, tcb_desc);
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
index 3441b72dd8f..a3302d5e01a 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
@@ -386,10 +386,10 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
else
IEEE80211_DEBUG_SCAN(
"Not showing network '%s ("
- MAC_FMT ")' due to age (%lums).\n",
+ "%pM)' due to age (%lums).\n",
escape_essid(network->ssid,
network->ssid_len),
- MAC_ARG(network->bssid),
+ network->bssid,
(jiffies - network->last_scanned) / (HZ / 100));
}
@@ -933,7 +933,7 @@ int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
#if 1
case IW_AUTH_WPA_ENABLED:
ieee->wpa_enabled = (data->value)?1:0;
- //printk("enalbe wpa:%d\n", ieee->wpa_enabled);
+ //printk("enable wpa:%d\n", ieee->wpa_enabled);
break;
#endif
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c
index e41e8a0c739..ae0e5b9e218 100644
--- a/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c
@@ -113,7 +113,7 @@ static struct sk_buff* ieee80211_ADDBA(struct ieee80211_device* ieee, u8* Dst, P
u16 tmp = 0;
u16 len = ieee->tx_headroom + 9;
//category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) + BA Timeout Value(2) + BA Start SeqCtrl(2)(or StatusCode(2))
- IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:"MAC_FMT", ieee->dev:%p\n", __FUNCTION__, type, MAC_ARG(Dst), ieee->dev);
+ IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __FUNCTION__, type, Dst, ieee->dev);
if (pBA == NULL||ieee == NULL)
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee);
@@ -243,7 +243,7 @@ static struct sk_buff* ieee80211_DELBA(
u16 len = 6 + ieee->tx_headroom;
if (net_ratelimit())
- IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:"MAC_FMT"\n", __FUNCTION__, ReasonCode, MAC_ARG(dst));
+ IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:%pM\n", __FUNCTION__, ReasonCode, dst);
memset(&DelbaParamSet, 0, 2);
@@ -397,7 +397,7 @@ int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb)
pBaTimeoutVal = (u16*)(tag + 5);
pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7);
- printk("====================>rx ADDBAREQ from :"MAC_FMT"\n", MAC_ARG(dst));
+ printk("====================>rx ADDBAREQ from :%pM\n", dst);
//some other capability is not ready now.
if( (ieee->current_network.qos_data.active == 0) ||
(ieee->pHTInfo->bCurrentHTSupport == false)) //||
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h b/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h
index 992b71825a8..f968817d073 100644
--- a/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_HT.h
@@ -458,7 +458,8 @@ typedef enum _HT_IOT_PEER
HT_IOT_PEER_RALINK = 3,
HT_IOT_PEER_ATHEROS = 4,
HT_IOT_PEER_CISCO= 5,
- HT_IOT_PEER_MAX = 6
+ HT_IOT_PEER_MARVELL=6,
+ HT_IOT_PEER_MAX = 7
}HT_IOT_PEER_E, *PHTIOT_PEER_E;
//
@@ -475,6 +476,7 @@ typedef enum _HT_IOT_ACTION{
HT_IOT_ACT_CDD_FSYNC = 0x00000080,
HT_IOT_ACT_PURE_N_MODE = 0x00000100,
HT_IOT_ACT_FORCED_CTS2SELF = 0x00000200,
+ HT_IOT_ACT_NULL_DATA_POWER_SAVING = 0x00800000,
}HT_IOT_ACTION_E, *PHT_IOT_ACTION_E;
#endif //_RTL819XU_HTTYPE_H_
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c b/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c
index 1e392141779..4c4b1df350a 100644
--- a/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_HTProc.c
@@ -32,7 +32,7 @@ u16 MCS_DATA_RATE[2][2][77] =
static u8 UNKNOWN_BORADCOM[3] = {0x00, 0x14, 0xbf};
static u8 LINKSYSWRT330_LINKSYSWRT300_BROADCOM[3] = {0x00, 0x1a, 0x70};
static u8 LINKSYSWRT350_LINKSYSWRT150_BROADCOM[3] = {0x00, 0x1d, 0x7e};
-static u8 NETGEAR834Bv2_BROADCOM[3] = {0x00, 0x1b, 0x2f};
+//static u8 NETGEAR834Bv2_BROADCOM[3] = {0x00, 0x1b, 0x2f};
static u8 BELKINF5D8233V1_RALINK[3] = {0x00, 0x17, 0x3f}; //cosa 03202008
static u8 BELKINF5D82334V3_RALINK[3] = {0x00, 0x1c, 0xdf};
static u8 PCI_RALINK[3] = {0x00, 0x90, 0xcc};
@@ -40,8 +40,9 @@ static u8 EDIMAX_RALINK[3] = {0x00, 0x0e, 0x2e};
static u8 AIRLINK_RALINK[3] = {0x00, 0x18, 0x02};
static u8 DLINK_ATHEROS[3] = {0x00, 0x1c, 0xf0};
static u8 CISCO_BROADCOM[3] = {0x00, 0x17, 0x94};
+static u8 LINKSYS_MARVELL_4400N[3] = {0x00, 0x14, 0xa4};
-// 2008/04/01 MH For Cisco G mode RX TP We need to change FW duration. Shoud we put the
+// 2008/04/01 MH For Cisco G mode RX TP We need to change FW duration. Should we put the
// code in other place??
//static u8 WIFI_CISCO_G_AP[3] = {0x00, 0x40, 0x96};
/********************************************************************************************************************
@@ -349,12 +350,12 @@ bool IsHTHalfNmodeAPs(struct ieee80211_device* ieee)
bool retValue = false;
struct ieee80211_network* net = &ieee->current_network;
#if 0
- if(pMgntInfo->bHalfNMode == false)
+ if(ieee->bHalfNMode == false)
retValue = false;
else
#endif
if((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3)==0) ||
- (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3)==0) ||
+ (memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3)==0) ||
(memcmp(net->bssid, PCI_RALINK, 3)==0) ||
(memcmp(net->bssid, EDIMAX_RALINK, 3)==0) ||
(memcmp(net->bssid, AIRLINK_RALINK, 3)==0) ||
@@ -363,7 +364,7 @@ bool IsHTHalfNmodeAPs(struct ieee80211_device* ieee)
else if((memcmp(net->bssid, UNKNOWN_BORADCOM, 3)==0) ||
(memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)||
(memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)||
- (memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3)==0) ||
+ //(memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3)==0) ||
(net->broadcom_cap_exist))
retValue = true;
else if(net->bssht.bdRT2RTAggregation)
@@ -387,13 +388,15 @@ void HTIOTPeerDetermine(struct ieee80211_device* ieee)
struct ieee80211_network* net = &ieee->current_network;
if(net->bssht.bdRT2RTAggregation)
pHTInfo->IOTPeer = HT_IOT_PEER_REALTEK;
- else if(net->broadcom_cap_exist)
+ else if(net->broadcom_cap_exist){
pHTInfo->IOTPeer = HT_IOT_PEER_BROADCOM;
+ }
else if((memcmp(net->bssid, UNKNOWN_BORADCOM, 3)==0) ||
(memcmp(net->bssid, LINKSYSWRT330_LINKSYSWRT300_BROADCOM, 3)==0)||
- (memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)||
- (memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3)==0) )
+ (memcmp(net->bssid, LINKSYSWRT350_LINKSYSWRT150_BROADCOM, 3)==0)){//||
+ //(memcmp(net->bssid, NETGEAR834Bv2_BROADCOM, 3)==0) ){
pHTInfo->IOTPeer = HT_IOT_PEER_BROADCOM;
+ }
else if((memcmp(net->bssid, BELKINF5D8233V1_RALINK, 3)==0) ||
(memcmp(net->bssid, BELKINF5D82334V3_RALINK, 3)==0) ||
(memcmp(net->bssid, PCI_RALINK, 3)==0) ||
@@ -405,6 +408,10 @@ void HTIOTPeerDetermine(struct ieee80211_device* ieee)
pHTInfo->IOTPeer = HT_IOT_PEER_ATHEROS;
else if(memcmp(net->bssid, CISCO_BROADCOM, 3)==0)
pHTInfo->IOTPeer = HT_IOT_PEER_CISCO;
+ else if ((memcmp(net->bssid, LINKSYS_MARVELL_4400N, 3) == 0) ||
+ net->marvell_cap_exist){
+ pHTInfo->IOTPeer = HT_IOT_PEER_MARVELL;
+ }
else
pHTInfo->IOTPeer = HT_IOT_PEER_UNKNOWN;
@@ -442,6 +449,18 @@ u8 HTIOTActIsDisableMCS14(struct ieee80211_device* ieee, u8* PeerMacAddr)
return ret;
}
+u8 HTIOTActIsForcedCTS2Self(struct ieee80211_device *ieee, struct ieee80211_network *network)
+{
+ u8 retValue = 0;
+ //if(network->marvell_cap_exist)
+ if(ieee->pHTInfo->IOTPeer == HT_IOT_PEER_MARVELL)
+ {
+ retValue = 1;
+ }
+
+ return retValue;
+}
+
/**
* Function: HTIOTActIsDisableMCS15
@@ -578,6 +597,23 @@ u8 HTIOTActIsCCDFsync(u8* PeerMacAddr)
return retValue;
}
+//
+// Send null data for to tell AP that we are awake.
+//
+bool
+HTIOTActIsNullDataPowerSaving(struct ieee80211_device* ieee,struct ieee80211_network *network)
+{
+ bool retValue = false;
+
+ PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
+ {
+ if(pHTInfo->IOTPeer == HT_IOT_PEER_BROADCOM) // ||(pBssDesc->Vender == HT_IOT_PEER_ATHEROS && pBssDesc->SubTypeOfVender == HT_IOT_PEER_ATHEROS_DIR635))
+ return true;
+
+ }
+ return retValue;
+}
+
void HTResetIOTSetting(
PRT_HIGH_THROUGHPUT pHTInfo
)
@@ -1071,6 +1107,13 @@ void HTOnAssocRsp(struct ieee80211_device *ieee)
// Config and configure A-MSDU setting
//
pHTInfo->bCurrent_AMSDU_Support = pHTInfo->bAMSDU_Support;
+ if (ieee->rtllib_ap_sec_type &&
+ (ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_WEP|SEC_ALG_TKIP))){
+ if( (pHTInfo->IOTPeer== HT_IOT_PEER_ATHEROS) ||
+ (pHTInfo->IOTPeer == HT_IOT_PEER_UNKNOWN) )
+ pHTInfo->bCurrentAMPDUEnable = false;
+ }
+
nMaxAMSDUSize = (pPeerHTCap->MaxAMSDUSize==0)?3839:7935;
@@ -1515,6 +1558,9 @@ void HTResetSelfAndSavePeerSetting(struct ieee80211_device* ieee, struct ieee80
bIOTAction = HTIOTActIsDisableMCS14(ieee, pNetwork->bssid);
if(bIOTAction)
pHTInfo->IOTAction |= HT_IOT_ACT_DISABLE_MCS14;
+ bIOTAction = HTIOTActIsForcedCTS2Self(ieee, pNetwork);
+ if(bIOTAction)
+ pHTInfo->IOTAction |= HT_IOT_ACT_FORCED_CTS2SELF;
bIOTAction = HTIOTActIsDisableMCS15(ieee);
if(bIOTAction)
@@ -1537,6 +1583,9 @@ void HTResetSelfAndSavePeerSetting(struct ieee80211_device* ieee, struct ieee80
if(bIOTAction)
pHTInfo->IOTAction |= HT_IOT_ACT_CDD_FSYNC;
+ bIOTAction = HTIOTActIsNullDataPowerSaving(ieee, pNetwork);
+ if(bIOTAction)
+ pHTInfo->IOTAction |= HT_IOT_ACT_NULL_DATA_POWER_SAVING;
}
else
diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c
index 2816b60a08a..e2cbfd3aa00 100644
--- a/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c
+++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_TSProc.c
@@ -304,7 +304,7 @@ PTS_COMMON_INFO SearchAdmitTRStream(struct ieee80211_device *ieee, u8* Addr, u8
if(search_dir[dir] ==false )
continue;
list_for_each_entry(pRet, psearch_list, List){
- // IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:"MAC_FMT", TID:%d, dir:%d\n", MAC_ARG(pRet->Addr), pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection);
+ // IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:%pM, TID:%d, dir:%d\n", pRet->Addr, pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection);
if (memcmp(pRet->Addr, Addr, 6) == 0)
if (pRet->TSpec.f.TSInfo.field.ucTSID == TID)
if(pRet->TSpec.f.TSInfo.field.ucDirection == dir)
@@ -466,7 +466,7 @@ bool GetTs(
ResetRxTsEntry(tmp);
}
- IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:"MAC_FMT"\n", UP, Dir, MAC_ARG(Addr));
+ IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:%pM\n", UP, Dir, Addr);
// Prepare TS Info releated field
pTSInfo->field.ucTrafficType = 0; // Traffic type: WMM is reserved in this field
pTSInfo->field.ucTSID = UP; // TSID
@@ -552,7 +552,7 @@ void RemoveTsEntry(
void RemovePeerTS(struct ieee80211_device* ieee, u8* Addr)
{
PTS_COMMON_INFO pTS, pTmpTS;
- printk("===========>RemovePeerTS,"MAC_FMT"\n", MAC_ARG(Addr));
+ printk("===========>RemovePeerTS,%pM\n", Addr);
#if 1
list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List)
{
diff --git a/drivers/staging/rtl8192e/r8180_93cx6.c b/drivers/staging/rtl8192e/r8180_93cx6.c
index 79f7a0f3962..262ed5fd086 100644
--- a/drivers/staging/rtl8192e/r8180_93cx6.c
+++ b/drivers/staging/rtl8192e/r8180_93cx6.c
@@ -22,7 +22,7 @@
static void eprom_cs(struct net_device *dev, short bit)
{
- if(bit)
+ if (bit)
write_nic_byte(dev, EPROM_CMD,
(1<<EPROM_CS_SHIFT) | \
read_nic_byte(dev, EPROM_CMD)); //enable EPROM
@@ -38,23 +38,23 @@ static void eprom_cs(struct net_device *dev, short bit)
static void eprom_ck_cycle(struct net_device *dev)
{
write_nic_byte(dev, EPROM_CMD,
- (1<<EPROM_CK_SHIFT) | read_nic_byte(dev,EPROM_CMD));
+ (1<<EPROM_CK_SHIFT) | read_nic_byte(dev, EPROM_CMD));
force_pci_posting(dev);
udelay(EPROM_DELAY);
write_nic_byte(dev, EPROM_CMD,
- read_nic_byte(dev, EPROM_CMD) &~ (1<<EPROM_CK_SHIFT));
+ read_nic_byte(dev, EPROM_CMD) & ~(1<<EPROM_CK_SHIFT));
force_pci_posting(dev);
udelay(EPROM_DELAY);
}
-static void eprom_w(struct net_device *dev,short bit)
+static void eprom_w(struct net_device *dev, short bit)
{
- if(bit)
+ if (bit)
write_nic_byte(dev, EPROM_CMD, (1<<EPROM_W_SHIFT) | \
- read_nic_byte(dev,EPROM_CMD));
+ read_nic_byte(dev, EPROM_CMD));
else
- write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev,EPROM_CMD)\
+ write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev, EPROM_CMD)\
&~(1<<EPROM_W_SHIFT));
force_pci_posting(dev);
@@ -66,10 +66,11 @@ static short eprom_r(struct net_device *dev)
{
short bit;
- bit=(read_nic_byte(dev, EPROM_CMD) & (1<<EPROM_R_SHIFT) );
+ bit = (read_nic_byte(dev, EPROM_CMD) & (1<<EPROM_R_SHIFT));
udelay(EPROM_DELAY);
- if(bit) return 1;
+ if (bit)
+ return 1;
return 0;
}
@@ -78,7 +79,7 @@ static void eprom_send_bits_string(struct net_device *dev, short b[], int len)
{
int i;
- for(i=0; i<len; i++){
+ for (i = 0; i < len; i++) {
eprom_w(dev, b[i]);
eprom_ck_cycle(dev);
}
@@ -88,37 +89,37 @@ static void eprom_send_bits_string(struct net_device *dev, short b[], int len)
u32 eprom_read(struct net_device *dev, u32 addr)
{
struct r8192_priv *priv = ieee80211_priv(dev);
- short read_cmd[]={1,1,0};
+ short read_cmd[] = {1, 1, 0};
short addr_str[8];
int i;
int addr_len;
u32 ret;
- ret=0;
+ ret = 0;
//enable EPROM programming
write_nic_byte(dev, EPROM_CMD,
(EPROM_CMD_PROGRAM<<EPROM_CMD_OPERATING_MODE_SHIFT));
force_pci_posting(dev);
udelay(EPROM_DELAY);
- if (priv->epromtype==EPROM_93c56){
- addr_str[7]=addr & 1;
- addr_str[6]=addr & (1<<1);
- addr_str[5]=addr & (1<<2);
- addr_str[4]=addr & (1<<3);
- addr_str[3]=addr & (1<<4);
- addr_str[2]=addr & (1<<5);
- addr_str[1]=addr & (1<<6);
- addr_str[0]=addr & (1<<7);
- addr_len=8;
- }else{
- addr_str[5]=addr & 1;
- addr_str[4]=addr & (1<<1);
- addr_str[3]=addr & (1<<2);
- addr_str[2]=addr & (1<<3);
- addr_str[1]=addr & (1<<4);
- addr_str[0]=addr & (1<<5);
- addr_len=6;
+ if (priv->epromtype == EPROM_93c56) {
+ addr_str[7] = addr & 1;
+ addr_str[6] = addr & (1<<1);
+ addr_str[5] = addr & (1<<2);
+ addr_str[4] = addr & (1<<3);
+ addr_str[3] = addr & (1<<4);
+ addr_str[2] = addr & (1<<5);
+ addr_str[1] = addr & (1<<6);
+ addr_str[0] = addr & (1<<7);
+ addr_len = 8;
+ } else {
+ addr_str[5] = addr & 1;
+ addr_str[4] = addr & (1<<1);
+ addr_str[3] = addr & (1<<2);
+ addr_str[2] = addr & (1<<3);
+ addr_str[1] = addr & (1<<4);
+ addr_str[0] = addr & (1<<5);
+ addr_len = 6;
}
eprom_cs(dev, 1);
eprom_ck_cycle(dev);
@@ -129,7 +130,7 @@ u32 eprom_read(struct net_device *dev, u32 addr)
//I'm unsure if it is necessary, but anyway shouldn't hurt
eprom_w(dev, 0);
- for(i=0;i<16;i++){
+ for (i = 0; i < 16; i++) {
//eeprom needs a clk cycle between writing opcode&adr
//and reading data. (eeprom outs a dummy 0)
eprom_ck_cycle(dev);
diff --git a/drivers/staging/rtl8192e/r8180_93cx6.h b/drivers/staging/rtl8192e/r8180_93cx6.h
index 62e14c78e96..4c3f675c6a6 100644
--- a/drivers/staging/rtl8192e/r8180_93cx6.h
+++ b/drivers/staging/rtl8192e/r8180_93cx6.h
@@ -1,17 +1,18 @@
-/*
- This is part of rtl8187 OpenSource driver
- Copyright (C) Andrea Merello 2004-2005 <andreamrl@tiscali.it>
- Released under the terms of GPL (General Public Licence)
-
- Parts of this driver are based on the GPL part of the official realtek driver
- Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon
- Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
-
- We want to tanks the Authors of such projects and the Ndiswrapper project Authors.
-*/
-
-/*This files contains card eeprom (93c46 or 93c56) programming routines*/
-/*memory is addressed by WORDS*/
+/* r8180_93cx6.h - 93c46 or 93c56 eeprom card programming routines
+ *
+ * This is part of rtl8187 OpenSource driver
+ * Copyright (C) Andrea Merello 2004-2005 <andreamrl@tiscali.it>
+ * Released under the terms of GPL (General Public Licence)
+ * Parts of this driver are based on the GPL part of the official realtek driver
+ *
+ * Parts of this driver are based on the rtl8180 driver skeleton from
+ * Patric Schenke & Andres Salomon.
+ *
+ * Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver
+ *
+ * We want to thank the authors of the above mentioned projects and to
+ * the authors of the Ndiswrapper project.
+ */
#include "r8192E.h"
#include "r8192E_hw.h"
@@ -36,5 +37,5 @@
#define EPROM_TXPW2 0x1b
#define EPROM_TXPW1 0x3d
-
-u32 eprom_read(struct net_device *dev,u32 addr); //reads a 16 bits word
+/* Reads a 16 bits word. */
+u32 eprom_read(struct net_device *dev, u32 addr);
diff --git a/drivers/staging/rtl8192e/r8190_rtl8256.c b/drivers/staging/rtl8192e/r8190_rtl8256.c
index 3d67fbb65b9..1bd054d42f2 100644
--- a/drivers/staging/rtl8192e/r8190_rtl8256.c
+++ b/drivers/staging/rtl8192e/r8190_rtl8256.c
@@ -429,11 +429,12 @@ SetRFPowerState8190(
bool bResult = true;
//u8 eRFPath;
u8 i = 0, QueueID = 0;
- ptx_ring head=NULL,tail=NULL;
+ //ptx_ring head=NULL,tail=NULL;
+ struct rtl8192_tx_ring *ring = NULL;
if(priv->SetRFPowerStateInProgress == true)
return false;
- RT_TRACE(COMP_POWER, "===========> SetRFPowerState8190()!\n");
+ //RT_TRACE(COMP_PS, "===========> SetRFPowerState8190()!\n");
priv->SetRFPowerStateInProgress = true;
switch(priv->rf_chip)
@@ -442,11 +443,11 @@ SetRFPowerState8190(
switch( eRFPowerState )
{
case eRfOn:
- RT_TRACE(COMP_POWER, "SetRFPowerState8190() eRfOn !\n");
+ //RT_TRACE(COMP_PS, "SetRFPowerState8190() eRfOn !\n");
//RXTX enable control: On
//for(eRFPath = 0; eRFPath <pHalData->NumTotalRFPath; eRFPath++)
- // PHY_SetRFReg(Adapter, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x2);
- #ifdef RTL8190P
+ // PHY_SetRFReg(dev, (RF90_RADIO_PATH_E)eRFPath, 0x4, 0xC00, 0x2);
+#ifdef RTL8190P
if(priv->rf_type == RF_2T4R)
{
//enable RF-Chip A/B
@@ -479,36 +480,92 @@ SetRFPowerState8190(
//analog to digital part2 on
rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x1800, 0x3); // 0x880[12:11]
}
- #else
- write_nic_byte(dev, ANAPAR, 0x37);//160MHz
- write_nic_byte(dev, MacBlkCtrl, 0x17); // 0x403
- mdelay(1);
- //enable clock 80/88 MHz
-
- priv->bHwRfOffAction = 0;
- //}
-
- // Baseband reset 2008.09.30 add
- write_nic_byte(dev, BB_RESET, (read_nic_byte(dev, BB_RESET)|BIT0));
-
- //2 AFE
- // 2008.09.30 add
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter2, 0x20000000, 0x1); // 0x884
- //analog to digital part2 on
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x3); // 0x880[6:5]
- //digital to analog on
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x98, 0x13); // 0x880[4:3]
- //analog to digital on
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf03, 0xf03);// 0x88c[9:8]
- //rx antenna on
- //PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, 0x3, 0x3);// 0xc04[1:0]
- //rx antenna on 2008.09.30 mark
- //PHY_SetBBReg(Adapter, rOFDM1_TRxPathEnable, 0x3, 0x3);// 0xd04[1:0]
-
- //2 RF
- //enable RF-Chip A/B
+ else if(priv->rf_type == RF_1T1R) //RF-C
+ {
+ //enable RF-Chip C/D
+ rtl8192_setBBreg(dev, rFPGA0_XC_RFInterfaceOE, BIT4, 0x1); // 0x868[4]
+ //analog to digital on
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x400, 0x1);// 0x88c[10]
+ //digital to analog on
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x80, 0x1); // 0x880[7]
+ //rx antenna on
+ rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x4, 0x1);// 0xc04[2]
+ //rx antenna on
+ rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x4, 0x1);// 0xd04[2]
+ //analog to digital part2 on
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x800, 0x1); // 0x880[11]
+ }
+
+#elif defined RTL8192E
+ // turn on RF
+ if((priv->ieee80211->eRFPowerState == eRfOff) && RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC))
+ { // The current RF state is OFF and the RF OFF level is halting the NIC, re-initialize the NIC.
+ bool rtstatus = true;
+ u32 InitilizeCount = 3;
+ do
+ {
+ InitilizeCount--;
+ priv->RegRfOff = false;
+ rtstatus = NicIFEnableNIC(dev);
+ }while( (rtstatus != true) &&(InitilizeCount >0) );
+
+ if(rtstatus != true)
+ {
+ RT_TRACE(COMP_ERR,"%s():Initialize Adapter fail,return\n",__FUNCTION__);
+ priv->SetRFPowerStateInProgress = false;
+ return false;
+ }
+
+ RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+ } else {
+ write_nic_byte(dev, ANAPAR, 0x37);//160MHz
+ //write_nic_byte(dev, MacBlkCtrl, 0x17); // 0x403
+ mdelay(1);
+ //enable clock 80/88 MHz
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x4, 0x1); // 0x880[2]
+ priv->bHwRfOffAction = 0;
+ //}
+
+ //RF-A, RF-B
+ //enable RF-Chip A/B
rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x1); // 0x860[4]
- rtl8192_setBBreg(dev, rFPGA0_XB_RFInterfaceOE, BIT4, 0x1); // 0x864[4]
+ //analog to digital on
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3);// 0x88c[9:8]
+ //digital to analog on
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x18, 0x3); // 0x880[4:3]
+ //rx antenna on
+ rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x3, 0x3);// 0xc04[1:0]
+ //rx antenna on
+ rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x3, 0x3);// 0xd04[1:0]
+ //analog to digital part2 on
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x3); // 0x880[6:5]
+
+ // Baseband reset 2008.09.30 add
+ //write_nic_byte(dev, BB_RESET, (read_nic_byte(dev, BB_RESET)|BIT0));
+
+ //2 AFE
+ // 2008.09.30 add
+ //rtl8192_setBBreg(dev, rFPGA0_AnalogParameter2, 0x20000000, 0x1); // 0x884
+ //analog to digital part2 on
+ //rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x3); // 0x880[6:5]
+
+
+ //digital to analog on
+ //rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x98, 0x13); // 0x880[4:3]
+ //analog to digital on
+ //rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf03, 0xf03);// 0x88c[9:8]
+ //rx antenna on
+ //PHY_SetBBReg(dev, rOFDM0_TRxPathEnable, 0x3, 0x3);// 0xc04[1:0]
+ //rx antenna on 2008.09.30 mark
+ //PHY_SetBBReg(dev, rOFDM1_TRxPathEnable, 0x3, 0x3);// 0xd04[1:0]
+
+ //2 RF
+ //enable RF-Chip A/B
+ //rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x1); // 0x860[4]
+ //rtl8192_setBBreg(dev, rFPGA0_XB_RFInterfaceOE, BIT4, 0x1); // 0x864[4]
+
+ }
+
#endif
break;
@@ -517,119 +574,137 @@ SetRFPowerState8190(
// By Bruce, 2008-01-16.
//
case eRfSleep:
- case eRfOff:
- RT_TRACE(COMP_POWER, "SetRFPowerState8190() eRfOff/Sleep !\n");
- if (pPSC->bLeisurePs)
+ {
+ // HW setting had been configured with deeper mode.
+ if(priv->ieee80211->eRFPowerState == eRfOff)
+ break;
+
+ // Update current RF state variable.
+ //priv->ieee80211->eRFPowerState = eRFPowerState;
+
+ //if (pPSC->bLeisurePs)
{
for(QueueID = 0, i = 0; QueueID < MAX_TX_QUEUE; )
{
- switch(QueueID) {
- case MGNT_QUEUE:
- tail=priv->txmapringtail;
- head=priv->txmapringhead;
+ ring = &priv->tx_ring[QueueID];
+
+ if(skb_queue_len(&ring->queue) == 0)
+ {
+ QueueID++;
+ continue;
+ }
+ else
+ {
+ RT_TRACE((COMP_POWER|COMP_RF), "eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 before doze!\n", (i+1), QueueID);
+ udelay(10);
+ i++;
+ }
+
+ if(i >= MAX_DOZE_WAITING_TIMES_9x)
+ {
+ RT_TRACE(COMP_POWER, "\n\n\n TimeOut!! SetRFPowerState8190(): eRfOff: %d times TcbBusyQueue[%d] != 0 !!!\n\n\n", MAX_DOZE_WAITING_TIMES_9x, QueueID);
break;
+ }
+ }
+ }
- case BK_QUEUE:
- tail=priv->txbkpringtail;
- head=priv->txbkpringhead;
+ //if(Adapter->HardwareType == HARDWARE_TYPE_RTL8190P)
+#ifdef RTL8190P
+ {
+ PHY_SetRtl8190pRfOff(dev);
+ }
+ //else if(Adapter->HardwareType == HARDWARE_TYPE_RTL8192E)
+#elif defined RTL8192E
+ {
+ PHY_SetRtl8192eRfOff(dev);
+ }
+#endif
+ }
break;
- case BE_QUEUE:
- tail=priv->txbepringtail;
- head=priv->txbepringhead;
- break;
+ case eRfOff:
+ //RT_TRACE(COMP_PS, "SetRFPowerState8190() eRfOff/Sleep !\n");
- case VI_QUEUE:
- tail=priv->txvipringtail;
- head=priv->txvipringhead;
- break;
+ // Update current RF state variable.
+ //priv->ieee80211->eRFPowerState = eRFPowerState;
- case VO_QUEUE:
- tail=priv->txvopringtail;
- head=priv->txvopringhead;
- break;
+ //
+ // Disconnect with Any AP or STA.
+ //
+ for(QueueID = 0, i = 0; QueueID < MAX_TX_QUEUE; )
+ {
+ ring = &priv->tx_ring[QueueID];
- default:
- tail=head=NULL;
- break;
- }
- if(tail == head)
+ if(skb_queue_len(&ring->queue) == 0)
{
- //DbgPrint("QueueID = %d", QueueID);
QueueID++;
continue;
}
else
{
- RT_TRACE(COMP_POWER, "eRf Off/Sleep: %d times BusyQueue[%d] !=0 before doze!\n", (i+1), QueueID);
+ RT_TRACE(COMP_POWER,
+ "eRf Off/Sleep: %d times TcbBusyQueue[%d] !=0 before doze!\n", (i+1), QueueID);
udelay(10);
i++;
}
if(i >= MAX_DOZE_WAITING_TIMES_9x)
{
- RT_TRACE(COMP_POWER, "\n\n\n TimeOut!! SetRFPowerState8190(): eRfOff: %d times BusyQueue[%d] != 0 !!!\n\n\n", MAX_DOZE_WAITING_TIMES_9x, QueueID);
+ RT_TRACE(COMP_POWER, "\n\n\n SetZebraRFPowerState8185B(): eRfOff: %d times TcbBusyQueue[%d] != 0 !!!\n\n\n", MAX_DOZE_WAITING_TIMES_9x, QueueID);
break;
}
}
+
+ //if(Adapter->HardwareType == HARDWARE_TYPE_RTL8190P)
+#if defined RTL8190P
+ {
+ PHY_SetRtl8190pRfOff(dev);
}
- #ifdef RTL8190P
- if(priv->rf_type == RF_2T4R)
+ //else if(Adapter->HardwareType == HARDWARE_TYPE_RTL8192E)
+#elif defined RTL8192E
{
- //disable RF-Chip A/B
- rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0); // 0x860[4]
+ //if(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC && !RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC) && priv->ieee80211->RfOffReason > RF_CHANGE_BY_PS)
+ if (pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC && !RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC))
+ { // Disable all components.
+ //
+ // Note:
+ // NicIFSetLinkStatus is a big problem when we indicate the status to OS,
+ // the OS(XP) will reset. But now, we cnnot find why the NIC is hard to receive
+ // packets after RF ON. Just keep this function here and still work to find out the root couse.
+ // By Bruce, 2009-05-01.
+ //
+ //NicIFSetLinkStatus( Adapter, RT_MEDIA_DISCONNECT );
+ //if HW radio of , need to indicate scan complete first for not be reset.
+ //if(MgntScanInProgress(pMgntInfo))
+ // MgntResetScanProcess( Adapter );
+
+ // <1> Disable Interrupt
+ //rtl8192_irq_disable(dev);
+ // <2> Stop all timer
+ //MgntCancelAllTimer(Adapter);
+ // <3> Disable Adapter
+ //NicIFHaltAdapter(Adapter, false);
+ NicIFDisableNIC(dev);
+ RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+ }
+ else if (!(pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC))
+ { // Normal case.
+ // IPS should go to this.
+ PHY_SetRtl8192eRfOff(dev);
+ }
+ }
+#else
+ else
+ {
+ RT_TRACE(COMP_DBG,DBG_TRACE,("It is not 8190Pci and 8192PciE \n"));
}
- //disable RF-Chip C/D
- rtl8192_setBBreg(dev, rFPGA0_XC_RFInterfaceOE, BIT4, 0x0); // 0x868[4]
- //analog to digital off, for power save
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0);// 0x88c[11:8]
- //digital to analog off, for power save
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x1e0, 0x0); // 0x880[8:5]
- //rx antenna off
- rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0xf, 0x0);// 0xc04[3:0]
- //rx antenna off
- rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0xf, 0x0);// 0xd04[3:0]
- //analog to digital part2 off, for power save
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x1e00, 0x0); // 0x880[12:9]
-#else //8192E
- //2 RF
- //disable RF-Chip A/B
- rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0); // 0x860[4]
- rtl8192_setBBreg(dev, rFPGA0_XB_RFInterfaceOE, BIT4, 0x0); // 0x864[4]
- //2 AFE
- //analog to digital off, for power save
- //PHY_SetBBReg(Adapter, rFPGA0_AnalogParameter4, 0xf00, 0x0);// 0x88c[11:8]
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf03, 0x0); // 2008.09.30 Modify
- //digital to analog off, for power save
- //PHY_SetBBReg(Adapter, rFPGA0_AnalogParameter1, 0x18, 0x0); // 0x880[4:3]
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x98, 0x0); // 0x880 2008.09.30 Modify
- //rx antenna off 2008.09.30 mark
- //PHY_SetBBReg(Adapter, rOFDM0_TRxPathEnable, 0xf, 0x0);// 0xc04[3:0]
- //rx antenna off 2008.09.30 mark
- //PHY_SetBBReg(Adapter, rOFDM1_TRxPathEnable, 0xf, 0x0);// 0xd04[3:0]
- //analog to digital part2 off, for power save
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x0); // 0x880[6:5]
- // 2008.09.30 add
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter2, 0x20000000, 0x0); // 0x884
-
-
- //disable clock 80/88 MHz 2008.09.30 mark
- //PHY_SetBBReg(Adapter, rFPGA0_AnalogParameter1, 0x4, 0x0); // 0x880[2]
- //2 BB
- // Baseband reset 2008.09.30 add
- write_nic_byte(dev, BB_RESET, (read_nic_byte(dev, BB_RESET)|BIT0)); // 0x101
- //MAC: off
- write_nic_byte(dev, MacBlkCtrl, 0x0); // 0x403
- //slow down cpu/lbus clock from 160MHz to Lower
- write_nic_byte(dev, ANAPAR, 0x07); // 0x 17 40MHz
- priv->bHwRfOffAction = 0;
- //}
#endif
+
break;
default:
bResult = false;
- RT_TRACE(COMP_ERR, "SetRFPowerState8190(): unknown state to set: 0x%X!!!\n", eRFPowerState);
+ RT_TRACE(COMP_ERR, "SetRFPowerState8190(): unknow state to set: 0x%X!!!\n", eRFPowerState);
break;
}
@@ -644,64 +719,11 @@ SetRFPowerState8190(
{
// Update current RF state variable.
priv->ieee80211->eRFPowerState = eRFPowerState;
-
- switch(priv->rf_chip )
- {
- case RF_8256:
- switch(priv->ieee80211->eRFPowerState)
- {
- case eRfOff:
- //
- //If Rf off reason is from IPS, Led should blink with no link, by Maddest 071015
- //
- if(priv->ieee80211->RfOffReason==RF_CHANGE_BY_IPS )
- {
- #ifdef TO_DO
- Adapter->HalFunc.LedControlHandler(Adapter,LED_CTL_NO_LINK);
- #endif
- }
- else
- {
- // Turn off LED if RF is not ON.
- #ifdef TO_DO
- Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_POWER_OFF);
- #endif
- }
- break;
-
- case eRfOn:
- // Turn on RF we are still linked, which might happen when
- // we quickly turn off and on HW RF. 2006.05.12, by rcnjko.
- if( priv->ieee80211->state == IEEE80211_LINKED)
- {
- #ifdef TO_DO
- Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_LINK);
- #endif
- }
- else
- {
- // Turn off LED if RF is not ON.
- #ifdef TO_DO
- Adapter->HalFunc.LedControlHandler(Adapter, LED_CTL_NO_LINK);
- #endif
- }
- break;
-
- default:
- // do nothing.
- break;
- }// Switch RF state
-
- break;
-
- default:
- RT_TRACE(COMP_ERR, "SetRFPowerState8190(): Unknown RF type\n");
- break;
- }// Switch RFChipID
}
+ //printk("%s()priv->ieee80211->eRFPowerState:%s\n" ,__func__,priv->ieee80211->eRFPowerState == eRfOn ? "On" : "Off");
priv->SetRFPowerStateInProgress = false;
- RT_TRACE(COMP_POWER, "<=========== SetRFPowerState8190() bResult = %d!\n", bResult);
+ //RT_TRACE(COMP_PS, "<=========== SetRFPowerState8190() bResult = %d!\n", bResult);
return bResult;
}
diff --git a/drivers/staging/rtl8192e/r8190_rtl8256.h b/drivers/staging/rtl8192e/r8190_rtl8256.h
index 7d9095a70ae..ce49c606521 100644
--- a/drivers/staging/rtl8192e/r8190_rtl8256.h
+++ b/drivers/staging/rtl8192e/r8190_rtl8256.h
@@ -1,28 +1,33 @@
-/*
- This is part of the rtl8180-sa2400 driver
- released under the GPL (See file COPYING for details).
- Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
+/* r8190_rtl8256.h - rtl8256 radio frontend
+ *
+ * This is part of the rtl8180-sa2400 driver
+ * released under the GPL (See file COPYING for details).
+ * Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Many thanks to Realtek Corp. for their great support!
+ */
- This files contains programming code for the rtl8256
- radio frontend.
-
- *Many* thanks to Realtek Corp. for their great support!
-
-*/
-
-#ifndef RTL8225H
-#define RTL8225H
+#ifndef RTL8225_H
+#define RTL8225_H
#ifdef RTL8190P
-#define RTL819X_TOTAL_RF_PATH 4
+#define RTL819X_TOTAL_RF_PATH 4
#else
-#define RTL819X_TOTAL_RF_PATH 2 //for 8192E
+#define RTL819X_TOTAL_RF_PATH 2 /* for 8192E */
#endif
-extern void PHY_SetRF8256Bandwidth(struct net_device* dev , HT_CHANNEL_WIDTH Bandwidth);
-extern RT_STATUS PHY_RF8256_Config(struct net_device* dev);
-extern RT_STATUS phy_RF8256_Config_ParaFile(struct net_device* dev);
-extern void PHY_SetRF8256CCKTxPower(struct net_device* dev, u8 powerlevel);
-extern void PHY_SetRF8256OFDMTxPower(struct net_device* dev, u8 powerlevel);
-extern bool MgntActSet_RF_State(struct net_device* dev, RT_RF_POWER_STATE StateToSet, RT_RF_CHANGE_SOURCE ChangeSource);
-#endif
+extern void PHY_SetRF8256Bandwidth(struct net_device *dev,
+ HT_CHANNEL_WIDTH Bandwidth);
+
+extern RT_STATUS PHY_RF8256_Config(struct net_device *dev);
+
+extern RT_STATUS phy_RF8256_Config_ParaFile(struct net_device *dev);
+
+extern void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8 powerlevel);
+extern void PHY_SetRF8256OFDMTxPower(struct net_device *dev, u8 powerlevel);
+
+extern bool MgntActSet_RF_State(struct net_device *dev,
+ RT_RF_POWER_STATE StateToSet,
+ RT_RF_CHANGE_SOURCE ChangeSource);
+
+#endif /* RTL8225_H */
diff --git a/drivers/staging/rtl8192e/r8192E.h b/drivers/staging/rtl8192e/r8192E.h
index 61b6f250b91..f4be9cc1100 100644
--- a/drivers/staging/rtl8192e/r8192E.h
+++ b/drivers/staging/rtl8192e/r8192E.h
@@ -39,7 +39,7 @@
#include <linux/random.h>
#include <linux/version.h>
#include <asm/io.h>
-#include "ieee80211.h"
+#include "ieee80211/ieee80211.h"
@@ -1003,6 +1003,11 @@ typedef struct r8192_priv
int irq;
short irq_enabled;
struct ieee80211_device *ieee80211;
+#ifdef ENABLE_LPS
+ bool ps_force;
+ bool force_lps;
+ bool bdisable_nic;
+#endif
bool being_init_adapter;
u8 Rf_Mode;
short card_8192; /* O: rtl8192, 1:rtl8185 V B/C, 2:rtl8185 V D */
@@ -1477,7 +1482,7 @@ void write_nic_word(struct net_device *dev, int x,u16 y);
void write_nic_dword(struct net_device *dev, int x,u32 y);
void force_pci_posting(struct net_device *dev);
-void rtl8192_rtx_disable(struct net_device *);
+void rtl8192_halt_adapter(struct net_device *dev, bool reset);
void rtl8192_rx_enable(struct net_device *);
void rtl8192_tx_enable(struct net_device *);
@@ -1512,5 +1517,19 @@ short rtl8192_is_tx_queue_empty(struct net_device *dev);
#ifdef ENABLE_IPS
void IPSEnter(struct net_device *dev);
void IPSLeave(struct net_device *dev);
+void InactivePsWorkItemCallback(struct net_device *dev);
+void IPSLeave_wq(void *data);
+void ieee80211_ips_leave_wq(struct net_device *dev);
+void ieee80211_ips_leave(struct net_device *dev);
+#endif
+#ifdef ENABLE_LPS
+void LeisurePSEnter(struct net_device *dev);
+void LeisurePSLeave(struct net_device *dev);
#endif
+
+bool NicIFEnableNIC(struct net_device* dev);
+bool NicIFDisableNIC(struct net_device* dev);
+
+void rtl8192_irq_disable(struct net_device *dev);
+void PHY_SetRtl8192eRfOff(struct net_device* dev);
#endif
diff --git a/drivers/staging/rtl8192e/r8192E_core.c b/drivers/staging/rtl8192e/r8192E_core.c
index 0ca5d8b4f74..886105db8b7 100644
--- a/drivers/staging/rtl8192e/r8192E_core.c
+++ b/drivers/staging/rtl8192e/r8192E_core.c
@@ -66,7 +66,7 @@
#endif
#ifdef ENABLE_DOT11D
-#include "dot11d.h"
+#include "ieee80211/dot11d.h"
#endif
//set here to open your trace code. //WB
@@ -75,7 +75,7 @@ u32 rt_global_debug_component = \
// COMP_EPROM |
// COMP_PHY |
// COMP_RF |
- COMP_FIRMWARE |
+// COMP_FIRMWARE |
// COMP_TRACE |
// COMP_DOWN |
// COMP_SWBW |
@@ -343,6 +343,141 @@ void write_nic_word(struct net_device *dev, int x,u16 y)
#endif /* RTL_IO_MAP */
+u8 rtl8192e_ap_sec_type(struct ieee80211_device *ieee)
+{
+ //struct r8192_priv* priv = ieee80211_priv(dev);
+ //struct ieee80211_device *ieee = priv->ieee80211;
+
+ static u8 ccmp_ie[4] = {0x00,0x50,0xf2,0x04};
+ static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
+ int wpa_ie_len= ieee->wpa_ie_len;
+ struct ieee80211_crypt_data* crypt;
+ int encrypt;
+
+ crypt = ieee->crypt[ieee->tx_keyidx];
+
+ encrypt = (ieee->current_network.capability & WLAN_CAPABILITY_PRIVACY) ||\
+ (ieee->host_encrypt && crypt && crypt->ops && \
+ (0 == strcmp(crypt->ops->name,"WEP")));
+
+ /* simply judge */
+ if(encrypt && (wpa_ie_len == 0)) {
+ // wep encryption, no N mode setting */
+ return SEC_ALG_WEP;
+ } else if((wpa_ie_len != 0)) {
+ // parse pairwise key type */
+ if (((ieee->wpa_ie[0] == 0xdd) && (!memcmp(&(ieee->wpa_ie[14]),ccmp_ie,4))) ||
+ ((ieee->wpa_ie[0] == 0x30) && (!memcmp(&ieee->wpa_ie[10],ccmp_rsn_ie, 4))))
+ return SEC_ALG_CCMP;
+ else
+ return SEC_ALG_TKIP;
+ } else {
+ return SEC_ALG_NONE;
+ }
+}
+
+void
+rtl8192e_SetHwReg(struct net_device *dev,u8 variable,u8* val)
+{
+ struct r8192_priv* priv = ieee80211_priv(dev);
+
+ switch(variable)
+ {
+
+ case HW_VAR_BSSID:
+ write_nic_dword(dev, BSSIDR, ((u32*)(val))[0]);
+ write_nic_word(dev, BSSIDR+2, ((u16*)(val+2))[0]);
+ break;
+
+ case HW_VAR_MEDIA_STATUS:
+ {
+ RT_OP_MODE OpMode = *((RT_OP_MODE *)(val));
+ //LED_CTL_MODE LedAction = LED_CTL_NO_LINK;
+ u8 btMsr = read_nic_byte(dev, MSR);
+
+ btMsr &= 0xfc;
+
+ switch(OpMode)
+ {
+ case RT_OP_MODE_INFRASTRUCTURE:
+ btMsr |= MSR_INFRA;
+ //LedAction = LED_CTL_LINK;
+ break;
+
+ case RT_OP_MODE_IBSS:
+ btMsr |= MSR_ADHOC;
+ // led link set seperate
+ break;
+
+ case RT_OP_MODE_AP:
+ btMsr |= MSR_AP;
+ //LedAction = LED_CTL_LINK;
+ break;
+
+ default:
+ btMsr |= MSR_NOLINK;
+ break;
+ }
+
+ write_nic_byte(dev, MSR, btMsr);
+
+ //priv->ieee80211->LedControlHandler(dev, LedAction);
+ }
+ break;
+
+ case HW_VAR_CECHK_BSSID:
+ {
+ u32 RegRCR, Type;
+
+ Type = ((u8*)(val))[0];
+ //priv->ieee80211->GetHwRegHandler(dev, HW_VAR_RCR, (u8*)(&RegRCR));
+ RegRCR = read_nic_dword(dev,RCR);
+ priv->ReceiveConfig = RegRCR;
+
+ if (Type == true)
+ RegRCR |= (RCR_CBSSID);
+ else if (Type == false)
+ RegRCR &= (~RCR_CBSSID);
+
+ //priv->ieee80211->SetHwRegHandler( dev, HW_VAR_RCR, (u8*)(&RegRCR) );
+ write_nic_dword(dev, RCR,RegRCR);
+ priv->ReceiveConfig = RegRCR;
+
+ }
+ break;
+
+ case HW_VAR_SLOT_TIME:
+ {
+ //PSTA_QOS pStaQos = Adapter->MgntInfo.pStaQos;
+ //AC_CODING eACI;
+
+ priv->slot_time = val[0];
+ write_nic_byte(dev, SLOT_TIME, val[0]);
+
+ }
+ break;
+
+ case HW_VAR_ACK_PREAMBLE:
+ {
+ u32 regTmp = 0;
+ priv->short_preamble = (bool)(*(u8*)val );
+ regTmp = priv->basic_rate;
+ if (priv->short_preamble)
+ regTmp |= BRSR_AckShortPmb;
+ write_nic_dword(dev, RRSR, regTmp);
+ }
+ break;
+
+ case HW_VAR_CPU_RST:
+ write_nic_dword(dev, CPU_GEN, ((u32*)(val))[0]);
+ break;
+
+ default:
+ break;
+ }
+
+}
+
///////////////////////////////////////////////////////////
@@ -365,11 +500,6 @@ void rtl8192_restart(struct work_struct *work);
//void rtl8192_rq_tx_ack(struct work_struct *work);
void watch_dog_timer_callback(unsigned long data);
-#ifdef ENABLE_IPS
-void IPSEnter(struct net_device *dev);
-void IPSLeave(struct net_device *dev);
-void InactivePsWorkItemCallback(struct net_device *dev);
-#endif
/****************************************************************************
-----------------------------PROCFS STUFF-------------------------
*****************************************************************************/
@@ -707,7 +837,7 @@ static void rtl8192_irq_enable(struct net_device *dev)
}
-static void rtl8192_irq_disable(struct net_device *dev)
+void rtl8192_irq_disable(struct net_device *dev)
{
struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
@@ -717,6 +847,7 @@ static void rtl8192_irq_disable(struct net_device *dev)
}
+#if 0
static void rtl8192_set_mode(struct net_device *dev,int mode)
{
u8 ecmd;
@@ -727,7 +858,7 @@ static void rtl8192_set_mode(struct net_device *dev,int mode)
ecmd=ecmd &~ (1<<EPROM_CK_SHIFT);
write_nic_byte(dev, EPROM_CMD, ecmd);
}
-
+#endif
void rtl8192_update_msr(struct net_device *dev)
{
@@ -861,7 +992,7 @@ static void rtl8192_free_tx_ring(struct net_device *dev, unsigned int prio)
ring->desc = NULL;
}
-
+#if 0
static void rtl8192_beacon_disable(struct net_device *dev)
{
struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
@@ -873,38 +1004,116 @@ static void rtl8192_beacon_disable(struct net_device *dev)
reg &= ~(IMR_BcnInt | IMR_BcnInt | IMR_TBDOK | IMR_TBDER);
write_nic_dword(priv->ieee80211->dev, INTA_MASK, reg);
}
+#endif
+
+void PHY_SetRtl8192eRfOff(struct net_device* dev )
+{
+ //struct r8192_priv *priv = ieee80211_priv(dev);
+
+ //disable RF-Chip A/B
+ rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0);
+ //analog to digital off, for power save
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x0);
+ //digital to analog off, for power save
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x18, 0x0);
+ //rx antenna off
+ rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0xf, 0x0);
+ //rx antenna off
+ rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0xf, 0x0);
+ //analog to digital part2 off, for power save
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x0);
+ rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x4, 0x0);
+ // Analog parameter!!Change bias and Lbus control.
+ write_nic_byte(dev, ANAPAR_FOR_8192PciE, 0x07);
+
+}
-void rtl8192_rtx_disable(struct net_device *dev)
+void rtl8192_halt_adapter(struct net_device *dev, bool reset)
{
- u8 cmd;
+ //u8 cmd;
struct r8192_priv *priv = ieee80211_priv(dev);
- int i;
+ int i;
+ u8 OpMode;
+ u8 u1bTmp;
+ u32 ulRegRead;
+
+ OpMode = RT_OP_MODE_NO_LINK;
+ priv->ieee80211->SetHwRegHandler(dev, HW_VAR_MEDIA_STATUS, &OpMode);
+#if 1
+ if(!priv->ieee80211->bSupportRemoteWakeUp)
+ {
+ u1bTmp = 0x0; // disable tx/rx. In 8185 we write 0x10 (Reset bit), but here we make reference to WMAC and wirte 0x0. 2006.11.21 Emily
+ //priv->ieee80211->SetHwRegHandler(dev, HW_VAR_COMMAND, &u1bTmp ); // Using HW_VAR_COMMAND instead of writing CMDR directly. Rewrited by Annie, 2006-04-07.
+ write_nic_byte(dev, CMDR, u1bTmp);
+ }
+#else
cmd=read_nic_byte(dev,CMDR);
-// if(!priv->ieee80211->bSupportRemoteWakeUp) {
- write_nic_byte(dev, CMDR, cmd &~ \
- (CR_TE|CR_RE));
-// }
- force_pci_posting(dev);
- mdelay(30);
+ write_nic_byte(dev, CMDR, cmd &~ (CR_TE|CR_RE));
+#endif
- for(i = 0; i < MAX_QUEUE_SIZE; i++) {
- skb_queue_purge(&priv->ieee80211->skb_waitQ [i]);
- }
- for(i = 0; i < MAX_QUEUE_SIZE; i++) {
- skb_queue_purge(&priv->ieee80211->skb_aggQ [i]);
- }
+ mdelay(20);
+ if(!reset)
+ {
+ //PlatformStallExecution(150000);
+ mdelay(150);
+
+#ifdef RTL8192E
+ priv->bHwRfOffAction = 2;
+#endif
+
+ //
+ // Call MgntActSet_RF_State instead to prevent RF config race condition.
+ // By Bruce, 2008-01-17.
+ //
+ if(!priv->ieee80211->bSupportRemoteWakeUp)
+ {
+ //MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_INIT);
+ //MgntActSet_RF_State(Adapter, eRfOff, Adapter->MgntInfo.RfOffReason);
+ //if(Adapter->HardwareType == HARDWARE_TYPE_RTL8190P)
+
+ PHY_SetRtl8192eRfOff(dev);
+
+ // 2006.11.30. System reset bit
+ //priv->ieee80211->GetHwRegHandler(dev, HW_VAR_CPU_RST, (u32*)(&ulRegRead) );
+ ulRegRead = read_nic_dword(dev,CPU_GEN);
+ ulRegRead|=CPU_GEN_SYSTEM_RESET;
+ //priv->ieee80211->SetHwRegHandler(dev, HW_VAR_CPU_RST, &ulRegRead);
+ write_nic_dword(dev,CPU_GEN, ulRegRead);
+ }
+ else
+ {
+ //2008.06.03 for WOL
+ write_nic_dword(dev, WFCRC0, 0xffffffff);
+ write_nic_dword(dev, WFCRC1, 0xffffffff);
+ write_nic_dword(dev, WFCRC2, 0xffffffff);
+
+ //Write PMR register
+ write_nic_byte(dev, PMR, 0x5);
+ //Disable tx, enanble rx
+ write_nic_byte(dev, MacBlkCtrl, 0xa);
+ }
+ }
+
+ for(i = 0; i < MAX_QUEUE_SIZE; i++) {
+ skb_queue_purge(&priv->ieee80211->skb_waitQ [i]);
+ }
+ for(i = 0; i < MAX_QUEUE_SIZE; i++) {
+ skb_queue_purge(&priv->ieee80211->skb_aggQ [i]);
+ }
skb_queue_purge(&priv->skb_queue);
return;
}
+#if 0
static void rtl8192_reset(struct net_device *dev)
{
rtl8192_irq_disable(dev);
printk("This is RTL819xP Reset procedure\n");
}
+#endif
static u16 rtl_rate[] = {10,20,55,110,60,90,120,180,240,360,480,540};
inline u16 rtl8192_rate2rate(short rate)
@@ -954,6 +1163,12 @@ static void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
/* shall not be referred by command packet */
assert(queue_index != TXCMD_QUEUE);
+ if((priv->bHwRadioOff == true)||(!priv->up))
+ {
+ kfree_skb(skb);
+ return;
+ }
+
//spin_lock_irqsave(&priv->tx_lock,flags);
memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
@@ -996,6 +1211,13 @@ static int rtl8192_hard_start_xmit(struct sk_buff *skb,struct net_device *dev)
cb_desc *tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
u8 queue_index = tcb_desc->queue_index;
+ if(queue_index != TXCMD_QUEUE){
+ if((priv->bHwRadioOff == true)||(!priv->up))
+ {
+ kfree_skb(skb);
+ return 0;
+ }
+ }
//spin_lock_irqsave(&priv->tx_lock,flags);
@@ -1379,6 +1601,15 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff* skb)
u8* pda_addr = NULL;
int idx;
+ if(priv->bdisable_nic){
+ RT_TRACE(COMP_ERR,"%s: ERR!! Nic is disabled! Can't tx packet len=%d qidx=%d!!!\n", __FUNCTION__, skb->len, tcb_desc->queue_index);
+ return skb->len;
+ }
+
+#ifdef ENABLE_LPS
+ priv->ieee80211->bAwakePktSent = true;
+#endif
+
mapping = pci_map_single(priv->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
/* collect the tx packets statitcs */
pda_addr = ((u8*)skb->data) + sizeof(TX_FWINFO_8190PCI);
@@ -1481,6 +1712,7 @@ short rtl8192_tx(struct net_device *dev, struct sk_buff* skb)
if((pdesc->OWN == 1) && (tcb_desc->queue_index != BEACON_QUEUE)) {
RT_TRACE(COMP_ERR,"No more TX desc@%d, ring->idx = %d,idx = %d,%x", \
tcb_desc->queue_index,ring->idx, idx,skb->len);
+ spin_unlock_irqrestore(&priv->irq_th_lock,flags);
return skb->len;
}
@@ -1575,7 +1807,7 @@ static short rtl8192_alloc_rx_desc_ring(struct net_device *dev)
return 0;
priv->rx_buf[i] = skb;
mapping = (dma_addr_t *)skb->cb;
- *mapping = pci_map_single(priv->pdev, skb->tail,//skb_tail_pointer(skb),
+ *mapping = pci_map_single(priv->pdev, skb_tail_pointer(skb),
priv->rxbuffersize, PCI_DMA_FROMDEVICE);
entry->BufferAddress = cpu_to_le32(*mapping);
@@ -1779,7 +2011,7 @@ static void rtl8192_qos_activate(struct work_struct * work)
(((u32)(qos_parameters->cw_max[i]))<< AC_PARAM_ECW_MAX_OFFSET)|
(((u32)(qos_parameters->cw_min[i]))<< AC_PARAM_ECW_MIN_OFFSET)|
((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET));
- printk("===>u4bAcParam:%x, ", u4bAcParam);
+ //printk("===>u4bAcParam:%x, ", u4bAcParam);
write_nic_dword(dev, WDCAPARA_ADD[i], u4bAcParam);
//write_nic_dword(dev, WDCAPARA_ADD[i], 0x005e4332);
}
@@ -1964,11 +2196,24 @@ void rtl8192_update_ratr_table(struct net_device* dev)
write_nic_byte(dev, UFWP, 1);
}
+#if 0
static u8 ccmp_ie[4] = {0x00,0x50,0xf2,0x04};
static u8 ccmp_rsn_ie[4] = {0x00, 0x0f, 0xac, 0x04};
+#endif
+
static bool GetNmodeSupportBySecCfg8190Pci(struct net_device*dev)
{
#if 1
+
+ struct r8192_priv *priv = ieee80211_priv(dev);
+ struct ieee80211_device *ieee = priv->ieee80211;
+ if (ieee->rtllib_ap_sec_type &&
+ (ieee->rtllib_ap_sec_type(ieee)&(SEC_ALG_WEP|SEC_ALG_TKIP))) {
+ return false;
+ } else {
+ return true;
+ }
+#else
struct r8192_priv* priv = ieee80211_priv(dev);
struct ieee80211_device* ieee = priv->ieee80211;
int wpa_ie_len= ieee->wpa_ie_len;
@@ -1995,18 +2240,6 @@ static bool GetNmodeSupportBySecCfg8190Pci(struct net_device*dev)
return true;
}
-#if 0
- //In here we discuss with SD4 David. He think we still can send TKIP in broadcast group key in MCS rate.
- //We can't force in G mode if Pairwie key is AES and group key is TKIP
- if((pSecInfo->GroupEncAlgorithm == WEP104_Encryption) || (pSecInfo->GroupEncAlgorithm == WEP40_Encryption) ||
- (pSecInfo->PairwiseEncAlgorithm == WEP104_Encryption) ||
- (pSecInfo->PairwiseEncAlgorithm == WEP40_Encryption) || (pSecInfo->PairwiseEncAlgorithm == TKIP_Encryption))
- {
- return false;
- }
- else
- return true;
-#endif
return true;
#endif
}
@@ -2080,7 +2313,7 @@ static void rtl8192_SetWirelessMode(struct net_device* dev, u8 wireless_mode)
wireless_mode = WIRELESS_MODE_B;
}
}
-#ifdef TO_DO_LIST //// TODO: this function doesn't work well at this time, we shoud wait for FPGA
+#ifdef TO_DO_LIST //// TODO: this function doesn't work well at this time, we should wait for FPGA
ActUpdateChannelAccessSetting( pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting );
#endif
priv->ieee80211->mode = wireless_mode;
@@ -2127,7 +2360,19 @@ short rtl8192_is_tx_queue_empty(struct net_device *dev)
}
static void rtl8192_hw_sleep_down(struct net_device *dev)
{
- RT_TRACE(COMP_POWER, "%s()============>come to sleep down\n", __FUNCTION__);
+ struct r8192_priv *priv = ieee80211_priv(dev);
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&priv->rf_ps_lock,flags);
+ if (priv->RFChangeInProgress) {
+ spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
+ RT_TRACE(COMP_RF, "rtl8192_hw_sleep_down(): RF Change in progress! \n");
+ printk("rtl8192_hw_sleep_down(): RF Change in progress!\n");
+ return;
+ }
+ spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
+ //RT_TRACE(COMP_PS, "%s()============>come to sleep down\n", __FUNCTION__);
+
MgntActSet_RF_State(dev, eRfSleep, RF_CHANGE_BY_PS);
}
static void rtl8192_hw_sleep_wq (struct work_struct *work)
@@ -2138,21 +2383,29 @@ static void rtl8192_hw_sleep_wq (struct work_struct *work)
struct delayed_work *dwork = container_of(work,struct delayed_work,work);
struct ieee80211_device *ieee = container_of(dwork,struct ieee80211_device,hw_sleep_wq);
struct net_device *dev = ieee->dev;
- //printk("=========>%s()\n", __FUNCTION__);
+
rtl8192_hw_sleep_down(dev);
}
-// printk("dev is %d\n",dev);
-// printk("&*&(^*(&(&=========>%s()\n", __FUNCTION__);
+
static void rtl8192_hw_wakeup(struct net_device* dev)
{
-// u32 flags = 0;
+ struct r8192_priv *priv = ieee80211_priv(dev);
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&priv->rf_ps_lock,flags);
+ if (priv->RFChangeInProgress) {
+ spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
+ RT_TRACE(COMP_RF, "rtl8192_hw_wakeup(): RF Change in progress! \n");
+ printk("rtl8192_hw_wakeup(): RF Change in progress! schedule wake up task again\n");
+ queue_delayed_work(priv->ieee80211->wq,&priv->ieee80211->hw_wakeup_wq,MSECS(10));//PowerSave is not supported if kernel version is below 2.6.20
+ return;
+ }
+ spin_unlock_irqrestore(&priv->rf_ps_lock,flags);
-// spin_lock_irqsave(&priv->ps_lock,flags);
- RT_TRACE(COMP_POWER, "%s()============>come to wake up\n", __FUNCTION__);
+ //RT_TRACE(COMP_PS, "%s()============>come to wake up\n", __FUNCTION__);
MgntActSet_RF_State(dev, eRfOn, RF_CHANGE_BY_PS);
- //FIXME: will we send package stored while nic is sleep?
-// spin_unlock_irqrestore(&priv->ps_lock,flags);
}
+
void rtl8192_hw_wakeup_wq (struct work_struct *work)
{
// struct r8180_priv *priv = container_of(work, struct r8180_priv, watch_dog_wq);
@@ -2169,7 +2422,6 @@ void rtl8192_hw_wakeup_wq (struct work_struct *work)
#define MAX_SLEEP_TIME 10000
static void rtl8192_hw_to_sleep(struct net_device *dev, u32 th, u32 tl)
{
-
struct r8192_priv *priv = ieee80211_priv(dev);
u32 rb = jiffies;
@@ -2177,58 +2429,55 @@ static void rtl8192_hw_to_sleep(struct net_device *dev, u32 th, u32 tl)
spin_lock_irqsave(&priv->ps_lock,flags);
- /* Writing HW register with 0 equals to disable
- * the timer, that is not really what we want
- */
- tl -= MSECS(4+16+7);
-
- //if(tl == 0) tl = 1;
-
- /* FIXME HACK FIXME HACK */
-// force_pci_posting(dev);
- //mdelay(1);
-
-// rb = read_nic_dword(dev, TSFTR);
+ // Writing HW register with 0 equals to disable
+ // the timer, that is not really what we want
+ //
+ tl -= MSECS(8+16+7);
- /* If the interval in witch we are requested to sleep is too
- * short then give up and remain awake
- */
+ // If the interval in witch we are requested to sleep is too
+ // short then give up and remain awake
+ // when we sleep after send null frame, the timer will be too short to sleep.
+ //
if(((tl>=rb)&& (tl-rb) <= MSECS(MIN_SLEEP_TIME))
- ||((rb>tl)&& (rb-tl) < MSECS(MIN_SLEEP_TIME))) {
+ ||((rb>tl)&& (rb-tl) < MSECS(MIN_SLEEP_TIME))) {
spin_unlock_irqrestore(&priv->ps_lock,flags);
- printk("too short to sleep\n");
+ printk("too short to sleep::%x, %x, %lx\n",tl, rb, MSECS(MIN_SLEEP_TIME));
return;
}
-// write_nic_dword(dev, TimerInt, tl);
-// rb = read_nic_dword(dev, TSFTR);
- {
- u32 tmp = (tl>rb)?(tl-rb):(rb-tl);
- // if (tl<rb)
- queue_delayed_work(priv->ieee80211->wq, &priv->ieee80211->hw_wakeup_wq, tmp); //as tl may be less than rb
- }
- /* if we suspect the TimerInt is gone beyond tl
- * while setting it, then give up
- */
-#if 1
if(((tl > rb) && ((tl-rb) > MSECS(MAX_SLEEP_TIME)))||
- ((tl < rb) && ((rb-tl) > MSECS(MAX_SLEEP_TIME)))) {
+ ((tl < rb) && (tl>MSECS(69)) && ((rb-tl) > MSECS(MAX_SLEEP_TIME)))||
+ ((tl<rb)&&(tl<MSECS(69))&&((tl+0xffffffff-rb)>MSECS(MAX_SLEEP_TIME)))) {
printk("========>too long to sleep:%x, %x, %lx\n", tl, rb, MSECS(MAX_SLEEP_TIME));
spin_unlock_irqrestore(&priv->ps_lock,flags);
return;
}
-#endif
-// if(priv->rf_sleep)
-// priv->rf_sleep(dev);
-
- //printk("<=========%s()\n", __FUNCTION__);
- queue_delayed_work(priv->ieee80211->wq, (void *)&priv->ieee80211->hw_sleep_wq,0);
+ {
+ u32 tmp = (tl>rb)?(tl-rb):(rb-tl);
+ queue_delayed_work(priv->ieee80211->wq,
+ &priv->ieee80211->hw_wakeup_wq,tmp);
+ //PowerSave not supported when kernel version less 2.6.20
+ }
+ queue_delayed_work(priv->ieee80211->wq,
+ (void *)&priv->ieee80211->hw_sleep_wq,0);
spin_unlock_irqrestore(&priv->ps_lock,flags);
+
}
static void rtl8192_init_priv_variable(struct net_device* dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
u8 i;
+ PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+
+ // Default Halt the NIC if RF is OFF.
+ pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_HALT_NIC;
+ pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_CLK_REQ;
+ pPSC->RegRfPsLevel |= RT_RF_OFF_LEVL_ASPM;
+ pPSC->RegRfPsLevel |= RT_RF_LPS_LEVEL_ASPM;
+ pPSC->bLeisurePs = true;
+ pPSC->RegMaxLPSAwakeIntvl = 5;
+ priv->bHwRadioOff = false;
+
priv->being_init_adapter = false;
priv->txbuffsize = 1600;//1024;
priv->txfwbuffersize = 4096;
@@ -2328,6 +2577,17 @@ static void rtl8192_init_priv_variable(struct net_device* dev)
//added by amy
priv->ieee80211->InitialGainHandler = InitialGain819xPci;
+#ifdef ENABLE_IPS
+ priv->ieee80211->ieee80211_ips_leave_wq = ieee80211_ips_leave_wq;
+ priv->ieee80211->ieee80211_ips_leave = ieee80211_ips_leave;
+#endif
+#ifdef ENABLE_LPS
+ priv->ieee80211->LeisurePSLeave = LeisurePSLeave;
+#endif//ENABL
+
+ priv->ieee80211->SetHwRegHandler = rtl8192e_SetHwReg;
+ priv->ieee80211->rtllib_ap_sec_type = rtl8192e_ap_sec_type;
+
priv->card_type = USB;
{
priv->ShortRetryLimit = 0x30;
@@ -2400,6 +2660,10 @@ static void rtl8192_init_priv_task(struct net_device* dev)
priv->priv_wq = create_workqueue(DRV_NAME);
#endif
+#ifdef ENABLE_IPS
+ INIT_WORK(&priv->ieee80211->ips_leave_wq, (void*)IPSLeave_wq);
+#endif
+
// INIT_WORK(&priv->reset_wq, (void(*)(void*)) rtl8192_restart);
INIT_WORK(&priv->reset_wq, rtl8192_restart);
// INIT_DELAYED_WORK(&priv->watch_dog_wq, hal_dm_watchdog);
@@ -2550,10 +2814,7 @@ static void rtl8192_read_eeprom_info(struct net_device* dev)
memcpy(dev->dev_addr, bMac_Tmp_Addr, 6);
}
- RT_TRACE(COMP_INIT, "Permanent Address = %02x-%02x-%02x-%02x-%02x-%02x\n",
- dev->dev_addr[0], dev->dev_addr[1],
- dev->dev_addr[2], dev->dev_addr[3],
- dev->dev_addr[4], dev->dev_addr[5]);
+ RT_TRACE(COMP_INIT, "Permanent Address = %pM\n", dev->dev_addr);
//2 TX Power Check EEPROM Fail or not
if(priv->card_8192_version > VERSION_8190_BD) {
@@ -2926,13 +3187,14 @@ static void rtl8192_read_eeprom_info(struct net_device* dev)
#endif
break;
}
-/*
- //2008.06.03, for WOL
+
+
if( priv->eeprom_vid == 0x1186 && priv->eeprom_did == 0x3304)
- priv->ieee80211->bSupportRemoteWakeUp = TRUE;
+ priv->ieee80211->bSupportRemoteWakeUp = true;
else
- priv->ieee80211->bSupportRemoteWakeUp = FALSE;
-*/
+ priv->ieee80211->bSupportRemoteWakeUp = false;
+
+
RT_TRACE(COMP_INIT, "RegChannelPlan(%d)\n", priv->RegChannelPlan);
RT_TRACE(COMP_INIT, "ChannelPlan = %d \n", priv->ChannelPlan);
RT_TRACE(COMP_INIT, "LedStrategy = %d \n", priv->LedStrategy);
@@ -4006,12 +4268,19 @@ static void rtl819x_ifsilentreset(struct net_device *dev)
struct ieee80211_device *ieee = priv->ieee80211;
+ return;
+
// 2007.07.20. If we need to check CCK stop, please uncomment this line.
//bStuck = Adapter->HalFunc.CheckHWStopHandler(Adapter);
if(priv->ResetProgress==RESET_TYPE_NORESET)
{
RESET_START:
+#ifdef ENABLE_LPS
+ //LZM for PS-Poll AID issue. 090429
+ if(priv->ieee80211->state == IEEE80211_LINKED)
+ LeisurePSLeave(dev);
+#endif
RT_TRACE(COMP_RESET,"=========>Reset progress!! \n");
@@ -4051,9 +4320,9 @@ RESET_START:
}
else{
printk("ieee->state is NOT LINKED\n");
- ieee80211_softmac_stop_protocol(priv->ieee80211);
+ ieee80211_softmac_stop_protocol(priv->ieee80211,true);
}
- rtl8192_rtx_disable(dev);
+ rtl8192_halt_adapter(dev, true);
up(&priv->wx_sem);
RT_TRACE(COMP_RESET,"%s():<==========down process is finished\n",__FUNCTION__);
RT_TRACE(COMP_RESET,"%s():===========>start to up the driver\n",__FUNCTION__);
@@ -4150,6 +4419,128 @@ void InactivePsWorkItemCallback(struct net_device *dev)
RT_TRACE(COMP_POWER, "InactivePsWorkItemCallback() <--------- \n");
}
+#ifdef ENABLE_LPS
+//
+// Change current and default preamble mode.
+// 2005.01.06, by rcnjko.
+//
+bool MgntActSet_802_11_PowerSaveMode(struct net_device *dev, u8 rtPsMode)
+{
+ struct r8192_priv *priv = ieee80211_priv(dev);
+ //PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+ //u8 RpwmVal, FwPwrMode;
+
+ // Currently, we do not change power save mode on IBSS mode.
+ if(priv->ieee80211->iw_mode == IW_MODE_ADHOC)
+ {
+ return false;
+ }
+
+ //
+ // <RJ_NOTE> If we make HW to fill up the PwrMgt bit for us,
+ // some AP will not response to our mgnt frames with PwrMgt bit set,
+ // e.g. cannot associate the AP.
+ // So I commented out it. 2005.02.16, by rcnjko.
+ //
+// // Change device's power save mode.
+// Adapter->HalFunc.SetPSModeHandler( Adapter, rtPsMode );
+
+ // Update power save mode configured.
+ //RT_TRACE(COMP_LPS,"%s(): set ieee->ps = %x\n",__FUNCTION__,rtPsMode);
+ if(!priv->ps_force) {
+ priv->ieee80211->ps = rtPsMode;
+ }
+
+ // Awake immediately
+ if(priv->ieee80211->sta_sleep != 0 && rtPsMode == IEEE80211_PS_DISABLED)
+ {
+ unsigned long flags;
+
+ //PlatformSetTimer(Adapter, &(pMgntInfo->AwakeTimer), 0);
+ // Notify the AP we awke.
+ rtl8192_hw_wakeup(dev);
+ priv->ieee80211->sta_sleep = 0;
+
+ spin_lock_irqsave(&(priv->ieee80211->mgmt_tx_lock), flags);
+ printk("LPS leave: notify AP we are awaked ++++++++++ SendNullFunctionData\n");
+ ieee80211_sta_ps_send_null_frame(priv->ieee80211, 0);
+ spin_unlock_irqrestore(&(priv->ieee80211->mgmt_tx_lock), flags);
+ }
+
+ return true;
+}
+
+//================================================================================
+// Leisure Power Save in linked state.
+//================================================================================
+
+//
+// Description:
+// Enter the leisure power save mode.
+//
+void LeisurePSEnter(struct net_device *dev)
+{
+ struct r8192_priv *priv = ieee80211_priv(dev);
+ PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+
+ //RT_TRACE(COMP_PS, "LeisurePSEnter()...\n");
+ //RT_TRACE(COMP_PS, "pPSC->bLeisurePs = %d, ieee->ps = %d,pPSC->LpsIdleCount is %d,RT_CHECK_FOR_HANG_PERIOD is %d\n",
+ // pPSC->bLeisurePs, priv->ieee80211->ps,pPSC->LpsIdleCount,RT_CHECK_FOR_HANG_PERIOD);
+
+ if(!((priv->ieee80211->iw_mode == IW_MODE_INFRA) &&
+ (priv->ieee80211->state == IEEE80211_LINKED)) ||
+ (priv->ieee80211->iw_mode == IW_MODE_ADHOC) ||
+ (priv->ieee80211->iw_mode == IW_MODE_MASTER))
+ return;
+
+ if (pPSC->bLeisurePs)
+ {
+ // Idle for a while if we connect to AP a while ago.
+ if(pPSC->LpsIdleCount >= RT_CHECK_FOR_HANG_PERIOD) // 4 Sec
+ {
+
+ if(priv->ieee80211->ps == IEEE80211_PS_DISABLED)
+ {
+
+ //RT_TRACE(COMP_LPS, "LeisurePSEnter(): Enter 802.11 power save mode...\n");
+ MgntActSet_802_11_PowerSaveMode(dev, IEEE80211_PS_MBCAST|IEEE80211_PS_UNICAST);
+
+ }
+ }
+ else
+ pPSC->LpsIdleCount++;
+ }
+}
+
+
+//
+// Description:
+// Leave the leisure power save mode.
+//
+void LeisurePSLeave(struct net_device *dev)
+{
+ struct r8192_priv *priv = ieee80211_priv(dev);
+ PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+
+
+ //RT_TRACE(COMP_PS, "LeisurePSLeave()...\n");
+ //RT_TRACE(COMP_PS, "pPSC->bLeisurePs = %d, ieee->ps = %d\n",
+ // pPSC->bLeisurePs, priv->ieee80211->ps);
+
+ if (pPSC->bLeisurePs)
+ {
+ if(priv->ieee80211->ps != IEEE80211_PS_DISABLED)
+ {
+ // move to lps_wakecomplete()
+ //RT_TRACE(COMP_LPS, "LeisurePSLeave(): Busy Traffic , Leave 802.11 power save..\n");
+ MgntActSet_802_11_PowerSaveMode(dev, IEEE80211_PS_DISABLED);
+
+ }
+ }
+}
+#endif
+
+
//
// Description:
// Enter the inactive power save mode. RF will be off
@@ -4178,6 +4569,7 @@ IPSEnter(struct net_device *dev)
&& (priv->ieee80211->state != IEEE80211_LINKED) )
{
RT_TRACE(COMP_RF,"IPSEnter(): Turn off RF.\n");
+ //printk("IPSEnter(): Turn off RF.\n");
pPSC->eInactivePowerState = eRfOff;
// queue_work(priv->priv_wq,&(pPSC->InactivePsWorkItem));
InactivePsWorkItemCallback(dev);
@@ -4203,12 +4595,53 @@ IPSLeave(struct net_device *dev)
if (rtState != eRfOn && !pPSC->bSwRfProcessing && priv->ieee80211->RfOffReason <= RF_CHANGE_BY_IPS)
{
RT_TRACE(COMP_POWER, "IPSLeave(): Turn on RF.\n");
+ //printk("IPSLeave(): Turn on RF.\n");
pPSC->eInactivePowerState = eRfOn;
// queue_work(priv->priv_wq,&(pPSC->InactivePsWorkItem));
InactivePsWorkItemCallback(dev);
}
}
}
+
+void IPSLeave_wq(void *data)
+{
+ struct ieee80211_device *ieee = container_of(data,struct ieee80211_device,ips_leave_wq);
+ struct net_device *dev = ieee->dev;
+
+ struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
+ down(&priv->ieee80211->ips_sem);
+ IPSLeave(dev);
+ up(&priv->ieee80211->ips_sem);
+}
+
+void ieee80211_ips_leave_wq(struct net_device *dev)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
+ RT_RF_POWER_STATE rtState;
+ rtState = priv->ieee80211->eRFPowerState;
+
+ if(priv->ieee80211->PowerSaveControl.bInactivePs){
+ if(rtState == eRfOff){
+ if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
+ {
+ RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
+ return;
+ }
+ else{
+ printk("=========>%s(): IPSLeave\n",__FUNCTION__);
+ queue_work(priv->ieee80211->wq,&priv->ieee80211->ips_leave_wq);
+ }
+ }
+ }
+}
+//added by amy 090331 end
+void ieee80211_ips_leave(struct net_device *dev)
+{
+ struct r8192_priv *priv = (struct r8192_priv *)ieee80211_priv(dev);
+ down(&priv->ieee80211->ips_sem);
+ IPSLeave(dev);
+ up(&priv->ieee80211->ips_sem);
+}
#endif
static void rtl819x_update_rxcounts(
@@ -4244,15 +4677,23 @@ void rtl819x_watchdog_wqcallback(struct work_struct *work)
unsigned long flags;
bool bBusyTraffic = false;
static u8 last_time = 0;
+ bool bEnterPS = false;
+
+ if((!priv->up) || (priv->bHwRadioOff == true))
+ return;
+
if(!priv->up)
return;
hal_dm_watchdog(dev);
#ifdef ENABLE_IPS
// printk("watch_dog ENABLE_IPS\n");
if(ieee->actscanning == false){
- if((ieee->iw_mode != IW_MODE_ADHOC) && (ieee->state == IEEE80211_NOLINK) && (ieee->beinretry == false) && (ieee->eRFPowerState == eRfOn) && !ieee->is_set_key){
+ //printk("%d,%d,%d,%d\n", ieee->eRFPowerState, ieee->is_set_key, ieee->proto_stoppping, ieee->wx_set_enc);
+ if((ieee->iw_mode == IW_MODE_INFRA) && (ieee->state == IEEE80211_NOLINK) &&\
+ (ieee->eRFPowerState == eRfOn)&&!ieee->is_set_key &&\
+ (!ieee->proto_stoppping) && !ieee->wx_set_enc){
if(ieee->PowerSaveControl.ReturnPoint == IPS_CALLBACK_NONE){
- printk("====================>haha:IPSEnter()\n");
+ //printk("====================>haha:IPSEnter()\n");
IPSEnter(dev);
//ieee80211_stop_scan(priv->ieee80211);
}
@@ -4262,14 +4703,49 @@ void rtl819x_watchdog_wqcallback(struct work_struct *work)
{//to get busy traffic condition
if(ieee->state == IEEE80211_LINKED)
{
- if( ieee->LinkDetectInfo.NumRxOkInPeriod> 666 ||
- ieee->LinkDetectInfo.NumTxOkInPeriod> 666 ) {
+ if( ieee->LinkDetectInfo.NumRxOkInPeriod> 100 ||
+ ieee->LinkDetectInfo.NumTxOkInPeriod> 100 ) {
bBusyTraffic = true;
}
+#ifdef ENABLE_LPS
+ //added by amy for Leisure PS
+ if( ((ieee->LinkDetectInfo.NumRxUnicastOkInPeriod + ieee->LinkDetectInfo.NumTxOkInPeriod) > 8 ) ||
+ (ieee->LinkDetectInfo.NumRxUnicastOkInPeriod > 2) )
+ {
+ //printk("ieee->LinkDetectInfo.NumRxUnicastOkInPeriod is %d,ieee->LinkDetectInfo.NumTxOkInPeriod is %d\n",
+ // ieee->LinkDetectInfo.NumRxUnicastOkInPeriod,ieee->LinkDetectInfo.NumTxOkInPeriod);
+ bEnterPS= false;
+ }
+ else
+ {
+ bEnterPS= true;
+ }
+
+ //printk("***bEnterPS = %d\n", bEnterPS);
+ // LeisurePS only work in infra mode.
+ if(bEnterPS)
+ {
+ LeisurePSEnter(dev);
+ }
+ else
+ {
+ LeisurePSLeave(dev);
+ }
+#endif
+
+ }
+ else
+ {
+#ifdef ENABLE_LPS
+ //RT_TRACE(COMP_LPS,"====>no link LPS leave\n");
+ LeisurePSLeave(dev);
+#endif
}
+
ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
ieee->LinkDetectInfo.NumTxOkInPeriod = 0;
+ ieee->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
ieee->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
}
@@ -4288,14 +4764,14 @@ void rtl819x_watchdog_wqcallback(struct work_struct *work)
if( ieee->eRFPowerState == eRfOff)
RT_TRACE(COMP_ERR,"========>%s()\n",__FUNCTION__);
printk("===>%s(): AP is power off,connect another one\n",__FUNCTION__);
- // Dot11d_Reset(dev);
+ // Dot11d_Reset(dev);
ieee->state = IEEE80211_ASSOCIATING;
notify_wx_assoc_event(priv->ieee80211);
- RemovePeerTS(priv->ieee80211,priv->ieee80211->current_network.bssid);
+ RemovePeerTS(priv->ieee80211,priv->ieee80211->current_network.bssid);
ieee->is_roaming = true;
ieee->is_set_key = false;
- ieee->link_change(dev);
- queue_work(ieee->wq, &ieee->associate_procedure_wq);
+ ieee->link_change(dev);
+ queue_work(ieee->wq, &ieee->associate_procedure_wq);
}
}
ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
@@ -4348,6 +4824,7 @@ int _rtl8192_up(struct net_device *dev)
RT_STATUS init_status = RT_STATUS_SUCCESS;
priv->up=1;
priv->ieee80211->ieee_up=1;
+ priv->bdisable_nic = false; //YJ,add,091111
RT_TRACE(COMP_INIT, "Bringing up iface");
init_status = rtl8192_adapter_start(dev);
@@ -4422,6 +4899,12 @@ int rtl8192_down(struct net_device *dev)
#endif
if (priv->up == 0) return -1;
+#ifdef ENABLE_LPS
+ //LZM for PS-Poll AID issue. 090429
+ if(priv->ieee80211->state == IEEE80211_LINKED)
+ LeisurePSLeave(dev);
+#endif
+
priv->up=0;
priv->ieee80211->ieee_up = 0;
RT_TRACE(COMP_DOWN, "==========>%s()\n", __FUNCTION__);
@@ -4459,11 +4942,9 @@ int rtl8192_down(struct net_device *dev)
deinit_hal_dm(dev);
del_timer_sync(&priv->watch_dog_timer);
- ieee80211_softmac_stop_protocol(priv->ieee80211);
-#ifdef ENABLE_IPS
- MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_INIT);
-#endif
- rtl8192_rtx_disable(dev);
+ ieee80211_softmac_stop_protocol(priv->ieee80211,true);
+
+ rtl8192_halt_adapter(dev,false);
memset(&priv->ieee80211->current_network, 0 , offsetof(struct ieee80211_network, list));
RT_TRACE(COMP_DOWN, "<==========%s()\n", __FUNCTION__);
@@ -4479,10 +4960,10 @@ void rtl8192_commit(struct net_device *dev)
if (priv->up == 0) return ;
- ieee80211_softmac_stop_protocol(priv->ieee80211);
+ ieee80211_softmac_stop_protocol(priv->ieee80211,true);
rtl8192_irq_disable(dev);
- rtl8192_rtx_disable(dev);
+ rtl8192_halt_adapter(dev,true);
_rtl8192_up(dev);
}
@@ -5806,8 +6287,7 @@ static void rtl8192_rx(struct net_device *dev)
skb = new_skb;
priv->rx_buf[priv->rx_idx] = skb;
- *((dma_addr_t *) skb->cb) = pci_map_single(priv->pdev, skb->tail, priv->rxbuffersize, PCI_DMA_FROMDEVICE);
-// *((dma_addr_t *) skb->cb) = pci_map_single(priv->pdev, skb_tail_pointer(skb), priv->rxbuffersize, PCI_DMA_FROMDEVICE);
+ *((dma_addr_t *) skb->cb) = pci_map_single(priv->pdev, skb_tail_pointer(skb), priv->rxbuffersize, PCI_DMA_FROMDEVICE);
}
}
@@ -6036,7 +6516,7 @@ void rtl8192_cancel_deferred_work(struct r8192_priv* priv)
/* call cancel_work_sync instead of cancel_delayed_work if and only if Linux_version_code
* is or is newer than 2.6.20 and work structure is defined to be struct work_struct.
* Otherwise call cancel_delayed_work is enough.
- * FIXME (2.6.20 shoud 2.6.22, work_struct shoud not cancel)
+ * FIXME (2.6.20 should 2.6.22, work_struct should not cancel)
* */
cancel_delayed_work(&priv->watch_dog_wq);
cancel_delayed_work(&priv->update_beacon_wq);
@@ -6381,11 +6861,13 @@ void setKey( struct net_device *dev,
if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
{
RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
- up(&priv->wx_sem);
+ //up(&priv->wx_sem);
return ;
}
else{
+ down(&priv->ieee80211->ips_sem);
IPSLeave(dev);
+ up(&priv->ieee80211->ips_sem);
}
}
}
@@ -6394,7 +6876,7 @@ void setKey( struct net_device *dev,
if (EntryNo >= TOTAL_CAM_ENTRY)
RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
- RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr"MAC_FMT"\n", dev,EntryNo, KeyIndex, KeyType, MAC_ARG(MacAddr));
+ RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr%pM\n", dev,EntryNo, KeyIndex, KeyType, MacAddr);
if (DefaultKey)
usConfig |= BIT15 | (KeyType<<2);
@@ -6455,6 +6937,65 @@ void CamPrintDbgReg(struct net_device* dev)
RT_TRACE(COMP_SEC, "WPA_Config=%x \n",ucValue);
}
+bool NicIFEnableNIC(struct net_device* dev)
+{
+ RT_STATUS init_status = RT_STATUS_SUCCESS;
+ struct r8192_priv* priv = ieee80211_priv(dev);
+ PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+
+ //YJ,add,091109
+ if (priv->up == 0){
+ RT_TRACE(COMP_ERR, "ERR!!! %s(): Driver is already down!\n",__FUNCTION__);
+ priv->bdisable_nic = false; //YJ,add,091111
+ return false;
+ }
+ // <1> Reset memory: descriptor, buffer,..
+ //NicIFResetMemory(Adapter);
+
+ // <2> Enable Adapter
+ //printk("===========>%s()\n",__FUNCTION__);
+ //priv->bfirst_init = true;
+ init_status = rtl8192_adapter_start(dev);
+ if (init_status != RT_STATUS_SUCCESS) {
+ RT_TRACE(COMP_ERR,"ERR!!! %s(): initialization is failed!\n",__FUNCTION__);
+ priv->bdisable_nic = false; //YJ,add,091111
+ return -1;
+ }
+ //printk("start adapter finished\n");
+ RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
+ //priv->bfirst_init = false;
+
+ // <3> Enable Interrupt
+ rtl8192_irq_enable(dev);
+ priv->bdisable_nic = false;
+ //RT_TRACE(COMP_PS,"<===========%s()\n",__FUNCTION__);
+ return (init_status == RT_STATUS_SUCCESS) ? true:false;
+}
+bool NicIFDisableNIC(struct net_device* dev)
+{
+ bool status = true;
+ struct r8192_priv* priv = ieee80211_priv(dev);
+ u8 tmp_state = 0;
+ // <1> Disable Interrupt
+ //RT_TRACE(COMP_PS, "=========>%s()\n",__FUNCTION__);
+ priv->bdisable_nic = true; //YJ,move,091109
+ tmp_state = priv->ieee80211->state;
+
+ ieee80211_softmac_stop_protocol(priv->ieee80211, false);
+
+ priv->ieee80211->state = tmp_state;
+ rtl8192_cancel_deferred_work(priv);
+ rtl8192_irq_disable(dev);
+ // <2> Stop all timer
+
+ // <3> Disable Adapter
+ rtl8192_halt_adapter(dev, false);
+// priv->bdisable_nic = true;
+ //RT_TRACE(COMP_PS, "<=========%s()\n",__FUNCTION__);
+
+ return status;
+}
+
/***************************************************************************
------------------- module init / exit stubs ----------------
diff --git a/drivers/staging/rtl8192e/r8192E_dm.c b/drivers/staging/rtl8192e/r8192E_dm.c
index 5ffb4f74055..a249f00da60 100644
--- a/drivers/staging/rtl8192e/r8192E_dm.c
+++ b/drivers/staging/rtl8192e/r8192E_dm.c
@@ -19,26 +19,28 @@ Major Change History:
#include "r819xE_phy.h"
#include "r819xE_phyreg.h"
#include "r8190_rtl8256.h"
+
+#define DRV_NAME "rtl819xE"
/*---------------------------Define Local Constant---------------------------*/
//
// Indicate different AP vendor for IOT issue.
//
#ifdef RTL8190P
static u32 edca_setting_DL[HT_IOT_PEER_MAX] =
-{ 0x5e4322, 0x5e4322, 0x5e4322, 0x604322, 0xa44f, 0x5e4322};
+{ 0x5e4322, 0x5e4322, 0x5e4322, 0x604322, 0xa44f, 0x5e4322, 0x5e4322};
static u32 edca_setting_UL[HT_IOT_PEER_MAX] =
-{ 0x5e4322, 0xa44f, 0x5e4322, 0x604322, 0x5e4322, 0x5e4322};
+{ 0x5e4322, 0xa44f, 0x5e4322, 0x604322, 0x5e4322, 0x5e4322, 0x5e4322};
#else
#ifdef RTL8192E
static u32 edca_setting_DL[HT_IOT_PEER_MAX] =
-{ 0x5e4322, 0x5e4322, 0x5e4322, 0x604322, 0xa44f, 0x5e4322};
+{ 0x5e4322, 0x5e4322, 0x5e4322, 0x604322, 0xa44f, 0x5e4322, 0x5e4322};
static u32 edca_setting_UL[HT_IOT_PEER_MAX] =
-{ 0x5e4322, 0xa44f, 0x5e4322, 0x604322, 0x5e4322, 0x5e4322};
+{ 0x5e4322, 0xa44f, 0x5e4322, 0x604322, 0x5e4322, 0x5e4322, 0x5e4322};
#else
static u32 edca_setting_DL[HT_IOT_PEER_MAX] =
-{ 0x5e4322, 0x5e4322, 0x5e4322, 0x604322, 0xa44f, 0x5ea44f};
+{ 0x5e4322, 0x5e4322, 0x5e4322, 0x604322, 0xa44f, 0x5ea44f, 0x5e4322};
static u32 edca_setting_UL[HT_IOT_PEER_MAX] =
-{ 0x5e4322, 0xa44f, 0x5e4322, 0x604322, 0x5ea44f, 0x5ea44f};
+{ 0x5e4322, 0xa44f, 0x5e4322, 0x604322, 0x5ea44f, 0x5ea44f, 0x5e4322};
#endif
#endif
@@ -275,6 +277,30 @@ void dm_CheckRxAggregation(struct net_device *dev) {
#endif
+// call the script file to enable
+void dm_check_ac_dc_power(struct net_device *dev)
+{
+ struct r8192_priv *priv = ieee80211_priv(dev);
+ static char *ac_dc_check_script_path = "/etc/acpi/wireless-rtl-ac-dc-power.sh";
+ char *argv[] = {ac_dc_check_script_path,DRV_NAME,NULL};
+ static char *envp[] = {"HOME=/",
+ "TERM=linux",
+ "PATH=/usr/bin:/bin",
+ NULL};
+
+ if(priv->ResetProgress == RESET_TYPE_SILENT)
+ {
+ RT_TRACE((COMP_INIT | COMP_POWER | COMP_RF), "GPIOChangeRFWorkItemCallBack(): Silent Reseting!!!!!!!\n");
+ return;
+ }
+
+ if(priv->ieee80211->state != IEEE80211_LINKED) {
+ return;
+ }
+ call_usermodehelper(ac_dc_check_script_path,argv,envp,1);
+
+ return;
+};
void hal_dm_watchdog(struct net_device *dev)
{
@@ -282,6 +308,8 @@ void hal_dm_watchdog(struct net_device *dev)
//static u8 previous_bssid[6] ={0};
+ dm_check_ac_dc_power(dev);
+
/*Add by amy 2008/05/15 ,porting from windows code.*/
dm_check_rate_adaptive(dev);
dm_dynamic_txpower(dev);
diff --git a/drivers/staging/rtl8192e/r8192E_hw.h b/drivers/staging/rtl8192e/r8192E_hw.h
index 388908fc8d2..346bfb18e2b 100644
--- a/drivers/staging/rtl8192e/r8192E_hw.h
+++ b/drivers/staging/rtl8192e/r8192E_hw.h
@@ -808,4 +808,12 @@ enum _RTL8192Pci_HW {
#define GPI 0x108
#define GPO 0x109
#define GPE 0x10a
+
+#define ANAPAR_FOR_8192PciE 0x17 // Analog parameter register
+
+#define MSR_NOLINK 0x00
+#define MSR_ADHOC 0x01
+#define MSR_INFRA 0x02
+#define MSR_AP 0x03
+
#endif
diff --git a/drivers/staging/rtl8192e/r8192E_wx.c b/drivers/staging/rtl8192e/r8192E_wx.c
index d1eb89229cd..0b0f39ce3ce 100644
--- a/drivers/staging/rtl8192e/r8192E_wx.c
+++ b/drivers/staging/rtl8192e/r8192E_wx.c
@@ -22,7 +22,7 @@
#include "r8192E_hw.h"
#include "r8192E_wx.h"
#ifdef ENABLE_DOT11D
-#include "dot11d.h"
+#include "ieee80211/dot11d.h"
#endif
#define RATE_COUNT 12
@@ -70,6 +70,9 @@ static int r8192_wx_set_rate(struct net_device *dev,
int ret;
struct r8192_priv *priv = ieee80211_priv(dev);
+ if(priv->bHwRadioOff == true)
+ return 0;
+
down(&priv->wx_sem);
ret = ieee80211_wx_set_rate(priv->ieee80211,info,wrqu,extra);
@@ -87,6 +90,9 @@ static int r8192_wx_set_rts(struct net_device *dev,
int ret;
struct r8192_priv *priv = ieee80211_priv(dev);
+ if(priv->bHwRadioOff == true)
+ return 0;
+
down(&priv->wx_sem);
ret = ieee80211_wx_set_rts(priv->ieee80211,info,wrqu,extra);
@@ -111,6 +117,9 @@ static int r8192_wx_set_power(struct net_device *dev,
int ret;
struct r8192_priv *priv = ieee80211_priv(dev);
+ if(priv->bHwRadioOff == true)
+ return 0;
+
down(&priv->wx_sem);
ret = ieee80211_wx_set_power(priv->ieee80211,info,wrqu,extra);
@@ -290,6 +299,9 @@ static int r8192_wx_set_rawtx(struct net_device *dev,
struct r8192_priv *priv = ieee80211_priv(dev);
int ret;
+ if(priv->bHwRadioOff == true)
+ return 0;
+
down(&priv->wx_sem);
ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
@@ -325,6 +337,9 @@ static int r8192_wx_set_crcmon(struct net_device *dev,
int enable = (parms[0] > 0);
short prev = priv->crcmon;
+ if(priv->bHwRadioOff == true)
+ return 0;
+
down(&priv->wx_sem);
if(enable)
@@ -352,6 +367,9 @@ static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
RT_RF_POWER_STATE rtState;
int ret;
+ if(priv->bHwRadioOff == true)
+ return 0;
+
rtState = priv->ieee80211->eRFPowerState;
down(&priv->wx_sem);
#ifdef ENABLE_IPS
@@ -366,8 +384,10 @@ static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
return -1;
}
else{
- printk("=========>%s(): IPSLeave\n",__FUNCTION__);
+ RT_TRACE(COMP_ERR, "%s(): IPSLeave\n",__FUNCTION__);
+ down(&priv->ieee80211->ips_sem);
IPSLeave(dev);
+ up(&priv->ieee80211->ips_sem);
}
}
}
@@ -425,7 +445,7 @@ static int rtl8180_wx_get_range(struct net_device *dev,
*/
/* ~5 Mb/s real (802.11b) */
- range->throughput = 5 * 1000 * 1000;
+ range->throughput = 130 * 1000 * 1000;
// TODO: Not used in 802.11b?
// range->min_nwid; /* Minimal NWID we are able to set */
@@ -468,7 +488,7 @@ static int rtl8180_wx_get_range(struct net_device *dev,
range->pmt_flags = IW_POWER_TIMEOUT;
range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
range->we_version_compiled = WIRELESS_EXT;
- range->we_version_source = 16;
+ range->we_version_source = 18;
// range->retry_capa; /* What retry options are supported */
// range->retry_flags; /* How to decode max/min retry limit */
@@ -517,7 +537,12 @@ static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
struct ieee80211_device* ieee = priv->ieee80211;
RT_RF_POWER_STATE rtState;
int ret;
+
+ if(priv->bHwRadioOff == true)
+ return 0;
+
rtState = priv->ieee80211->eRFPowerState;
+
if(!priv->up) return -ENETDOWN;
if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true)
return -EAGAIN;
@@ -547,8 +572,10 @@ static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
return -1;
}
else{
- printk("=========>%s(): IPSLeave\n",__FUNCTION__);
+ //RT_TRACE(COMP_PS, "%s(): IPSLeave\n",__FUNCTION__);
+ down(&priv->ieee80211->ips_sem);
IPSLeave(dev);
+ up(&priv->ieee80211->ips_sem);
}
}
}
@@ -580,6 +607,9 @@ static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
int ret;
struct r8192_priv *priv = ieee80211_priv(dev);
+ if(priv->bHwRadioOff == true)
+ return 0;
+
if(!priv->up) return -ENETDOWN;
down(&priv->wx_sem);
@@ -599,23 +629,16 @@ static int r8192_wx_set_essid(struct net_device *dev,
RT_RF_POWER_STATE rtState;
int ret;
+ if(priv->bHwRadioOff == true)
+ return 0;
+
rtState = priv->ieee80211->eRFPowerState;
down(&priv->wx_sem);
+
#ifdef ENABLE_IPS
- if(priv->ieee80211->PowerSaveControl.bInactivePs){
- if(rtState == eRfOff){
- if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
- {
- RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
- up(&priv->wx_sem);
- return -1;
- }
- else{
- printk("=========>%s(): IPSLeave\n",__FUNCTION__);
- IPSLeave(dev);
- }
- }
- }
+ down(&priv->ieee80211->ips_sem);
+ IPSLeave(dev);
+ up(&priv->ieee80211->ips_sem);
#endif
ret = ieee80211_wx_set_essid(priv->ieee80211,a,wrqu,b);
@@ -650,6 +673,9 @@ static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
int ret;
struct r8192_priv *priv = ieee80211_priv(dev);
+ if(priv->bHwRadioOff == true)
+ return 0;
+
down(&priv->wx_sem);
ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
@@ -673,6 +699,9 @@ static int r8192_wx_set_frag(struct net_device *dev,
{
struct r8192_priv *priv = ieee80211_priv(dev);
+ if(priv->bHwRadioOff == true)
+ return 0;
+
if (wrqu->frag.disabled)
priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
else {
@@ -711,8 +740,16 @@ static int r8192_wx_set_wap(struct net_device *dev,
struct r8192_priv *priv = ieee80211_priv(dev);
// struct sockaddr *temp = (struct sockaddr *)awrq;
+ if(priv->bHwRadioOff == true)
+ return 0;
+
down(&priv->wx_sem);
+#ifdef ENABLE_IPS
+ down(&priv->ieee80211->ips_sem);
+ IPSLeave(dev);
+ up(&priv->ieee80211->ips_sem);
+#endif
ret = ieee80211_wx_set_wap(priv->ieee80211,info,awrq,extra);
up(&priv->wx_sem);
@@ -753,14 +790,24 @@ static int r8192_wx_set_enc(struct net_device *dev,
u32 hwkey[4]={0,0,0,0};
u8 mask=0xff;
u32 key_idx=0;
- u8 zero_addr[4][6] ={ {0x00,0x00,0x00,0x00,0x00,0x00},
+ u8 zero_addr[4][6] ={{0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x01},
{0x00,0x00,0x00,0x00,0x00,0x02},
{0x00,0x00,0x00,0x00,0x00,0x03} };
int i;
+ if(priv->bHwRadioOff == true)
+ return 0;
+
if(!priv->up) return -ENETDOWN;
+ priv->ieee80211->wx_set_enc = 1;
+#ifdef ENABLE_IPS
+ down(&priv->ieee80211->ips_sem);
+ IPSLeave(dev);
+ up(&priv->ieee80211->ips_sem);
+#endif
+
down(&priv->wx_sem);
RT_TRACE(COMP_SEC, "Setting SW wep key");
@@ -768,7 +815,6 @@ static int r8192_wx_set_enc(struct net_device *dev,
up(&priv->wx_sem);
-
//sometimes, the length is zero while we do not type key value
if(wrqu->encoding.length!=0){
@@ -868,6 +914,8 @@ static int r8192_wx_set_enc(struct net_device *dev,
}
#endif
+ priv->ieee80211->wx_set_enc = 0;
+
return ret;
}
@@ -893,6 +941,9 @@ static int r8192_wx_set_retry(struct net_device *dev,
struct r8192_priv *priv = ieee80211_priv(dev);
int err = 0;
+ if(priv->bHwRadioOff == true)
+ return 0;
+
down(&priv->wx_sem);
if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
@@ -985,6 +1036,10 @@ static int r8192_wx_set_sens(struct net_device *dev,
struct r8192_priv *priv = ieee80211_priv(dev);
short err = 0;
+
+ if(priv->bHwRadioOff == true)
+ return 0;
+
down(&priv->wx_sem);
//DMESG("attempt to set sensivity to %ddb",wrqu->sens.value);
if(priv->rf_set_sens == NULL) {
@@ -1011,7 +1066,19 @@ static int r8192_wx_set_enc_ext(struct net_device *dev,
struct r8192_priv *priv = ieee80211_priv(dev);
struct ieee80211_device* ieee = priv->ieee80211;
+ if(priv->bHwRadioOff == true)
+ return 0;
+
down(&priv->wx_sem);
+
+ priv->ieee80211->wx_set_enc = 1;
+
+#ifdef ENABLE_IPS
+ down(&priv->ieee80211->ips_sem);
+ IPSLeave(dev);
+ up(&priv->ieee80211->ips_sem);
+#endif
+
ret = ieee80211_wx_set_encode_ext(ieee, info, wrqu, extra);
{
@@ -1091,6 +1158,7 @@ static int r8192_wx_set_enc_ext(struct net_device *dev,
}
end_hw_sec:
+ priv->ieee80211->wx_set_enc = 0;
up(&priv->wx_sem);
return ret;
@@ -1102,6 +1170,10 @@ static int r8192_wx_set_auth(struct net_device *dev,
int ret=0;
//printk("====>%s()\n", __FUNCTION__);
struct r8192_priv *priv = ieee80211_priv(dev);
+
+ if(priv->bHwRadioOff == true)
+ return 0;
+
down(&priv->wx_sem);
ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
up(&priv->wx_sem);
@@ -1116,6 +1188,10 @@ static int r8192_wx_set_mlme(struct net_device *dev,
int ret=0;
struct r8192_priv *priv = ieee80211_priv(dev);
+
+ if(priv->bHwRadioOff == true)
+ return 0;
+
down(&priv->wx_sem);
ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
up(&priv->wx_sem);
@@ -1129,6 +1205,10 @@ static int r8192_wx_set_gen_ie(struct net_device *dev,
//printk("====>%s(), len:%d\n", __FUNCTION__, data->length);
int ret=0;
struct r8192_priv *priv = ieee80211_priv(dev);
+
+ if(priv->bHwRadioOff == true)
+ return 0;
+
down(&priv->wx_sem);
ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
up(&priv->wx_sem);
@@ -1142,6 +1222,42 @@ static int dummy(struct net_device *dev, struct iw_request_info *a,
return -1;
}
+// check ac/dc status with the help of user space application */
+static int r8192_wx_adapter_power_status(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct r8192_priv *priv = ieee80211_priv(dev);
+#ifdef ENABLE_LPS
+ PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
+ struct ieee80211_device* ieee = priv->ieee80211;
+#endif
+ down(&priv->wx_sem);
+
+#ifdef ENABLE_LPS
+ RT_TRACE(COMP_POWER, "%s(): %s\n",__FUNCTION__, (*extra == 6)?"DC power":"AC power");
+ // ieee->ps shall not be set under DC mode, otherwise it conflict
+ // with Leisure power save mode setting.
+ //
+ if(*extra || priv->force_lps) {
+ priv->ps_force = false;
+ pPSC->bLeisurePs = true;
+ } else {
+ //LZM for PS-Poll AID issue. 090429
+ if(priv->ieee80211->state == IEEE80211_LINKED)
+ LeisurePSLeave(dev);
+
+ priv->ps_force = true;
+ pPSC->bLeisurePs = false;
+ ieee->ps = *extra;
+ }
+
+#endif
+ up(&priv->wx_sem);
+ return 0;
+
+}
+
static iw_handler r8192_wx_handlers[] =
{
@@ -1231,72 +1347,28 @@ static const struct iw_priv_args r8192_private_args[] = {
SIOCIWFIRSTPRIV + 0x2,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
}
-#ifdef JOHN_IOCTL
,
{
SIOCIWFIRSTPRIV + 0x3,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readRF"
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
+
}
,
{
SIOCIWFIRSTPRIV + 0x4,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writeRF"
- }
- ,
- {
- SIOCIWFIRSTPRIV + 0x5,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readBB"
- }
- ,
- {
- SIOCIWFIRSTPRIV + 0x6,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writeBB"
- }
- ,
- {
- SIOCIWFIRSTPRIV + 0x7,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readnicb"
- }
- ,
- {
- SIOCIWFIRSTPRIV + 0x8,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writenicb"
- }
- ,
- {
- SIOCIWFIRSTPRIV + 0x9,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
- }
-
-#endif
- ,
- {
- SIOCIWFIRSTPRIV + 0x3,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
-
+ IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE,
+ "set_power"
}
};
static iw_handler r8192_private_handler[] = {
-// r8192_wx_set_monitor, /* SIOCIWFIRSTPRIV */
r8192_wx_set_crcmon, /*SIOCIWSECONDPRIV*/
-// r8192_wx_set_forceassociate,
-// r8192_wx_set_beaconinterval,
-// r8192_wx_set_monitor_type,
r8192_wx_set_scan_type,
r8192_wx_set_rawtx,
-#ifdef JOHN_IOCTL
- r8192_wx_read_regs,
- r8192_wx_write_regs,
- r8192_wx_read_bb,
- r8192_wx_write_bb,
- r8192_wx_read_nicb,
- r8192_wx_write_nicb,
- r8192_wx_get_ap_status
-#endif
r8192_wx_force_reset,
+ r8192_wx_adapter_power_status,
};
//#if WIRELESS_EXT >= 17
diff --git a/drivers/staging/rtl8192e/r8192E_wx.h b/drivers/staging/rtl8192e/r8192E_wx.h
index 79ebdb698a4..047030bc051 100644
--- a/drivers/staging/rtl8192e/r8192E_wx.h
+++ b/drivers/staging/rtl8192e/r8192E_wx.h
@@ -15,7 +15,6 @@
#ifndef R8180_WX_H
#define R8180_WX_H
//#include <linux/wireless.h>
-//#include "ieee80211.h"
extern struct iw_handler_def r8192_wx_handlers_def;
/* Enable the rtl819x_core.c to share this function, david 2008.9.22 */
extern struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev);
diff --git a/drivers/staging/rtl8192e/r819xE_cmdpkt.c b/drivers/staging/rtl8192e/r819xE_cmdpkt.c
index 2aaa4e1bb37..87c334fb733 100644
--- a/drivers/staging/rtl8192e/r819xE_cmdpkt.c
+++ b/drivers/staging/rtl8192e/r819xE_cmdpkt.c
@@ -135,7 +135,7 @@ RT_STATUS cmpk_message_handle_tx(
* Transform from little endian to big endian
* and pending zero
*/
- seg_ptr = skb->tail;
+ seg_ptr = skb_tail_pointer(skb);
for(i=0 ; i < frag_length; i+=4) {
*seg_ptr++ = ((i+0)<frag_length)?code_virtual_address[i+3]:0;
*seg_ptr++ = ((i+1)<frag_length)?code_virtual_address[i+2]:0;
diff --git a/drivers/staging/rtl8192e/r819xE_firmware.c b/drivers/staging/rtl8192e/r819xE_firmware.c
index 1f9e413bcd4..793a1754555 100644
--- a/drivers/staging/rtl8192e/r819xE_firmware.c
+++ b/drivers/staging/rtl8192e/r819xE_firmware.c
@@ -1,5 +1,5 @@
/*
- * Procedure: Init boot code/firmware code/data session
+ * Procedure: Init boot code/firmware code/data session
*
* Description: This routine will intialize firmware. If any error occurs
* during the initialization process, the routine shall terminate
@@ -7,19 +7,21 @@
* NdisOpenFile only from MiniportInitialize.
*
* Arguments: The pointer of the adapter
-
+ *
* Returns:
* NDIS_STATUS_FAILURE - the following initialization process
* should be terminated
* NDIS_STATUS_SUCCESS - if firmware initialization process
* success
*/
+
#include "r8192E.h"
#include "r8192E_hw.h"
+
#include <linux/firmware.h>
/* It should be double word alignment */
-#define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) (4 * (v / 4) - 8)
+#define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) (4 * (v / 4) - 8)
enum firmware_init_step {
FW_INIT_STEP0_BOOT = 0,
@@ -47,17 +49,17 @@ void firmware_init_param(struct net_device *dev)
static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
u32 buffer_len)
{
- struct r8192_priv *priv = ieee80211_priv(dev);
- bool rt_status = true;
- u16 frag_threshold;
- u16 frag_length, frag_offset = 0;
- int i;
-
- rt_firmware *pfirmware = priv->pFirmware;
- struct sk_buff *skb;
- unsigned char *seg_ptr;
- cb_desc *tcb_desc;
- u8 bLastIniPkt;
+ struct r8192_priv *priv = ieee80211_priv(dev);
+ bool rt_status = true;
+ u16 frag_threshold;
+ u16 frag_length, frag_offset = 0;
+ int i;
+
+ rt_firmware *pfirmware = priv->pFirmware;
+ struct sk_buff *skb;
+ unsigned char *seg_ptr;
+ cb_desc *tcb_desc;
+ u8 bLastIniPkt;
firmware_init_param(dev);
@@ -89,10 +91,17 @@ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
* Transform from little endian to big endian and pending zero
*/
for (i = 0; i < frag_length; i += 4) {
- *seg_ptr++ = ((i+0) < frag_length) ? code_virtual_address[i+3] : 0;
- *seg_ptr++ = ((i+1) < frag_length) ? code_virtual_address[i+2] : 0;
- *seg_ptr++ = ((i+2) < frag_length) ? code_virtual_address[i+1] : 0;
- *seg_ptr++ = ((i+3) < frag_length) ? code_virtual_address[i+0] : 0;
+ *seg_ptr++ = ((i+0) < frag_length) ? \
+ code_virtual_address[i+3] : 0;
+
+ *seg_ptr++ = ((i+1) < frag_length) ? \
+ code_virtual_address[i+2] : 0;
+
+ *seg_ptr++ = ((i+2) < frag_length) ? \
+ code_virtual_address[i+1] : 0;
+
+ *seg_ptr++ = ((i+3) < frag_length) ? \
+ code_virtual_address[i+0] : 0;
}
tcb_desc->txbuf_size = (u16)i;
skb_put(skb, i);
@@ -204,16 +213,16 @@ CPUCheckFirmwareReady_Fail:
bool init_firmware(struct net_device *dev)
{
- struct r8192_priv *priv = ieee80211_priv(dev);
- bool rt_status = TRUE;
- u32 file_length = 0;
- u8 *mapped_file = NULL;
- u32 init_step = 0;
- enum opt_rst_type rst_opt = OPT_SYSTEM_RESET;
+ struct r8192_priv *priv = ieee80211_priv(dev);
+ bool rt_status = true;
+ u32 file_length = 0;
+ u8 *mapped_file = NULL;
+ u32 init_step = 0;
+ enum opt_rst_type rst_opt = OPT_SYSTEM_RESET;
enum firmware_init_step starting_state = FW_INIT_STEP0_BOOT;
- rt_firmware *pfirmware = priv->pFirmware;
- const struct firmware *fw_entry;
+ rt_firmware *pfirmware = priv->pFirmware;
+ const struct firmware *fw_entry;
const char *fw_name[3] = { "RTL8192E/boot.img",
"RTL8192E/main.img",
"RTL8192E/data.img"};
@@ -240,31 +249,37 @@ bool init_firmware(struct net_device *dev)
* Download boot, main, and data image for System reset.
* Download data image for firmware reseta
*/
- for (init_step = starting_state; init_step <= FW_INIT_STEP2_DATA; init_step++) {
+ for (init_step = starting_state; init_step <= FW_INIT_STEP2_DATA; \
+ init_step++) {
/*
* Open Image file, and map file to contineous memory if open file success.
* or read image file from array. Default load from IMG file
*/
if (rst_opt == OPT_SYSTEM_RESET) {
if (pfirmware->firmware_buf_size[init_step] == 0) {
- rc = request_firmware(&fw_entry, fw_name[init_step], &priv->pdev->dev);
+ rc = request_firmware(&fw_entry,
+ fw_name[init_step], &priv->pdev->dev);
+
if (rc < 0) {
RT_TRACE(COMP_FIRMWARE, "request firmware fail!\n");
goto download_firmware_fail;
}
if (fw_entry->size > sizeof(pfirmware->firmware_buf[init_step])) {
- RT_TRACE(COMP_FIRMWARE, "img file size exceed the container buffer fail!\n");
+ RT_TRACE(COMP_FIRMWARE, \
+ "img file size exceed the container buffer fail!\n");
goto download_firmware_fail;
}
if (init_step != FW_INIT_STEP1_MAIN) {
- memcpy(pfirmware->firmware_buf[init_step], fw_entry->data, fw_entry->size);
+ memcpy(pfirmware->firmware_buf[init_step],
+ fw_entry->data, fw_entry->size);
pfirmware->firmware_buf_size[init_step] = fw_entry->size;
} else {
memset(pfirmware->firmware_buf[init_step], 0, 128);
- memcpy(&pfirmware->firmware_buf[init_step][128], fw_entry->data, fw_entry->size);
+ memcpy(&pfirmware->firmware_buf[init_step][128], fw_entry->data,
+ fw_entry->size);
pfirmware->firmware_buf_size[init_step] = fw_entry->size+128;
}
@@ -273,6 +288,7 @@ bool init_firmware(struct net_device *dev)
}
mapped_file = pfirmware->firmware_buf[init_step];
file_length = pfirmware->firmware_buf_size[init_step];
+
} else if (rst_opt == OPT_FIRMWARE_RESET) {
/* we only need to download data.img here */
mapped_file = pfirmware->firmware_buf[init_step];
@@ -346,7 +362,10 @@ bool init_firmware(struct net_device *dev)
download_firmware_fail:
RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
- rt_status = FALSE;
+ rt_status = false;
return rt_status;
-
}
+
+MODULE_FIRMWARE("RTL8192E/boot.img");
+MODULE_FIRMWARE("RTL8192E/main.img");
+MODULE_FIRMWARE("RTL8192E/data.img");
diff --git a/drivers/staging/rtl8192e/r819xE_phy.c b/drivers/staging/rtl8192e/r819xE_phy.c
index c44059aeacb..7bd4fae0667 100644
--- a/drivers/staging/rtl8192e/r819xE_phy.c
+++ b/drivers/staging/rtl8192e/r819xE_phy.c
@@ -5,7 +5,7 @@
#include "r819xE_phy.h"
#include "r8192E_dm.h"
#ifdef ENABLE_DOT11D
-#include "dot11d.h"
+#include "ieee80211/dot11d.h"
#endif
static u32 RF_CHANNEL_TABLE_ZEBRA[] = {
0,
diff --git a/drivers/staging/rtl8192e/r819xE_phy.h b/drivers/staging/rtl8192e/r819xE_phy.h
index fa77abe8882..41e0d777eab 100644
--- a/drivers/staging/rtl8192e/r819xE_phy.h
+++ b/drivers/staging/rtl8192e/r819xE_phy.h
@@ -1,43 +1,46 @@
#ifndef _R819XU_PHY_H
#define _R819XU_PHY_H
-/* Channel switch:The size of command tables for switch channel*/
+
+/* Channel switch: the size of command tables for switch channel */
#define MAX_PRECMD_CNT 16
#define MAX_RFDEPENDCMD_CNT 16
#define MAX_POSTCMD_CNT 16
#ifdef RTL8190P
#define MACPHY_Array_PGLength 21
-#define Rtl819XMACPHY_Array_PG Rtl8190PciMACPHY_Array_PG
-#define Rtl819XMACPHY_Array Rtl8190PciMACPHY_Array
+#define Rtl819XMACPHY_Array_PG Rtl8190PciMACPHY_Array_PG
+#define Rtl819XMACPHY_Array Rtl8190PciMACPHY_Array
#define RadioC_ArrayLength 246
#define RadioD_ArrayLength 78
-#define Rtl819XRadioA_Array Rtl8190PciRadioA_Array
-#define Rtl819XRadioB_Array Rtl8190PciRadioB_Array
-#define Rtl819XRadioC_Array Rtl8190PciRadioC_Array
-#define Rtl819XRadioD_Array Rtl8190PciRadioD_Array
-#define Rtl819XAGCTAB_Array Rtl8190PciAGCTAB_Array
-#define PHY_REGArrayLength 280
-#define Rtl819XPHY_REGArray Rtl8190PciPHY_REGArray
-#define PHY_REG_1T2RArrayLength 280
-#define Rtl819XPHY_REG_1T2RArray Rtl8190PciPHY_REG_1T2RArray
+#define Rtl819XRadioA_Array Rtl8190PciRadioA_Array
+#define Rtl819XRadioB_Array Rtl8190PciRadioB_Array
+#define Rtl819XRadioC_Array Rtl8190PciRadioC_Array
+#define Rtl819XRadioD_Array Rtl8190PciRadioD_Array
+#define Rtl819XAGCTAB_Array Rtl8190PciAGCTAB_Array
+#define PHY_REGArrayLength 280
+#define Rtl819XPHY_REGArray Rtl8190PciPHY_REGArray
+#define PHY_REG_1T2RArrayLength 280
+#define Rtl819XPHY_REG_1T2RArray Rtl8190PciPHY_REG_1T2RArray
+#endif
+
+
+#ifdef RTL8192E
+#define MACPHY_Array_PGLength 30
+#define Rtl819XMACPHY_Array_PG Rtl8192PciEMACPHY_Array_PG
+#define Rtl819XMACPHY_Array Rtl8192PciEMACPHY_Array
+#define RadioC_ArrayLength 1
+#define RadioD_ArrayLength 1
+#define Rtl819XRadioA_Array Rtl8192PciERadioA_Array
+#define Rtl819XRadioB_Array Rtl8192PciERadioB_Array
+#define Rtl819XRadioC_Array Rtl8192PciERadioC_Array
+#define Rtl819XRadioD_Array Rtl8192PciERadioD_Array
+#define Rtl819XAGCTAB_Array Rtl8192PciEAGCTAB_Array
+#define PHY_REGArrayLength 1
+#define Rtl819XPHY_REGArray Rtl8192PciEPHY_REGArray
+#define PHY_REG_1T2RArrayLength 296
+#define Rtl819XPHY_REG_1T2RArray Rtl8192PciEPHY_REG_1T2RArray
#endif
- #ifdef RTL8192E
- #define MACPHY_Array_PGLength 30
- #define Rtl819XMACPHY_Array_PG Rtl8192PciEMACPHY_Array_PG
- #define Rtl819XMACPHY_Array Rtl8192PciEMACPHY_Array
- #define RadioC_ArrayLength 1
- #define RadioD_ArrayLength 1
- #define Rtl819XRadioA_Array Rtl8192PciERadioA_Array
- #define Rtl819XRadioB_Array Rtl8192PciERadioB_Array
- #define Rtl819XRadioC_Array Rtl8192PciERadioC_Array
- #define Rtl819XRadioD_Array Rtl8192PciERadioD_Array
- #define Rtl819XAGCTAB_Array Rtl8192PciEAGCTAB_Array
- #define PHY_REGArrayLength 1
- #define Rtl819XPHY_REGArray Rtl8192PciEPHY_REGArray
- #define PHY_REG_1T2RArrayLength 296
- #define Rtl819XPHY_REG_1T2RArray Rtl8192PciEPHY_REG_1T2RArray
- #endif
#define AGCTAB_ArrayLength 384
#define MACPHY_ArrayLength 18
@@ -45,7 +48,7 @@
#define RadioB_ArrayLength 78
-typedef enum _SwChnlCmdID{
+typedef enum _SwChnlCmdID {
CmdID_End,
CmdID_SetTxPowerLevel,
CmdID_BBRegWrite10,
@@ -53,16 +56,15 @@ typedef enum _SwChnlCmdID{
CmdID_WritePortUshort,
CmdID_WritePortUchar,
CmdID_RF_WriteReg,
-}SwChnlCmdID;
+} SwChnlCmdID;
-/*--------------------------------Define structure--------------------------------*/
-/* 1. Switch channel related */
-typedef struct _SwChnlCmd{
- SwChnlCmdID CmdID;
- u32 Para1;
- u32 Para2;
- u32 msDelay;
-}__attribute__ ((packed)) SwChnlCmd;
+/* switch channel data structure */
+typedef struct _SwChnlCmd {
+ SwChnlCmdID CmdID;
+ u32 Para1;
+ u32 Para2;
+ u32 msDelay;
+} __attribute__ ((packed)) SwChnlCmd;
extern u32 rtl819XMACPHY_Array_PG[];
extern u32 rtl819XPHY_REG_1T2RArray[];
@@ -72,54 +74,90 @@ extern u32 rtl819XRadioB_Array[];
extern u32 rtl819XRadioC_Array[];
extern u32 rtl819XRadioD_Array[];
-typedef enum _HW90_BLOCK{
+typedef enum _HW90_BLOCK {
HW90_BLOCK_MAC = 0,
HW90_BLOCK_PHY0 = 1,
HW90_BLOCK_PHY1 = 2,
HW90_BLOCK_RF = 3,
- HW90_BLOCK_MAXIMUM = 4, // Never use this
-}HW90_BLOCK_E, *PHW90_BLOCK_E;
-
-typedef enum _RF90_RADIO_PATH{
- RF90_PATH_A = 0, //Radio Path A
- RF90_PATH_B = 1, //Radio Path B
- RF90_PATH_C = 2, //Radio Path C
- RF90_PATH_D = 3, //Radio Path D
- RF90_PATH_MAX //Max RF number 92 support
-}RF90_RADIO_PATH_E, *PRF90_RADIO_PATH_E;
-
-#define bMaskByte0 0xff
-#define bMaskByte1 0xff00
-#define bMaskByte2 0xff0000
-#define bMaskByte3 0xff000000
-#define bMaskHWord 0xffff0000
-#define bMaskLWord 0x0000ffff
-#define bMaskDWord 0xffffffff
-
-//extern u32 rtl8192_CalculateBitShift(u32 dwBitMask);
-extern u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device* dev, u32 eRFPath);
-extern void rtl8192_setBBreg(struct net_device* dev, u32 dwRegAddr, u32 dwBitMask, u32 dwData);
-extern u32 rtl8192_QueryBBReg(struct net_device* dev, u32 dwRegAddr, u32 dwBitMask);
-//extern u32 rtl8192_phy_RFSerialRead(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset);
-//extern void rtl8192_phy_RFSerialWrite(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 Offset, u32 Data);
-extern void rtl8192_phy_SetRFReg(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask, u32 Data);
-extern u32 rtl8192_phy_QueryRFReg(struct net_device* dev, RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask);
-extern void rtl8192_phy_configmac(struct net_device* dev);
-extern void rtl8192_phyConfigBB(struct net_device* dev, u8 ConfigType);
-//extern void rtl8192_InitBBRFRegDef(struct net_device* dev);
-extern RT_STATUS rtl8192_phy_checkBBAndRF(struct net_device* dev, HW90_BLOCK_E CheckBlock, RF90_RADIO_PATH_E eRFPath);
-//extern RT_STATUS rtl8192_BB_Config_ParaFile(struct net_device* dev);
-extern RT_STATUS rtl8192_BBConfig(struct net_device* dev);
-extern void rtl8192_phy_getTxPower(struct net_device* dev);
-extern void rtl8192_phy_setTxPower(struct net_device* dev, u8 channel);
+ /* Don't ever use this. */
+ HW90_BLOCK_MAXIMUM = 4,
+} HW90_BLOCK_E, *PHW90_BLOCK_E;
+
+typedef enum _RF90_RADIO_PATH {
+ /* Radio paths */
+ RF90_PATH_A = 0,
+ RF90_PATH_B = 1,
+ RF90_PATH_C = 2,
+ RF90_PATH_D = 3,
+
+ /* Max RF number 92 support */
+ RF90_PATH_MAX
+} RF90_RADIO_PATH_E, *PRF90_RADIO_PATH_E;
+
+#define bMaskByte0 0xff
+#define bMaskByte1 0xff00
+#define bMaskByte2 0xff0000
+#define bMaskByte3 0xff000000
+#define bMaskHWord 0xffff0000
+#define bMaskLWord 0x0000ffff
+#define bMaskDWord 0xffffffff
+
+/*extern u32 rtl8192_CalculateBitShift(u32 dwBitMask);
+
+extern u32 rtl8192_phy_RFSerialRead(struct net_device *dev,
+ RF90_RADIO_PATH_E eRFPath, u32 Offset);
+
+extern void rtl8192_phy_RFSerialWrite(struct net_device *dev,
+ RF90_RADIO_PATH_E eRFPath, u32 Offset, u32 Data);
+
+extern void rtl8192_InitBBRFRegDef(struct net_device *dev);
+
+extern RT_STATUS rtl8192_BB_Config_ParaFile(struct net_device *dev); */
+
+extern u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device *dev, u32 eRFPath);
+
+extern void rtl8192_setBBreg(struct net_device *dev, u32 dwRegAddr,
+ u32 dwBitMask, u32 dwData);
+
+extern u32 rtl8192_QueryBBReg(struct net_device *dev, u32 dwRegAddr,
+ u32 dwBitMask);
+
+extern void rtl8192_phy_SetRFReg(struct net_device *dev,
+ RF90_RADIO_PATH_E eRFPath, u32 RegAddr,
+ u32 BitMask, u32 Data);
+
+extern u32 rtl8192_phy_QueryRFReg(struct net_device *dev,
+ RF90_RADIO_PATH_E eRFPath, u32 RegAddr, u32 BitMask);
+
+extern void rtl8192_phy_configmac(struct net_device *dev);
+
+extern void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType);
+
+extern RT_STATUS rtl8192_phy_checkBBAndRF(struct net_device *dev,
+ HW90_BLOCK_E CheckBlock, RF90_RADIO_PATH_E eRFPath);
+
+extern RT_STATUS rtl8192_BBConfig(struct net_device *dev);
+
+extern void rtl8192_phy_getTxPower(struct net_device *dev);
+
+extern void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel);
+
extern RT_STATUS rtl8192_phy_RFConfig(struct net_device* dev);
+
extern void rtl8192_phy_updateInitGain(struct net_device* dev);
-extern u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device* dev, RF90_RADIO_PATH_E eRFPath);
-extern u8 rtl8192_phy_SwChnl(struct net_device* dev, u8 channel);
-extern void rtl8192_SetBWMode(struct net_device *dev, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset);
+extern u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev,
+ RF90_RADIO_PATH_E eRFPath);
+
+extern u8 rtl8192_phy_SwChnl(struct net_device *dev, u8 channel);
+
+extern void rtl8192_SetBWMode(struct net_device *dev,
+ HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset);
+
extern void rtl8192_SwChnl_WorkItem(struct net_device *dev);
+
extern void rtl8192_SetBWModeWorkItem(struct net_device *dev);
+
extern void InitialGain819xPci(struct net_device *dev, u8 Operation);
-#endif
+#endif /* _R819XU_PHY_H */
diff --git a/drivers/staging/rtl8192e/r819xE_phyreg.h b/drivers/staging/rtl8192e/r819xE_phyreg.h
index 37f0feefaf2..d5de279f664 100644
--- a/drivers/staging/rtl8192e/r819xE_phyreg.h
+++ b/drivers/staging/rtl8192e/r819xE_phyreg.h
@@ -38,6 +38,8 @@
#define MCS_TXAGC 0x340 // MCS AGC
#define CCK_TXAGC 0x348 // CCK AGC
+#define MacBlkCtrl 0x403 // Mac block on/off control register
+
//page8
#define rFPGA0_RFMOD 0x800 //RF mode & CCK TxSC
#define rFPGA0_TxInfo 0x804
@@ -79,55 +81,70 @@
#define rFPGA0_XB_LSSIReadBack 0x8a4
#define rFPGA0_XC_LSSIReadBack 0x8a8
#define rFPGA0_XD_LSSIReadBack 0x8ac
-#define rFPGA0_PSDReport 0x8b4
+#define rFPGA0_PSDReport 0x8b4
#define rFPGA0_XAB_RFInterfaceRB 0x8e0
#define rFPGA0_XCD_RFInterfaceRB 0x8e4
-//page 9
-#define rFPGA1_RFMOD 0x900 //RF mode & OFDM TxSC
-#define rFPGA1_TxBlock 0x904
-#define rFPGA1_DebugSelect 0x908
-#define rFPGA1_TxInfo 0x90c
-
-//page a
-#define rCCK0_System 0xa00
-#define rCCK0_AFESetting 0xa04
-#define rCCK0_CCA 0xa08
-#define rCCK0_RxAGC1 0xa0c //AGC default value, saturation level
-#define rCCK0_RxAGC2 0xa10 //AGC & DAGC
-#define rCCK0_RxHP 0xa14
-#define rCCK0_DSPParameter1 0xa18 //Timing recovery & Channel estimation threshold
-#define rCCK0_DSPParameter2 0xa1c //SQ threshold
-#define rCCK0_TxFilter1 0xa20
-#define rCCK0_TxFilter2 0xa24
-#define rCCK0_DebugPort 0xa28 //debug port and Tx filter3
-#define rCCK0_FalseAlarmReport 0xa2c //0xa2d
-#define rCCK0_TRSSIReport 0xa50
-#define rCCK0_RxReport 0xa54 //0xa57
-#define rCCK0_FACounterLower 0xa5c //0xa5b
-#define rCCK0_FACounterUpper 0xa58 //0xa5c
-
-//page c
-#define rOFDM0_LSTF 0xc00
+/* Page 9 - RF mode & OFDM TxSC */
+#define rFPGA1_RFMOD 0x900
+#define rFPGA1_TxBlock 0x904
+#define rFPGA1_DebugSelect 0x908
+#define rFPGA1_TxInfo 0x90c
+
+/* Page a */
+#define rCCK0_System 0xa00
+#define rCCK0_AFESetting 0xa04
+#define rCCK0_CCA 0xa08
+/* AGC default value, saturation level */
+#define rCCK0_RxAGC1 0xa0c
+/* AGC & DAGC */
+#define rCCK0_RxAGC2 0xa10
+#define rCCK0_RxHP 0xa14
+/* Timing recovery & channel estimation threshold */
+#define rCCK0_DSPParameter1 0xa18
+/* SQ threshold */
+#define rCCK0_DSPParameter2 0xa1c
+#define rCCK0_TxFilter1 0xa20
+#define rCCK0_TxFilter2 0xa24
+/* Debug port and TX filter 3 */
+#define rCCK0_DebugPort 0xa28
+#define rCCK0_FalseAlarmReport 0xa2c
+#define rCCK0_TRSSIReport 0xa50
+#define rCCK0_RxReport 0xa54
+#define rCCK0_FACounterLower 0xa5c
+#define rCCK0_FACounterUpper 0xa58
+
+/* Page c */
+#define rOFDM0_LSTF 0xc00
#define rOFDM0_TRxPathEnable 0xc04
-#define rOFDM0_TRMuxPar 0xc08
-#define rOFDM0_TRSWIsolation 0xc0c
-#define rOFDM0_XARxAFE 0xc10 //RxIQ DC offset, Rx digital filter, DC notch filter
-#define rOFDM0_XARxIQImbalance 0xc14 //RxIQ imblance matrix
-#define rOFDM0_XBRxAFE 0xc18
+#define rOFDM0_TRMuxPar 0xc08
+#define rOFDM0_TRSWIsolation 0xc0c
+/* RxIQ DC offset, Rx digital filter, DC notch filter */
+#define rOFDM0_XARxAFE 0xc10
+/* RxIQ imblance matrix */
+#define rOFDM0_XARxIQImbalance 0xc14
+#define rOFDM0_XBRxAFE 0xc18
#define rOFDM0_XBRxIQImbalance 0xc1c
-#define rOFDM0_XCRxAFE 0xc20
+#define rOFDM0_XCRxAFE 0xc20
#define rOFDM0_XCRxIQImbalance 0xc24
-#define rOFDM0_XDRxAFE 0xc28
+#define rOFDM0_XDRxAFE 0xc28
#define rOFDM0_XDRxIQImbalance 0xc2c
-#define rOFDM0_RxDetector1 0xc30 //PD,BW & SBD
-#define rOFDM0_RxDetector2 0xc34 //SBD & Fame Sync.
-#define rOFDM0_RxDetector3 0xc38 //Frame Sync.
-#define rOFDM0_RxDetector4 0xc3c //PD, SBD, Frame Sync & Short-GI
-#define rOFDM0_RxDSP 0xc40 //Rx Sync Path
-#define rOFDM0_CFOandDAGC 0xc44 //CFO & DAGC
-#define rOFDM0_CCADropThreshold 0xc48 //CCA Drop threshold
-#define rOFDM0_ECCAThreshold 0xc4c // energy CCA
+/* PD, BW & SBD */
+#define rOFDM0_RxDetector1 0xc30
+/* SBD */
+#define rOFDM0_RxDetector2 0xc34
+/* Frame Sync */
+#define rOFDM0_RxDetector3 0xc38
+/* PD, SBD, Frame Sync & Short-GI */
+#define rOFDM0_RxDetector4 0xc3c
+/* Rx Sync Path */
+#define rOFDM0_RxDSP 0xc40
+/* CFO & DAGC */
+#define rOFDM0_CFOandDAGC 0xc44
+/* CCA Drop threshold */
+#define rOFDM0_CCADropThreshold 0xc48
+/* Energy CCA */
+#define rOFDM0_ECCAThreshold 0xc4c
#define rOFDM0_XAAGCCore1 0xc50
#define rOFDM0_XAAGCCore2 0xc54
#define rOFDM0_XBAGCCore1 0xc58
@@ -139,501 +156,517 @@
#define rOFDM0_AGCParameter1 0xc70
#define rOFDM0_AGCParameter2 0xc74
#define rOFDM0_AGCRSSITable 0xc78
-#define rOFDM0_HTSTFAGC 0xc7c
+#define rOFDM0_HTSTFAGC 0xc7c
#define rOFDM0_XATxIQImbalance 0xc80
-#define rOFDM0_XATxAFE 0xc84
+#define rOFDM0_XATxAFE 0xc84
#define rOFDM0_XBTxIQImbalance 0xc88
-#define rOFDM0_XBTxAFE 0xc8c
+#define rOFDM0_XBTxAFE 0xc8c
#define rOFDM0_XCTxIQImbalance 0xc90
-#define rOFDM0_XCTxAFE 0xc94
+#define rOFDM0_XCTxAFE 0xc94
#define rOFDM0_XDTxIQImbalance 0xc98
-#define rOFDM0_XDTxAFE 0xc9c
+#define rOFDM0_XDTxAFE 0xc9c
#define rOFDM0_RxHPParameter 0xce0
#define rOFDM0_TxPseudoNoiseWgt 0xce4
-#define rOFDM0_FrameSync 0xcf0
-#define rOFDM0_DFSReport 0xcf4
-#define rOFDM0_TxCoeff1 0xca4
-#define rOFDM0_TxCoeff2 0xca8
-#define rOFDM0_TxCoeff3 0xcac
-#define rOFDM0_TxCoeff4 0xcb0
-#define rOFDM0_TxCoeff5 0xcb4
-#define rOFDM0_TxCoeff6 0xcb8
-
-
-//page d
-#define rOFDM1_LSTF 0xd00
+#define rOFDM0_FrameSync 0xcf0
+#define rOFDM0_DFSReport 0xcf4
+#define rOFDM0_TxCoeff1 0xca4
+#define rOFDM0_TxCoeff2 0xca8
+#define rOFDM0_TxCoeff3 0xcac
+#define rOFDM0_TxCoeff4 0xcb0
+#define rOFDM0_TxCoeff5 0xcb4
+#define rOFDM0_TxCoeff6 0xcb8
+
+
+/* Page d */
+#define rOFDM1_LSTF 0xd00
#define rOFDM1_TRxPathEnable 0xd04
-#define rOFDM1_CFO 0xd08
-#define rOFDM1_CSI1 0xd10
-#define rOFDM1_SBD 0xd14
-#define rOFDM1_CSI2 0xd18
-#define rOFDM1_CFOTracking 0xd2c
+#define rOFDM1_CFO 0xd08
+#define rOFDM1_CSI1 0xd10
+#define rOFDM1_SBD 0xd14
+#define rOFDM1_CSI2 0xd18
+#define rOFDM1_CFOTracking 0xd2c
#define rOFDM1_TRxMesaure1 0xd34
-#define rOFDM1_IntfDet 0xd3c
-#define rOFDM1_PseudoNoiseStateAB 0xd50
-#define rOFDM1_PseudoNoiseStateCD 0xd54
-#define rOFDM1_RxPseudoNoiseWgt 0xd58
-#define rOFDM_PHYCounter1 0xda0 //cca, parity fail
-#define rOFDM_PHYCounter2 0xda4 //rate illegal, crc8 fail
-#define rOFDM_PHYCounter3 0xda8 //MCS not support
-#define rOFDM_ShortCFOAB 0xdac
-#define rOFDM_ShortCFOCD 0xdb0
-#define rOFDM_LongCFOAB 0xdb4
-#define rOFDM_LongCFOCD 0xdb8
-#define rOFDM_TailCFOAB 0xdbc
-#define rOFDM_TailCFOCD 0xdc0
+#define rOFDM1_IntfDet 0xd3c
+#define rOFDM1_PseudoNoiseStateAB 0xd50
+#define rOFDM1_PseudoNoiseStateCD 0xd54
+#define rOFDM1_RxPseudoNoiseWgt 0xd58
+/* cca, parity fail */
+#define rOFDM_PHYCounter1 0xda0
+/* rate illegal, crc8 fail */
+#define rOFDM_PHYCounter2 0xda4
+/* MCS not supported */
+#define rOFDM_PHYCounter3 0xda8
+#define rOFDM_ShortCFOAB 0xdac
+#define rOFDM_ShortCFOCD 0xdb0
+#define rOFDM_LongCFOAB 0xdb4
+#define rOFDM_LongCFOCD 0xdb8
+#define rOFDM_TailCFOAB 0xdbc
+#define rOFDM_TailCFOCD 0xdc0
#define rOFDM_PWMeasure1 0xdc4
#define rOFDM_PWMeasure2 0xdc8
-#define rOFDM_BWReport 0xdcc
-#define rOFDM_AGCReport 0xdd0
-#define rOFDM_RxSNR 0xdd4
-#define rOFDM_RxEVMCSI 0xdd8
-#define rOFDM_SIGReport 0xddc
-
-//page e
-#define rTxAGC_Rate18_06 0xe00
-#define rTxAGC_Rate54_24 0xe04
-#define rTxAGC_CCK_Mcs32 0xe08
-#define rTxAGC_Mcs03_Mcs00 0xe10
-#define rTxAGC_Mcs07_Mcs04 0xe14
-#define rTxAGC_Mcs11_Mcs08 0xe18
-#define rTxAGC_Mcs15_Mcs12 0xe1c
-
-
-//RF
-//Zebra1
+#define rOFDM_BWReport 0xdcc
+#define rOFDM_AGCReport 0xdd0
+#define rOFDM_RxSNR 0xdd4
+#define rOFDM_RxEVMCSI 0xdd8
+#define rOFDM_SIGReport 0xddc
+
+/* Page e */
+#define rTxAGC_Rate18_06 0xe00
+#define rTxAGC_Rate54_24 0xe04
+#define rTxAGC_CCK_Mcs32 0xe08
+#define rTxAGC_Mcs03_Mcs00 0xe10
+#define rTxAGC_Mcs07_Mcs04 0xe14
+#define rTxAGC_Mcs11_Mcs08 0xe18
+#define rTxAGC_Mcs15_Mcs12 0xe1c
+
+
+/* RF Zebra 1 */
#define rZebra1_HSSIEnable 0x0
#define rZebra1_TRxEnable1 0x1
#define rZebra1_TRxEnable2 0x2
-#define rZebra1_AGC 0x4
+#define rZebra1_AGC 0x4
#define rZebra1_ChargePump 0x5
-#define rZebra1_Channel 0x7
-#define rZebra1_TxGain 0x8
-#define rZebra1_TxLPF 0x9
-#define rZebra1_RxLPF 0xb
+#define rZebra1_Channel 0x7
+#define rZebra1_TxGain 0x8
+#define rZebra1_TxLPF 0x9
+#define rZebra1_RxLPF 0xb
#define rZebra1_RxHPFCorner 0xc
-//Zebra4
-#define rGlobalCtrl 0
-#define rRTL8256_TxLPF 19
-#define rRTL8256_RxLPF 11
+/* Zebra 4 */
+#define rGlobalCtrl 0
+#define rRTL8256_TxLPF 19
+#define rRTL8256_RxLPF 11
-//RTL8258
-#define rRTL8258_TxLPF 0x11
-#define rRTL8258_RxLPF 0x13
+/* RTL8258 */
+#define rRTL8258_TxLPF 0x11
+#define rRTL8258_RxLPF 0x13
#define rRTL8258_RSSILPF 0xa
-//Bit Mask
-//page-1
-#define bBBResetB 0x100
-#define bGlobalResetB 0x200
-#define bOFDMTxStart 0x4
-#define bCCKTxStart 0x8
-#define bCRC32Debug 0x100
-#define bPMACLoopback 0x10
-#define bTxLSIG 0xffffff
-#define bOFDMTxRate 0xf
-#define bOFDMTxReserved 0x10
-#define bOFDMTxLength 0x1ffe0
-#define bOFDMTxParity 0x20000
-#define bTxHTSIG1 0xffffff
-#define bTxHTMCSRate 0x7f
-#define bTxHTBW 0x80
-#define bTxHTLength 0xffff00
-#define bTxHTSIG2 0xffffff
-#define bTxHTSmoothing 0x1
-#define bTxHTSounding 0x2
-#define bTxHTReserved 0x4
-#define bTxHTAggreation 0x8
-#define bTxHTSTBC 0x30
-#define bTxHTAdvanceCoding 0x40
-#define bTxHTShortGI 0x80
-#define bTxHTNumberHT_LTF 0x300
-#define bTxHTCRC8 0x3fc00
-#define bCounterReset 0x10000
-#define bNumOfOFDMTx 0xffff
-#define bNumOfCCKTx 0xffff0000
-#define bTxIdleInterval 0xffff
-#define bOFDMService 0xffff0000
-#define bTxMACHeader 0xffffffff
-#define bTxDataInit 0xff
-#define bTxHTMode 0x100
-#define bTxDataType 0x30000
-#define bTxRandomSeed 0xffffffff
-#define bCCKTxPreamble 0x1
-#define bCCKTxSFD 0xffff0000
-#define bCCKTxSIG 0xff
-#define bCCKTxService 0xff00
-#define bCCKLengthExt 0x8000
-#define bCCKTxLength 0xffff0000
-#define bCCKTxCRC16 0xffff
-#define bCCKTxStatus 0x1
-#define bOFDMTxStatus 0x2
-
-//page-8
-#define bRFMOD 0x1
-#define bJapanMode 0x2
-#define bCCKTxSC 0x30
-#define bCCKEn 0x1000000
-#define bOFDMEn 0x2000000
-#define bOFDMRxADCPhase 0x10000
-#define bOFDMTxDACPhase 0x40000
-#define bXATxAGC 0x3f
-#define bXBTxAGC 0xf00
-#define bXCTxAGC 0xf000
-#define bXDTxAGC 0xf0000
-#define bPAStart 0xf0000000
-#define bTRStart 0x00f00000
-#define bRFStart 0x0000f000
-#define bBBStart 0x000000f0
-#define bBBCCKStart 0x0000000f
-#define bPAEnd 0xf //Reg0x814
-#define bTREnd 0x0f000000
-#define bRFEnd 0x000f0000
-#define bCCAMask 0x000000f0 //T2R
-#define bR2RCCAMask 0x00000f00
-#define bHSSI_R2TDelay 0xf8000000
-#define bHSSI_T2RDelay 0xf80000
-#define bContTxHSSI 0x400 //channel gain at continue Tx
-#define bIGFromCCK 0x200
-#define bAGCAddress 0x3f
-#define bRxHPTx 0x7000
-#define bRxHPT2R 0x38000
-#define bRxHPCCKIni 0xc0000
-#define bAGCTxCode 0xc00000
-#define bAGCRxCode 0x300000
-#define b3WireDataLength 0x800
-#define b3WireAddressLength 0x400
-#define b3WireRFPowerDown 0x1
-//#define bHWSISelect 0x8
-#define b5GPAPEPolarity 0x40000000
-#define b2GPAPEPolarity 0x80000000
-#define bRFSW_TxDefaultAnt 0x3
-#define bRFSW_TxOptionAnt 0x30
-#define bRFSW_RxDefaultAnt 0x300
-#define bRFSW_RxOptionAnt 0x3000
-#define bRFSI_3WireData 0x1
-#define bRFSI_3WireClock 0x2
-#define bRFSI_3WireLoad 0x4
-#define bRFSI_3WireRW 0x8
-#define bRFSI_3Wire 0xf //3-wire total control
-#define bRFSI_RFENV 0x10
-#define bRFSI_TRSW 0x20
-#define bRFSI_TRSWB 0x40
-#define bRFSI_ANTSW 0x100
-#define bRFSI_ANTSWB 0x200
-#define bRFSI_PAPE 0x400
-#define bRFSI_PAPE5G 0x800
-#define bBandSelect 0x1
-#define bHTSIG2_GI 0x80
-#define bHTSIG2_Smoothing 0x01
-#define bHTSIG2_Sounding 0x02
-#define bHTSIG2_Aggreaton 0x08
-#define bHTSIG2_STBC 0x30
-#define bHTSIG2_AdvCoding 0x40
+/* Bit Mask */
+/* Page 1 */
+#define bBBResetB 0x100
+#define bGlobalResetB 0x200
+#define bOFDMTxStart 0x4
+#define bCCKTxStart 0x8
+#define bCRC32Debug 0x100
+#define bPMACLoopback 0x10
+#define bTxLSIG 0xffffff
+#define bOFDMTxRate 0xf
+#define bOFDMTxReserved 0x10
+#define bOFDMTxLength 0x1ffe0
+#define bOFDMTxParity 0x20000
+#define bTxHTSIG1 0xffffff
+#define bTxHTMCSRate 0x7f
+#define bTxHTBW 0x80
+#define bTxHTLength 0xffff00
+#define bTxHTSIG2 0xffffff
+#define bTxHTSmoothing 0x1
+#define bTxHTSounding 0x2
+#define bTxHTReserved 0x4
+#define bTxHTAggreation 0x8
+#define bTxHTSTBC 0x30
+#define bTxHTAdvanceCoding 0x40
+#define bTxHTShortGI 0x80
+#define bTxHTNumberHT_LTF 0x300
+#define bTxHTCRC8 0x3fc00
+#define bCounterReset 0x10000
+#define bNumOfOFDMTx 0xffff
+#define bNumOfCCKTx 0xffff0000
+#define bTxIdleInterval 0xffff
+#define bOFDMService 0xffff0000
+#define bTxMACHeader 0xffffffff
+#define bTxDataInit 0xff
+#define bTxHTMode 0x100
+#define bTxDataType 0x30000
+#define bTxRandomSeed 0xffffffff
+#define bCCKTxPreamble 0x1
+#define bCCKTxSFD 0xffff0000
+#define bCCKTxSIG 0xff
+#define bCCKTxService 0xff00
+#define bCCKLengthExt 0x8000
+#define bCCKTxLength 0xffff0000
+#define bCCKTxCRC16 0xffff
+#define bCCKTxStatus 0x1
+#define bOFDMTxStatus 0x2
+
+/* Page 8 */
+#define bRFMOD 0x1
+#define bJapanMode 0x2
+#define bCCKTxSC 0x30
+#define bCCKEn 0x1000000
+#define bOFDMEn 0x2000000
+#define bOFDMRxADCPhase 0x10000
+#define bOFDMTxDACPhase 0x40000
+#define bXATxAGC 0x3f
+#define bXBTxAGC 0xf00
+#define bXCTxAGC 0xf000
+#define bXDTxAGC 0xf0000
+#define bPAStart 0xf0000000
+#define bTRStart 0x00f00000
+#define bRFStart 0x0000f000
+#define bBBStart 0x000000f0
+#define bBBCCKStart 0x0000000f
+/* Reg)x814 */
+#define bPAEnd 0xf
+#define bTREnd 0x0f000000
+#define bRFEnd 0x000f0000
+/* T2R */
+#define bCCAMask 0x000000f0
+#define bR2RCCAMask 0x00000f00
+#define bHSSI_R2TDelay 0xf8000000
+#define bHSSI_T2RDelay 0xf80000
+/* Channel gain at continue TX. */
+#define bContTxHSSI 0x400
+#define bIGFromCCK 0x200
+#define bAGCAddress 0x3f
+#define bRxHPTx 0x7000
+#define bRxHPT2R 0x38000
+#define bRxHPCCKIni 0xc0000
+#define bAGCTxCode 0xc00000
+#define bAGCRxCode 0x300000
+#define b3WireDataLength 0x800
+#define b3WireAddressLength 0x400
+#define b3WireRFPowerDown 0x1
+/*#define bHWSISelect 0x8 */
+#define b5GPAPEPolarity 0x40000000
+#define b2GPAPEPolarity 0x80000000
+#define bRFSW_TxDefaultAnt 0x3
+#define bRFSW_TxOptionAnt 0x30
+#define bRFSW_RxDefaultAnt 0x300
+#define bRFSW_RxOptionAnt 0x3000
+#define bRFSI_3WireData 0x1
+#define bRFSI_3WireClock 0x2
+#define bRFSI_3WireLoad 0x4
+#define bRFSI_3WireRW 0x8
+/* 3-wire total control */
+#define bRFSI_3Wire 0xf
+#define bRFSI_RFENV 0x10
+#define bRFSI_TRSW 0x20
+#define bRFSI_TRSWB 0x40
+#define bRFSI_ANTSW 0x100
+#define bRFSI_ANTSWB 0x200
+#define bRFSI_PAPE 0x400
+#define bRFSI_PAPE5G 0x800
+#define bBandSelect 0x1
+#define bHTSIG2_GI 0x80
+#define bHTSIG2_Smoothing 0x01
+#define bHTSIG2_Sounding 0x02
+#define bHTSIG2_Aggreaton 0x08
+#define bHTSIG2_STBC 0x30
+#define bHTSIG2_AdvCoding 0x40
#define bHTSIG2_NumOfHTLTF 0x300
-#define bHTSIG2_CRC8 0x3fc
-#define bHTSIG1_MCS 0x7f
-#define bHTSIG1_BandWidth 0x80
-#define bHTSIG1_HTLength 0xffff
-#define bLSIG_Rate 0xf
-#define bLSIG_Reserved 0x10
-#define bLSIG_Length 0x1fffe
-#define bLSIG_Parity 0x20
-#define bCCKRxPhase 0x4
-#define bLSSIReadAddress 0x3f000000 //LSSI "Read" Address
-#define bLSSIReadEdge 0x80000000 //LSSI "Read" edge signal
-#define bLSSIReadBackData 0xfff
-#define bLSSIReadOKFlag 0x1000
-#define bCCKSampleRate 0x8 //0: 44MHz, 1:88MHz
-
-#define bRegulator0Standby 0x1
-#define bRegulatorPLLStandby 0x2
-#define bRegulator1Standby 0x4
-#define bPLLPowerUp 0x8
-#define bDPLLPowerUp 0x10
-#define bDA10PowerUp 0x20
-#define bAD7PowerUp 0x200
-#define bDA6PowerUp 0x2000
-#define bXtalPowerUp 0x4000
-#define b40MDClkPowerUP 0x8000
-#define bDA6DebugMode 0x20000
-#define bDA6Swing 0x380000
-#define bADClkPhase 0x4000000
-#define b80MClkDelay 0x18000000
-#define bAFEWatchDogEnable 0x20000000
-#define bXtalCap 0x0f000000
-#define bXtalCap01 0xc0000000
-#define bXtalCap23 0x3
-#define bXtalCap92x 0x0f000000
-#define bIntDifClkEnable 0x400
-#define bExtSigClkEnable 0x800
+#define bHTSIG2_CRC8 0x3fc
+#define bHTSIG1_MCS 0x7f
+#define bHTSIG1_BandWidth 0x80
+#define bHTSIG1_HTLength 0xffff
+#define bLSIG_Rate 0xf
+#define bLSIG_Reserved 0x10
+#define bLSIG_Length 0x1fffe
+#define bLSIG_Parity 0x20
+#define bCCKRxPhase 0x4
+/* LSSI "read" address */
+#define bLSSIReadAddress 0x3f000000
+/* LSSI "read" edge signal */
+#define bLSSIReadEdge 0x80000000
+#define bLSSIReadBackData 0xfff
+#define bLSSIReadOKFlag 0x1000
+/* 0: 44 MHz, 1: 88MHz */
+#define bCCKSampleRate 0x8
+
+#define bRegulator0Standby 0x1
+#define bRegulatorPLLStandby 0x2
+#define bRegulator1Standby 0x4
+#define bPLLPowerUp 0x8
+#define bDPLLPowerUp 0x10
+#define bDA10PowerUp 0x20
+#define bAD7PowerUp 0x200
+#define bDA6PowerUp 0x2000
+#define bXtalPowerUp 0x4000
+#define b40MDClkPowerUP 0x8000
+#define bDA6DebugMode 0x20000
+#define bDA6Swing 0x380000
+#define bADClkPhase 0x4000000
+#define b80MClkDelay 0x18000000
+#define bAFEWatchDogEnable 0x20000000
+#define bXtalCap 0x0f000000
+#define bXtalCap01 0xc0000000
+#define bXtalCap23 0x3
+#define bXtalCap92x 0x0f000000
+#define bIntDifClkEnable 0x400
+#define bExtSigClkEnable 0x800
#define bBandgapMbiasPowerUp 0x10000
-#define bAD11SHGain 0xc0000
-#define bAD11InputRange 0x700000
-#define bAD11OPCurrent 0x3800000
-#define bIPathLoopback 0x4000000
-#define bQPathLoopback 0x8000000
-#define bAFELoopback 0x10000000
-#define bDA10Swing 0x7e0
-#define bDA10Reverse 0x800
-#define bDAClkSource 0x1000
-#define bAD7InputRange 0x6000
-#define bAD7Gain 0x38000
-#define bAD7OutputCMMode 0x40000
-#define bAD7InputCMMode 0x380000
-#define bAD7Current 0xc00000
-#define bRegulatorAdjust 0x7000000
-#define bAD11PowerUpAtTx 0x1
-#define bDA10PSAtTx 0x10
-#define bAD11PowerUpAtRx 0x100
-#define bDA10PSAtRx 0x1000
-
-#define bCCKRxAGCFormat 0x200
-
-#define bPSDFFTSamplepPoint 0xc000
-#define bPSDAverageNum 0x3000
-#define bIQPathControl 0xc00
-#define bPSDFreq 0x3ff
-#define bPSDAntennaPath 0x30
-#define bPSDIQSwitch 0x40
-#define bPSDRxTrigger 0x400000
-#define bPSDTxTrigger 0x80000000
-#define bPSDSineToneScale 0x7f000000
-#define bPSDReport 0xffff
-
-//page-9
-#define bOFDMTxSC 0x30000000
-#define bCCKTxOn 0x1
-#define bOFDMTxOn 0x2
-#define bDebugPage 0xfff //reset debug page and also HWord, LWord
-#define bDebugItem 0xff //reset debug page and LWord
-#define bAntL 0x10
-#define bAntNonHT 0x100
-#define bAntHT1 0x1000
-#define bAntHT2 0x10000
-#define bAntHT1S1 0x100000
-#define bAntNonHTS1 0x1000000
-
-//page-a
-#define bCCKBBMode 0x3
-#define bCCKTxPowerSaving 0x80
-#define bCCKRxPowerSaving 0x40
-#define bCCKSideBand 0x10
-#define bCCKScramble 0x8
-#define bCCKAntDiversity 0x8000
+#define bAD11SHGain 0xc0000
+#define bAD11InputRange 0x700000
+#define bAD11OPCurrent 0x3800000
+#define bIPathLoopback 0x4000000
+#define bQPathLoopback 0x8000000
+#define bAFELoopback 0x10000000
+#define bDA10Swing 0x7e0
+#define bDA10Reverse 0x800
+#define bDAClkSource 0x1000
+#define bAD7InputRange 0x6000
+#define bAD7Gain 0x38000
+#define bAD7OutputCMMode 0x40000
+#define bAD7InputCMMode 0x380000
+#define bAD7Current 0xc00000
+#define bRegulatorAdjust 0x7000000
+#define bAD11PowerUpAtTx 0x1
+#define bDA10PSAtTx 0x10
+#define bAD11PowerUpAtRx 0x100
+#define bDA10PSAtRx 0x1000
+
+#define bCCKRxAGCFormat 0x200
+
+#define bPSDFFTSamplepPoint 0xc000
+#define bPSDAverageNum 0x3000
+#define bIQPathControl 0xc00
+#define bPSDFreq 0x3ff
+#define bPSDAntennaPath 0x30
+#define bPSDIQSwitch 0x40
+#define bPSDRxTrigger 0x400000
+#define bPSDTxTrigger 0x80000000
+#define bPSDSineToneScale 0x7f000000
+#define bPSDReport 0xffff
+
+/* Page 8 */
+#define bOFDMTxSC 0x30000000
+#define bCCKTxOn 0x1
+#define bOFDMTxOn 0x2
+/* Reset debug page and also HWord, LWord */
+#define bDebugPage 0xfff
+/* Reset debug page and LWord */
+#define bDebugItem 0xff
+#define bAntL 0x10
+#define bAntNonHT 0x100
+#define bAntHT1 0x1000
+#define bAntHT2 0x10000
+#define bAntHT1S1 0x100000
+#define bAntNonHTS1 0x1000000
+
+/* Page a */
+#define bCCKBBMode 0x3
+#define bCCKTxPowerSaving 0x80
+#define bCCKRxPowerSaving 0x40
+#define bCCKSideBand 0x10
+#define bCCKScramble 0x8
+#define bCCKAntDiversity 0x8000
#define bCCKCarrierRecovery 0x4000
-#define bCCKTxRate 0x3000
-#define bCCKDCCancel 0x0800
-#define bCCKISICancel 0x0400
-#define bCCKMatchFilter 0x0200
-#define bCCKEqualizer 0x0100
-#define bCCKPreambleDetect 0x800000
-#define bCCKFastFalseCCA 0x400000
-#define bCCKChEstStart 0x300000
-#define bCCKCCACount 0x080000
-#define bCCKcs_lim 0x070000
-#define bCCKBistMode 0x80000000
-#define bCCKCCAMask 0x40000000
+#define bCCKTxRate 0x3000
+#define bCCKDCCancel 0x0800
+#define bCCKISICancel 0x0400
+#define bCCKMatchFilter 0x0200
+#define bCCKEqualizer 0x0100
+#define bCCKPreambleDetect 0x800000
+#define bCCKFastFalseCCA 0x400000
+#define bCCKChEstStart 0x300000
+#define bCCKCCACount 0x080000
+#define bCCKcs_lim 0x070000
+#define bCCKBistMode 0x80000000
+#define bCCKCCAMask 0x40000000
#define bCCKTxDACPhase 0x4
-#define bCCKRxADCPhase 0x20000000 //r_rx_clk
+/* r_rx_clk */
+#define bCCKRxADCPhase 0x20000000
#define bCCKr_cp_mode0 0x0100
-#define bCCKTxDCOffset 0xf0
-#define bCCKRxDCOffset 0xf
-#define bCCKCCAMode 0xc000
-#define bCCKFalseCS_lim 0x3f00
-#define bCCKCS_ratio 0xc00000
-#define bCCKCorgBit_sel 0x300000
-#define bCCKPD_lim 0x0f0000
-#define bCCKNewCCA 0x80000000
-#define bCCKRxHPofIG 0x8000
-#define bCCKRxIG 0x7f00
-#define bCCKLNAPolarity 0x800000
-#define bCCKRx1stGain 0x7f0000
-#define bCCKRFExtend 0x20000000 //CCK Rx Iinital gain polarity
-#define bCCKRxAGCSatLevel 0x1f000000
-#define bCCKRxAGCSatCount 0xe0
-#define bCCKRxRFSettle 0x1f //AGCsamp_dly
-#define bCCKFixedRxAGC 0x8000
-//#define bCCKRxAGCFormat 0x4000 //remove to HSSI register 0x824
-#define bCCKAntennaPolarity 0x2000
-#define bCCKTxFilterType 0x0c00
+#define bCCKTxDCOffset 0xf0
+#define bCCKRxDCOffset 0xf
+#define bCCKCCAMode 0xc000
+#define bCCKFalseCS_lim 0x3f00
+#define bCCKCS_ratio 0xc00000
+#define bCCKCorgBit_sel 0x300000
+#define bCCKPD_lim 0x0f0000
+#define bCCKNewCCA 0x80000000
+#define bCCKRxHPofIG 0x8000
+#define bCCKRxIG 0x7f00
+#define bCCKLNAPolarity 0x800000
+#define bCCKRx1stGain 0x7f0000
+/* CCK Rx Initial gain polarity */
+#define bCCKRFExtend 0x20000000
+#define bCCKRxAGCSatLevel 0x1f000000
+#define bCCKRxAGCSatCount 0xe0
+/* AGCSAmp_dly */
+#define bCCKRxRFSettle 0x1f
+#define bCCKFixedRxAGC 0x8000
+/*#define bCCKRxAGCFormat 0x4000 remove to HSSI register 0x824 */
+#define bCCKAntennaPolarity 0x2000
+#define bCCKTxFilterType 0x0c00
#define bCCKRxAGCReportType 0x0300
-#define bCCKRxDAGCEn 0x80000000
-#define bCCKRxDAGCPeriod 0x20000000
+#define bCCKRxDAGCEn 0x80000000
+#define bCCKRxDAGCPeriod 0x20000000
#define bCCKRxDAGCSatLevel 0x1f000000
-#define bCCKTimingRecovery 0x800000
-#define bCCKTxC0 0x3f0000
-#define bCCKTxC1 0x3f000000
-#define bCCKTxC2 0x3f
-#define bCCKTxC3 0x3f00
-#define bCCKTxC4 0x3f0000
-#define bCCKTxC5 0x3f000000
-#define bCCKTxC6 0x3f
-#define bCCKTxC7 0x3f00
-#define bCCKDebugPort 0xff0000
-#define bCCKDACDebug 0x0f000000
-#define bCCKFalseAlarmEnable 0x8000
-#define bCCKFalseAlarmRead 0x4000
-#define bCCKTRSSI 0x7f
-#define bCCKRxAGCReport 0xfe
-#define bCCKRxReport_AntSel 0x80000000
-#define bCCKRxReport_MFOff 0x40000000
+#define bCCKTimingRecovery 0x800000
+#define bCCKTxC0 0x3f0000
+#define bCCKTxC1 0x3f000000
+#define bCCKTxC2 0x3f
+#define bCCKTxC3 0x3f00
+#define bCCKTxC4 0x3f0000
+#define bCCKTxC5 0x3f000000
+#define bCCKTxC6 0x3f
+#define bCCKTxC7 0x3f00
+#define bCCKDebugPort 0xff0000
+#define bCCKDACDebug 0x0f000000
+#define bCCKFalseAlarmEnable 0x8000
+#define bCCKFalseAlarmRead 0x4000
+#define bCCKTRSSI 0x7f
+#define bCCKRxAGCReport 0xfe
+#define bCCKRxReport_AntSel 0x80000000
+#define bCCKRxReport_MFOff 0x40000000
#define bCCKRxRxReport_SQLoss 0x20000000
-#define bCCKRxReport_Pktloss 0x10000000
+#define bCCKRxReport_Pktloss 0x10000000
#define bCCKRxReport_Lockedbit 0x08000000
#define bCCKRxReport_RateError 0x04000000
-#define bCCKRxReport_RxRate 0x03000000
+#define bCCKRxReport_RxRate 0x03000000
#define bCCKRxFACounterLower 0xff
#define bCCKRxFACounterUpper 0xff000000
-#define bCCKRxHPAGCStart 0xe000
-#define bCCKRxHPAGCFinal 0x1c00
+#define bCCKRxHPAGCStart 0xe000
+#define bCCKRxHPAGCFinal 0x1c00
#define bCCKRxFalseAlarmEnable 0x8000
-#define bCCKFACounterFreeze 0x4000
-
-#define bCCKTxPathSel 0x10000000
-#define bCCKDefaultRxPath 0xc000000
-#define bCCKOptionRxPath 0x3000000
-
-//page c
-#define bNumOfSTF 0x3
-#define bShift_L 0xc0
-#define bGI_TH 0xc
-#define bRxPathA 0x1
-#define bRxPathB 0x2
-#define bRxPathC 0x4
-#define bRxPathD 0x8
-#define bTxPathA 0x1
-#define bTxPathB 0x2
-#define bTxPathC 0x4
-#define bTxPathD 0x8
-#define bTRSSIFreq 0x200
-#define bADCBackoff 0x3000
-#define bDFIRBackoff 0xc000
-#define bTRSSILatchPhase 0x10000
-#define bRxIDCOffset 0xff
-#define bRxQDCOffset 0xff00
-#define bRxDFIRMode 0x1800000
-#define bRxDCNFType 0xe000000
-#define bRXIQImb_A 0x3ff
-#define bRXIQImb_B 0xfc00
-#define bRXIQImb_C 0x3f0000
-#define bRXIQImb_D 0xffc00000
-#define bDC_dc_Notch 0x60000
-#define bRxNBINotch 0x1f000000
-#define bPD_TH 0xf
-#define bPD_TH_Opt2 0xc000
-#define bPWED_TH 0x700
-#define bIfMF_Win_L 0x800
-#define bPD_Option 0x1000
-#define bMF_Win_L 0xe000
-#define bBW_Search_L 0x30000
-#define bwin_enh_L 0xc0000
-#define bBW_TH 0x700000
-#define bED_TH2 0x3800000
-#define bBW_option 0x4000000
-#define bRatio_TH 0x18000000
-#define bWindow_L 0xe0000000
-#define bSBD_Option 0x1
-#define bFrame_TH 0x1c
-#define bFS_Option 0x60
-#define bDC_Slope_check 0x80
-#define bFGuard_Counter_DC_L 0xe00
-#define bFrame_Weight_Short 0x7000
-#define bSub_Tune 0xe00000
-#define bFrame_DC_Length 0xe000000
-#define bSBD_start_offset 0x30000000
-#define bFrame_TH_2 0x7
-#define bFrame_GI2_TH 0x38
-#define bGI2_Sync_en 0x40
-#define bSarch_Short_Early 0x300
-#define bSarch_Short_Late 0xc00
-#define bSarch_GI2_Late 0x70000
-#define bCFOAntSum 0x1
-#define bCFOAcc 0x2
-#define bCFOStartOffset 0xc
-#define bCFOLookBack 0x70
-#define bCFOSumWeight 0x80
-#define bDAGCEnable 0x10000
-#define bTXIQImb_A 0x3ff
-#define bTXIQImb_B 0xfc00
-#define bTXIQImb_C 0x3f0000
-#define bTXIQImb_D 0xffc00000
-#define bTxIDCOffset 0xff
-#define bTxQDCOffset 0xff00
-#define bTxDFIRMode 0x10000
-#define bTxPesudoNoiseOn 0x4000000
-#define bTxPesudoNoise_A 0xff
-#define bTxPesudoNoise_B 0xff00
-#define bTxPesudoNoise_C 0xff0000
-#define bTxPesudoNoise_D 0xff000000
-#define bCCADropOption 0x20000
-#define bCCADropThres 0xfff00000
-#define bEDCCA_H 0xf
-#define bEDCCA_L 0xf0
-#define bLambda_ED 0x300
-#define bRxInitialGain 0x7f
-#define bRxAntDivEn 0x80
-#define bRxAGCAddressForLNA 0x7f00
-#define bRxHighPowerFlow 0x8000
-#define bRxAGCFreezeThres 0xc0000
-#define bRxFreezeStep_AGC1 0x300000
-#define bRxFreezeStep_AGC2 0xc00000
-#define bRxFreezeStep_AGC3 0x3000000
-#define bRxFreezeStep_AGC0 0xc000000
-#define bRxRssi_Cmp_En 0x10000000
-#define bRxQuickAGCEn 0x20000000
-#define bRxAGCFreezeThresMode 0x40000000
-#define bRxOverFlowCheckType 0x80000000
-#define bRxAGCShift 0x7f
-#define bTRSW_Tri_Only 0x80
-#define bPowerThres 0x300
-#define bRxAGCEn 0x1
-#define bRxAGCTogetherEn 0x2
-#define bRxAGCMin 0x4
-#define bRxHP_Ini 0x7
-#define bRxHP_TRLNA 0x70
-#define bRxHP_RSSI 0x700
-#define bRxHP_BBP1 0x7000
-#define bRxHP_BBP2 0x70000
-#define bRxHP_BBP3 0x700000
-#define bRSSI_H 0x7f0000 //the threshold for high power
-#define bRSSI_Gen 0x7f000000 //the threshold for ant diversity
-#define bRxSettle_TRSW 0x7
-#define bRxSettle_LNA 0x38
-#define bRxSettle_RSSI 0x1c0
-#define bRxSettle_BBP 0xe00
-#define bRxSettle_RxHP 0x7000
-#define bRxSettle_AntSW_RSSI 0x38000
-#define bRxSettle_AntSW 0xc0000
-#define bRxProcessTime_DAGC 0x300000
-#define bRxSettle_HSSI 0x400000
-#define bRxProcessTime_BBPPW 0x800000
-#define bRxAntennaPowerShift 0x3000000
-#define bRSSITableSelect 0xc000000
-#define bRxHP_Final 0x7000000
-#define bRxHTSettle_BBP 0x7
-#define bRxHTSettle_HSSI 0x8
-#define bRxHTSettle_RxHP 0x70
-#define bRxHTSettle_BBPPW 0x80
-#define bRxHTSettle_Idle 0x300
-#define bRxHTSettle_Reserved 0x1c00
-#define bRxHTRxHPEn 0x8000
-#define bRxHTAGCFreezeThres 0x30000
-#define bRxHTAGCTogetherEn 0x40000
-#define bRxHTAGCMin 0x80000
-#define bRxHTAGCEn 0x100000
-#define bRxHTDAGCEn 0x200000
-#define bRxHTRxHP_BBP 0x1c00000
-#define bRxHTRxHP_Final 0xe0000000
-#define bRxPWRatioTH 0x3
-#define bRxPWRatioEn 0x4
-#define bRxMFHold 0x3800
-#define bRxPD_Delay_TH1 0x38
-#define bRxPD_Delay_TH2 0x1c0
-#define bRxPD_DC_COUNT_MAX 0x600
-//#define bRxMF_Hold 0x3800
+#define bCCKFACounterFreeze 0x4000
+
+#define bCCKTxPathSel 0x10000000
+#define bCCKDefaultRxPath 0xc000000
+#define bCCKOptionRxPath 0x3000000
+
+/* Page c */
+#define bNumOfSTF 0x3
+#define bShift_L 0xc0
+#define bGI_TH 0xc
+#define bRxPathA 0x1
+#define bRxPathB 0x2
+#define bRxPathC 0x4
+#define bRxPathD 0x8
+#define bTxPathA 0x1
+#define bTxPathB 0x2
+#define bTxPathC 0x4
+#define bTxPathD 0x8
+#define bTRSSIFreq 0x200
+#define bADCBackoff 0x3000
+#define bDFIRBackoff 0xc000
+#define bTRSSILatchPhase 0x10000
+#define bRxIDCOffset 0xff
+#define bRxQDCOffset 0xff00
+#define bRxDFIRMode 0x1800000
+#define bRxDCNFType 0xe000000
+#define bRXIQImb_A 0x3ff
+#define bRXIQImb_B 0xfc00
+#define bRXIQImb_C 0x3f0000
+#define bRXIQImb_D 0xffc00000
+#define bDC_dc_Notch 0x60000
+#define bRxNBINotch 0x1f000000
+#define bPD_TH 0xf
+#define bPD_TH_Opt2 0xc000
+#define bPWED_TH 0x700
+#define bIfMF_Win_L 0x800
+#define bPD_Option 0x1000
+#define bMF_Win_L 0xe000
+#define bBW_Search_L 0x30000
+#define bwin_enh_L 0xc0000
+#define bBW_TH 0x700000
+#define bED_TH2 0x3800000
+#define bBW_option 0x4000000
+#define bRatio_TH 0x18000000
+#define bWindow_L 0xe0000000
+#define bSBD_Option 0x1
+#define bFrame_TH 0x1c
+#define bFS_Option 0x60
+#define bDC_Slope_check 0x80
+#define bFGuard_Counter_DC_L 0xe00
+#define bFrame_Weight_Short 0x7000
+#define bSub_Tune 0xe00000
+#define bFrame_DC_Length 0xe000000
+#define bSBD_start_offset 0x30000000
+#define bFrame_TH_2 0x7
+#define bFrame_GI2_TH 0x38
+#define bGI2_Sync_en 0x40
+#define bSarch_Short_Early 0x300
+#define bSarch_Short_Late 0xc00
+#define bSarch_GI2_Late 0x70000
+#define bCFOAntSum 0x1
+#define bCFOAcc 0x2
+#define bCFOStartOffset 0xc
+#define bCFOLookBack 0x70
+#define bCFOSumWeight 0x80
+#define bDAGCEnable 0x10000
+#define bTXIQImb_A 0x3ff
+#define bTXIQImb_B 0xfc00
+#define bTXIQImb_C 0x3f0000
+#define bTXIQImb_D 0xffc00000
+#define bTxIDCOffset 0xff
+#define bTxQDCOffset 0xff00
+#define bTxDFIRMode 0x10000
+#define bTxPesudoNoiseOn 0x4000000
+#define bTxPesudoNoise_A 0xff
+#define bTxPesudoNoise_B 0xff00
+#define bTxPesudoNoise_C 0xff0000
+#define bTxPesudoNoise_D 0xff000000
+#define bCCADropOption 0x20000
+#define bCCADropThres 0xfff00000
+#define bEDCCA_H 0xf
+#define bEDCCA_L 0xf0
+#define bLambda_ED 0x300
+#define bRxInitialGain 0x7f
+#define bRxAntDivEn 0x80
+#define bRxAGCAddressForLNA 0x7f00
+#define bRxHighPowerFlow 0x8000
+#define bRxAGCFreezeThres 0xc0000
+#define bRxFreezeStep_AGC1 0x300000
+#define bRxFreezeStep_AGC2 0xc00000
+#define bRxFreezeStep_AGC3 0x3000000
+#define bRxFreezeStep_AGC0 0xc000000
+#define bRxRssi_Cmp_En 0x10000000
+#define bRxQuickAGCEn 0x20000000
+#define bRxAGCFreezeThresMode 0x40000000
+#define bRxOverFlowCheckType 0x80000000
+#define bRxAGCShift 0x7f
+#define bTRSW_Tri_Only 0x80
+#define bPowerThres 0x300
+#define bRxAGCEn 0x1
+#define bRxAGCTogetherEn 0x2
+#define bRxAGCMin 0x4
+#define bRxHP_Ini 0x7
+#define bRxHP_TRLNA 0x70
+#define bRxHP_RSSI 0x700
+#define bRxHP_BBP1 0x7000
+#define bRxHP_BBP2 0x70000
+#define bRxHP_BBP3 0x700000
+/* The threshold for high power */
+#define bRSSI_H 0x7f0000
+/* The threshold for ant diversity */
+#define bRSSI_Gen 0x7f000000
+#define bRxSettle_TRSW 0x7
+#define bRxSettle_LNA 0x38
+#define bRxSettle_RSSI 0x1c0
+#define bRxSettle_BBP 0xe00
+#define bRxSettle_RxHP 0x7000
+#define bRxSettle_AntSW_RSSI 0x38000
+#define bRxSettle_AntSW 0xc0000
+#define bRxProcessTime_DAGC 0x300000
+#define bRxSettle_HSSI 0x400000
+#define bRxProcessTime_BBPPW 0x800000
+#define bRxAntennaPowerShift 0x3000000
+#define bRSSITableSelect 0xc000000
+#define bRxHP_Final 0x7000000
+#define bRxHTSettle_BBP 0x7
+#define bRxHTSettle_HSSI 0x8
+#define bRxHTSettle_RxHP 0x70
+#define bRxHTSettle_BBPPW 0x80
+#define bRxHTSettle_Idle 0x300
+#define bRxHTSettle_Reserved 0x1c00
+#define bRxHTRxHPEn 0x8000
+#define bRxHTAGCFreezeThres 0x30000
+#define bRxHTAGCTogetherEn 0x40000
+#define bRxHTAGCMin 0x80000
+#define bRxHTAGCEn 0x100000
+#define bRxHTDAGCEn 0x200000
+#define bRxHTRxHP_BBP 0x1c00000
+#define bRxHTRxHP_Final 0xe0000000
+#define bRxPWRatioTH 0x3
+#define bRxPWRatioEn 0x4
+#define bRxMFHold 0x3800
+#define bRxPD_Delay_TH1 0x38
+#define bRxPD_Delay_TH2 0x1c0
+#define bRxPD_DC_COUNT_MAX 0x600
+/*#define bRxMF_Hold 0x3800*/
#define bRxPD_Delay_TH 0x8000
#define bRxProcess_Delay 0xf0000
#define bRxSearchrange_GI2_Early 0x700000
@@ -659,7 +692,7 @@
#define bExtLNAGain 0x7c00
-//page d
+/* Page d */
#define bSTBCEn 0x4
#define bAntennaMapping 0x10
#define bNss 0x20
@@ -669,12 +702,12 @@
#define bOFDMContinueTx 0x10000000
#define bOFDMSingleCarrier 0x20000000
#define bOFDMSingleTone 0x40000000
-//#define bRxPath1 0x01
-//#define bRxPath2 0x02
-//#define bRxPath3 0x04
-//#define bRxPath4 0x08
-//#define bTxPath1 0x10
-//#define bTxPath2 0x20
+/*#define bRxPath1 0x01
+#define bRxPath2 0x02
+#define bRxPath3 0x04
+#define bRxPath4 0x08
+#define bTxPath1 0x10
+#define bTxPath2 0x20*/
#define bHTDetect 0x100
#define bCFOEn 0x10000
#define bCFOValue 0xfff00000
@@ -687,8 +720,10 @@
#define bCounter_MCSNoSupport 0xffff
#define bCounter_FastSync 0xffff
#define bShortCFO 0xfff
-#define bShortCFOTLength 12 //total
-#define bShortCFOFLength 11 //fraction
+/* total */
+#define bShortCFOTLength 12
+/* fraction */
+#define bShortCFOFLength 11
#define bLongCFO 0x7ff
#define bLongCFOTLength 11
#define bLongCFOFLength 11
@@ -765,18 +800,18 @@
#define bUChCfg 0x7000000
#define bUpdEqz 0x8000000
-//page e
-#define bTxAGCRate18_06 0x7f7f7f7f
-#define bTxAGCRate54_24 0x7f7f7f7f
+/* Page e */
+#define bTxAGCRate18_06 0x7f7f7f7f
+#define bTxAGCRate54_24 0x7f7f7f7f
#define bTxAGCRateMCS32 0x7f
-#define bTxAGCRateCCK 0x7f00
+#define bTxAGCRateCCK 0x7f00
#define bTxAGCRateMCS3_MCS0 0x7f7f7f7f
#define bTxAGCRateMCS7_MCS4 0x7f7f7f7f
#define bTxAGCRateMCS11_MCS8 0x7f7f7f7f
#define bTxAGCRateMCS15_MCS12 0x7f7f7f7f
-//Rx Pseduo noise
+/* Rx Pseduo noise */
#define bRxPesudoNoiseOn 0x20000000
#define bRxPesudoNoise_A 0xff
#define bRxPesudoNoise_B 0xff00
@@ -787,8 +822,7 @@
#define bPesudoNoiseState_C 0xffff
#define bPesudoNoiseState_D 0xffff0000
-//RF
-//Zebra1
+/* RF Zebra 1 */
#define bZebra1_HSSIEnable 0x8
#define bZebra1_TRxControl 0xc00
#define bZebra1_TRxGainSetting 0x07f
@@ -799,7 +833,7 @@
#define bZebra1_TxLPFBW 0x400
#define bZebra1_RxLPFBW 0x600
-//Zebra4
+/* Zebra4 */
#define bRTL8256RegModeCtrl1 0x100
#define bRTL8256RegModeCtrl0 0x40
#define bRTL8256_TxLPFBW 0x18
@@ -810,7 +844,7 @@
#define bRTL8258_RxLPFBW 0xc00
#define bRTL8258_RSSILPFBW 0xc0
-//byte endable for sb_write
+/* byte endable for sb_write */
#define bByte0 0x1
#define bByte1 0x2
#define bByte2 0x4
@@ -819,7 +853,7 @@
#define bWord1 0xc
#define bDWord 0xf
-//for PutRegsetting & GetRegSetting BitMask
+/* for PutRegsetting & GetRegSetting BitMask */
#define bMaskByte0 0xff
#define bMaskByte1 0xff00
#define bMaskByte2 0xff0000
@@ -828,7 +862,7 @@
#define bMaskLWord 0x0000ffff
#define bMaskDWord 0xffffffff
-//for PutRFRegsetting & GetRFRegSetting BitMask
+/* for PutRFRegsetting & GetRFRegSetting BitMask */
#define bMask12Bits 0xfff
#define bEnable 0x1
@@ -837,14 +871,16 @@
#define LeftAntenna 0x0
#define RightAntenna 0x1
-#define tCheckTxStatus 500 //500ms
-#define tUpdateRxCounter 100 //100ms
+/* 500 ms */
+#define tCheckTxStatus 500
+/* 100 ms */
+#define tUpdateRxCounter 100
#define rateCCK 0
#define rateOFDM 1
#define rateHT 2
-//define Register-End
+/* define Register-End */
#define bPMAC_End 0x1ff
#define bFPGAPHY0_End 0x8ff
#define bFPGAPHY1_End 0x9ff
@@ -852,12 +888,12 @@
#define bOFDMPHY0_End 0xcff
#define bOFDMPHY1_End 0xdff
-//define max debug item in each debug page
-//#define bMaxItem_FPGA_PHY0 0x9
-//#define bMaxItem_FPGA_PHY1 0x3
-//#define bMaxItem_PHY_11B 0x16
-//#define bMaxItem_OFDM_PHY0 0x29
-//#define bMaxItem_OFDM_PHY1 0x0
+/*#define max debug item in each debug page
+#define bMaxItem_FPGA_PHY0 0x9
+#define bMaxItem_FPGA_PHY1 0x3
+#define bMaxItem_PHY_11B 0x16
+#define bMaxItem_OFDM_PHY0 0x29
+#define bMaxItem_OFDM_PHY1 0x0 */
#define bPMACControl 0x0
#define bWMACControl 0x1
@@ -868,11 +904,12 @@
#define PathC 0x2
#define PathD 0x3
-#define rRTL8256RxMixerPole 0xb
-#define bZebraRxMixerPole 0x6
-#define rRTL8256TxBBOPBias 0x9
-#define bRTL8256TxBBOPBias 0x400
-#define rRTL8256TxBBBW 19
-#define bRTL8256TxBBBW 0x18
+#define rRTL8256RxMixerPole 0xb
+#define bZebraRxMixerPole 0x6
+#define rRTL8256TxBBOPBias 0x9
+#define bRTL8256TxBBOPBias 0x400
+#define rRTL8256TxBBBW 19
+#define bRTL8256TxBBBW 0x18
+
-#endif //__INC_HAL8190PCIPHYREG_H
+#endif /* __INC_HAL8190PCIPHYREG_H */
diff --git a/drivers/staging/rtl8192su/Kconfig b/drivers/staging/rtl8192su/Kconfig
index 123fa6d6a93..b72a96206f5 100644
--- a/drivers/staging/rtl8192su/Kconfig
+++ b/drivers/staging/rtl8192su/Kconfig
@@ -1,6 +1,7 @@
config RTL8192SU
tristate "RealTek RTL8192SU Wireless LAN NIC driver"
depends on PCI && WLAN && USB
- depends on WIRELESS_EXT
+ select WIRELESS_EXT
+ select WEXT_PRIV
default N
---help---
diff --git a/drivers/staging/rtl8192su/TODO b/drivers/staging/rtl8192su/TODO
index f11eec70003..3c8da157a93 100644
--- a/drivers/staging/rtl8192su/TODO
+++ b/drivers/staging/rtl8192su/TODO
@@ -4,7 +4,6 @@ TODO:
- cleanup ieee80211.h
- move rtl8192su's specific code out from ieee80211.h
- abstract rtl819su's specific code
- - use list_for_each_safe() in ieee80211_crypto_deinit
- switch to use shared "librtl" instead of private ieee80211 stack
- switch to use LIB80211
- switch to use MAC80211
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211.h b/drivers/staging/rtl8192su/ieee80211/ieee80211.h
index 2b8c85556dc..32b261d1559 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211.h
@@ -30,6 +30,7 @@
#include <linux/jiffies.h>
#include <linux/timer.h>
#include <linux/sched.h>
+#include <linux/semaphore.h>
#include <linux/delay.h>
#include <linux/wireless.h>
@@ -195,10 +196,6 @@ extern u32 ieee80211_debug_level;
#define IEEE80211_DEBUG_DATA(level, data, datalen) do {} while(0)
#endif /* CONFIG_IEEE80211_DEBUG */
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAC_ARG(x) ((u8 *)(x))[0], ((u8 *)(x))[1], ((u8 *)(x))[2], \
- ((u8 *)(x))[3], ((u8 *)(x))[4], ((u8 *)(x))[5]
-
/*
* To use the debug system;
*
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt.c
index 521e7b98993..c4640e63196 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt.c
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt.c
@@ -226,19 +226,20 @@ out:
void __exit ieee80211_crypto_deinit(void)
{
struct list_head *ptr, *n;
+ struct ieee80211_crypto_alg *alg = NULL;
if (hcrypt == NULL)
return;
- for (ptr = hcrypt->algs.next, n = ptr->next; ptr != &hcrypt->algs;
- ptr = n, n = ptr->next) {
- struct ieee80211_crypto_alg *alg =
- (struct ieee80211_crypto_alg *) ptr;
- list_del(ptr);
- printk(KERN_DEBUG "ieee80211_crypt: unregistered algorithm "
- "'%s' (deinit)\n", alg->ops->name);
- kfree(alg);
+ list_for_each_safe(ptr, n, &hcrypt->algs) {
+ alg = list_entry(ptr, struct ieee80211_crypto_alg, list);
+ if (alg) {
+ list_del(ptr);
+ printk(KERN_DEBUG
+ "ieee80211_crypt: unregistered algorithm '%s' (deinit)\n",
+ alg->ops->name);
+ kfree(alg);
+ }
}
-
kfree(hcrypt);
}
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt_ccmp.c
index 7bc956e1f45..8a93f7d3eb3 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt_ccmp.c
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt_ccmp.c
@@ -288,7 +288,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (!(keyidx & (1 << 5))) {
if (net_ratelimit()) {
printk(KERN_DEBUG "CCMP: received packet without ExtIV"
- " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
+ " flag from %pM\n", hdr->addr2);
}
key->dot11RSNAStatsCCMPFormatErrors++;
return -2;
@@ -301,9 +301,9 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
}
if (!key->key_set) {
if (net_ratelimit()) {
- printk(KERN_DEBUG "CCMP: received packet from " MAC_FMT
+ printk(KERN_DEBUG "CCMP: received packet from %pM"
" with keyid=%d that does not have a configured"
- " key\n", MAC_ARG(hdr->addr2), keyidx);
+ " key\n", hdr->addr2, keyidx);
}
return -3;
}
@@ -318,11 +318,9 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
if (net_ratelimit()) {
- printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT
- " previous PN %02x%02x%02x%02x%02x%02x "
- "received PN %02x%02x%02x%02x%02x%02x\n",
- MAC_ARG(hdr->addr2), MAC_ARG(key->rx_pn),
- MAC_ARG(pn));
+ printk(KERN_DEBUG "CCMP: replay detected: STA=%pM"
+ " previous PN %pm received PN %pm\n",
+ hdr->addr2, key->rx_pn, pn);
}
key->dot11RSNAStatsCCMPReplays++;
return -4;
@@ -359,7 +357,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
if (net_ratelimit()) {
printk(KERN_DEBUG "CCMP: decrypt failed: STA="
- MAC_FMT "\n", MAC_ARG(hdr->addr2));
+ "%pM\n", hdr->addr2);
}
key->dot11RSNAStatsCCMPDecryptErrors++;
return -5;
@@ -435,11 +433,10 @@ static char * ieee80211_ccmp_print_stats(char *p, void *priv)
{
struct ieee80211_ccmp_data *ccmp = priv;
p += sprintf(p, "key[%d] alg=CCMP key_set=%d "
- "tx_pn=%02x%02x%02x%02x%02x%02x "
- "rx_pn=%02x%02x%02x%02x%02x%02x "
+ "tx_pn=%pm rx_pn=%pm "
"format_errors=%d replays=%d decrypt_errors=%d\n",
ccmp->key_idx, ccmp->key_set,
- MAC_ARG(ccmp->tx_pn), MAC_ARG(ccmp->rx_pn),
+ ccmp->tx_pn, ccmp->rx_pn,
ccmp->dot11RSNAStatsCCMPFormatErrors,
ccmp->dot11RSNAStatsCCMPReplays,
ccmp->dot11RSNAStatsCCMPDecryptErrors);
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt_tkip.c
index 9b9438fb5f6..7e48748da10 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt_tkip.c
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt_tkip.c
@@ -410,7 +410,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (!(keyidx & (1 << 5))) {
if (net_ratelimit()) {
printk(KERN_DEBUG "TKIP: received packet without ExtIV"
- " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
+ " flag from %pM\n", hdr->addr2);
}
return -2;
}
@@ -422,9 +422,9 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
}
if (!tkey->key_set) {
if (net_ratelimit()) {
- printk(KERN_DEBUG "TKIP: received packet from " MAC_FMT
+ printk(KERN_DEBUG "TKIP: received packet from %pM"
" with keyid=%d that does not have a configured"
- " key\n", MAC_ARG(hdr->addr2), keyidx);
+ " key\n", hdr->addr2, keyidx);
}
return -3;
}
@@ -437,9 +437,9 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (iv32 < tkey->rx_iv32 ||
(iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
if (net_ratelimit()) {
- printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT
+ printk(KERN_DEBUG "TKIP: replay detected: STA=%pM"
" previous TSC %08x%04x received TSC "
- "%08x%04x\n", MAC_ARG(hdr->addr2),
+ "%08x%04x\n", hdr->addr2,
tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
}
tkey->dot11RSNAStatsTKIPReplays++;
@@ -460,8 +460,8 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
if (net_ratelimit()) {
printk(KERN_DEBUG ": TKIP: failed to decrypt "
- "received packet from " MAC_FMT "\n",
- MAC_ARG(hdr->addr2));
+ "received packet from %pM\n",
+ hdr->addr2);
}
return -7;
}
@@ -480,7 +480,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
}
if (net_ratelimit()) {
printk(KERN_DEBUG "TKIP: ICV error detected: STA="
- MAC_FMT "\n", MAC_ARG(hdr->addr2));
+ "%pM\n", hdr->addr2);
}
tkey->dot11RSNAStatsTKIPICVErrors++;
return -5;
@@ -635,8 +635,8 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
struct ieee80211_hdr_4addr *hdr;
hdr = (struct ieee80211_hdr_4addr *) skb->data;
printk(KERN_DEBUG "%s: Michael MIC verification failed for "
- "MSDU from " MAC_FMT " keyidx=%d\n",
- skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2),
+ "MSDU from %pM keyidx=%d\n",
+ skb->dev ? skb->dev->name : "N/A", hdr->addr2,
keyidx);
if (skb->dev)
ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c
index e8c67d5dfb7..c024fa60072 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c
@@ -262,7 +262,7 @@ static int store_debug_level(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char buf[] = "0x00000000";
- unsigned long len = min(sizeof(buf) - 1, count);
+ unsigned long len = min_t(unsigned long, sizeof(buf) - 1, count);
char *p = (char *)buf;
unsigned long val;
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c
index 095b8c64314..cc80faf6598 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c
@@ -314,8 +314,8 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
strcmp(crypt->ops->name, "TKIP") == 0) {
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
- "received packet from " MAC_FMT "\n",
- ieee->dev->name, MAC_ARG(hdr->addr2));
+ "received packet from %pM\n",
+ ieee->dev->name, hdr->addr2);
}
return -1;
}
@@ -326,8 +326,8 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
atomic_dec(&crypt->refcnt);
if (res < 0) {
IEEE80211_DEBUG_DROP(
- "decryption failed (SA=" MAC_FMT
- ") res=%d\n", MAC_ARG(hdr->addr2), res);
+ "decryption failed (SA=%pM"
+ ") res=%d\n", hdr->addr2, res);
if (res == -2)
IEEE80211_DEBUG_DROP("Decryption failed ICV "
"mismatch (key %d)\n",
@@ -364,8 +364,8 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device* ieee, struct sk_buff *s
atomic_dec(&crypt->refcnt);
if (res < 0) {
printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
- " (SA=" MAC_FMT " keyidx=%d)\n",
- ieee->dev->name, MAC_ARG(hdr->addr2), keyidx);
+ " (SA=%pM keyidx=%d)\n",
+ ieee->dev->name, hdr->addr2, keyidx);
return -1;
}
@@ -939,8 +939,8 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
* frames silently instead of filling system log with
* these reports. */
IEEE80211_DEBUG_DROP("Decryption failed (not set)"
- " (SA=" MAC_FMT ")\n",
- MAC_ARG(hdr->addr2));
+ " (SA=%pM)\n",
+ hdr->addr2);
ieee->ieee_stats.rx_discards_undecryptable++;
goto rx_dropped;
}
@@ -1143,8 +1143,8 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
} else {
IEEE80211_DEBUG_DROP(
"encryption configured, but RX "
- "frame not encrypted (SA=" MAC_FMT ")\n",
- MAC_ARG(hdr->addr2));
+ "frame not encrypted (SA=%pM)\n",
+ hdr->addr2);
goto rx_dropped;
}
}
@@ -1163,9 +1163,9 @@ int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
!ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
IEEE80211_DEBUG_DROP(
"dropped unencrypted RX data "
- "frame from " MAC_FMT
+ "frame from %pM"
" (drop_unencrypted=1)\n",
- MAC_ARG(hdr->addr2));
+ hdr->addr2);
goto rx_dropped;
}
/*
@@ -2159,11 +2159,11 @@ static inline int ieee80211_network_init(
}
if (network->mode == 0) {
- IEEE80211_DEBUG_SCAN("Filtered out '%s (" MAC_FMT ")' "
+ IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' "
"network.\n",
escape_essid(network->ssid,
network->ssid_len),
- MAC_ARG(network->bssid));
+ network->bssid);
return 1;
}
@@ -2345,9 +2345,9 @@ static inline void ieee80211_process_probe_response(
memset(&network, 0, sizeof(struct ieee80211_network));
IEEE80211_DEBUG_SCAN(
- "'%s' (" MAC_FMT "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
+ "'%s' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
escape_essid(info_element->data, info_element->len),
- MAC_ARG(beacon->header.addr3),
+ beacon->header.addr3,
(beacon->capability & (1<<0xf)) ? '1' : '0',
(beacon->capability & (1<<0xe)) ? '1' : '0',
(beacon->capability & (1<<0xd)) ? '1' : '0',
@@ -2366,10 +2366,10 @@ static inline void ieee80211_process_probe_response(
(beacon->capability & (1<<0x0)) ? '1' : '0');
if (ieee80211_network_init(ieee, beacon, &network, stats)) {
- IEEE80211_DEBUG_SCAN("Dropped '%s' (" MAC_FMT ") via %s.\n",
+ IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
escape_essid(info_element->data,
info_element->len),
- MAC_ARG(beacon->header.addr3),
+ beacon->header.addr3,
WLAN_FC_GET_STYPE(beacon->header.frame_control) ==
IEEE80211_STYPE_PROBE_RESP ?
"PROBE RESPONSE" : "BEACON");
@@ -2478,11 +2478,11 @@ static inline void ieee80211_process_probe_response(
/* If there are no more slots, expire the oldest */
list_del(&oldest->list);
target = oldest;
- IEEE80211_DEBUG_SCAN("Expired '%s' (" MAC_FMT ") from "
+ IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from "
"network list.\n",
escape_essid(target->ssid,
target->ssid_len),
- MAC_ARG(target->bssid));
+ target->bssid);
} else {
/* Otherwise just pull from the free list */
target = list_entry(ieee->network_free_list.next,
@@ -2492,10 +2492,10 @@ static inline void ieee80211_process_probe_response(
#ifdef CONFIG_IEEE80211_DEBUG
- IEEE80211_DEBUG_SCAN("Adding '%s' (" MAC_FMT ") via %s.\n",
+ IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
escape_essid(network.ssid,
network.ssid_len),
- MAC_ARG(network.bssid),
+ network.bssid,
WLAN_FC_GET_STYPE(beacon->header.frame_control) ==
IEEE80211_STYPE_PROBE_RESP ?
"PROBE RESPONSE" : "BEACON");
@@ -2505,10 +2505,10 @@ static inline void ieee80211_process_probe_response(
if(ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)
ieee80211_softmac_new_net(ieee,&network);
} else {
- IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n",
+ IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
escape_essid(target->ssid,
target->ssid_len),
- MAC_ARG(target->bssid),
+ target->bssid,
WLAN_FC_GET_STYPE(beacon->header.frame_control) ==
IEEE80211_STYPE_PROBE_RESP ?
"PROBE RESPONSE" : "BEACON");
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c
index 0ba2a01a06a..9d8cb0e575d 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c
@@ -1709,7 +1709,7 @@ ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
ieee80211_resp_to_assoc_rq(ieee, dest);
}
- printk(KERN_INFO"New client associated: "MAC_FMT"\n", MAC_ARG(dest));
+ printk(KERN_INFO"New client associated: %pM\n", dest);
//FIXME
}
@@ -2145,8 +2145,8 @@ void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *
ieee80211_sta_wakeup(ieee,0);
/* update the tx status */
-// ieee->stats.tx_bytes += txb->payload_size;
-// ieee->stats.tx_packets++;
+ ieee->stats.tx_bytes += txb->payload_size;
+ ieee->stats.tx_packets++;
tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
if(tcb_desc->bMulticast) {
ieee->stats.multicast++;
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c
index 4d54e1e62d2..484c3aba5cb 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c
@@ -199,8 +199,8 @@ int ieee80211_encrypt_fragment(
header = (struct rtl_ieee80211_hdr *)frag->data;
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
- "TX packet to " MAC_FMT "\n",
- ieee->dev->name, MAC_ARG(header->addr1));
+ "TX packet to %pM\n",
+ ieee->dev->name, header->addr1);
}
return -1;
}
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c
index 85c7e96b622..122f8004904 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c
@@ -261,10 +261,10 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
else
IEEE80211_DEBUG_SCAN(
"Not showing network '%s ("
- MAC_FMT ")' due to age (%lums).\n",
+ "%pM)' due to age (%lums).\n",
escape_essid(network->ssid,
network->ssid_len),
- MAC_ARG(network->bssid),
+ network->bssid,
(jiffies - network->last_scanned) / (HZ / 100));
}
@@ -731,7 +731,7 @@ int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
#if 1
case IW_AUTH_WPA_ENABLED:
ieee->wpa_enabled = (data->value)?1:0;
- //printk("enalbe wpa:%d\n", ieee->wpa_enabled);
+ //printk("enable wpa:%d\n", ieee->wpa_enabled);
break;
#endif
diff --git a/drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c
index c6962450e06..8c37dd124fc 100644
--- a/drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c
+++ b/drivers/staging/rtl8192su/ieee80211/rtl819x_BAProc.c
@@ -113,7 +113,7 @@ static struct sk_buff* ieee80211_ADDBA(struct ieee80211_device* ieee, u8* Dst, P
u16 tmp = 0;
u16 len = ieee->tx_headroom + 9;
//category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) + BA Timeout Value(2) + BA Start SeqCtrl(2)(or StatusCode(2))
- IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:"MAC_FMT", ieee->dev:%p\n", __FUNCTION__, type, MAC_ARG(Dst), ieee->dev);
+ IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __FUNCTION__, type, Dst, ieee->dev);
if (pBA == NULL||ieee == NULL)
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee);
@@ -200,7 +200,7 @@ static struct sk_buff* ieee80211_DELBA(
u16 len = 6 + ieee->tx_headroom;
if (net_ratelimit())
- IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:"MAC_FMT"\n", __FUNCTION__, ReasonCode, MAC_ARG(dst));
+ IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:%pM\n", __FUNCTION__, ReasonCode, dst);
memset(&DelbaParamSet, 0, 2);
@@ -339,7 +339,10 @@ int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb)
if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
{
- IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %ld)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9));
+ IEEE80211_DEBUG(IEEE80211_DL_ERR,
+ " Invalid skb len in BAREQ(%d / %zd)\n",
+ skb->len,
+ sizeof(struct ieee80211_hdr_3addr) + 9);
return -1;
}
@@ -354,7 +357,7 @@ int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb)
pBaTimeoutVal = (u16*)(tag + 5);
pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7);
- printk("====================>rx ADDBAREQ from :"MAC_FMT"\n", MAC_ARG(dst));
+ printk("====================>rx ADDBAREQ from :%pM\n", dst);
//some other capability is not ready now.
if( (ieee->current_network.qos_data.active == 0) ||
(ieee->pHTInfo->bCurrentHTSupport == false) ||
@@ -440,7 +443,10 @@ int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb)
if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
{
- IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %ld)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9));
+ IEEE80211_DEBUG(IEEE80211_DL_ERR,
+ " Invalid skb len in BARSP(%d / %zd)\n",
+ skb->len,
+ sizeof(struct ieee80211_hdr_3addr) + 9);
return -1;
}
rsp = ( struct ieee80211_hdr_3addr*)skb->data;
@@ -570,7 +576,10 @@ int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb)
if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 6)
{
- IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %ld)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 6));
+ IEEE80211_DEBUG(IEEE80211_DL_ERR,
+ " Invalid skb len in DELBA(%d / %zd)\n",
+ skb->len,
+ sizeof(struct ieee80211_hdr_3addr) + 6);
return -1;
}
diff --git a/drivers/staging/rtl8192su/ieee80211/rtl819x_HTProc.c b/drivers/staging/rtl8192su/ieee80211/rtl819x_HTProc.c
index 33c7fa7edc8..01114c5181b 100644
--- a/drivers/staging/rtl8192su/ieee80211/rtl819x_HTProc.c
+++ b/drivers/staging/rtl8192su/ieee80211/rtl819x_HTProc.c
@@ -42,7 +42,7 @@ static u8 DLINK_ATHEROS_1[3] = {0x00, 0x1c, 0xf0};
static u8 DLINK_ATHEROS_2[3] = {0x00, 0x21, 0x91};
static u8 CISCO_BROADCOM[3] = {0x00, 0x17, 0x94};
static u8 LINKSYS_MARVELL_4400N[3] = {0x00, 0x14, 0xa4};
-// 2008/04/01 MH For Cisco G mode RX TP We need to change FW duration. Shoud we put the
+// 2008/04/01 MH For Cisco G mode RX TP We need to change FW duration. Should we put the
// code in other place??
//static u8 WIFI_CISCO_G_AP[3] = {0x00, 0x40, 0x96};
/********************************************************************************************************************
diff --git a/drivers/staging/rtl8192su/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192su/ieee80211/rtl819x_TSProc.c
index ad3bf35d80e..60cf1f8781c 100644
--- a/drivers/staging/rtl8192su/ieee80211/rtl819x_TSProc.c
+++ b/drivers/staging/rtl8192su/ieee80211/rtl819x_TSProc.c
@@ -291,7 +291,7 @@ PTS_COMMON_INFO SearchAdmitTRStream(struct ieee80211_device *ieee, u8* Addr, u8
if(search_dir[dir] ==false )
continue;
list_for_each_entry(pRet, psearch_list, List){
- // IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:"MAC_FMT", TID:%d, dir:%d\n", MAC_ARG(pRet->Addr), pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection);
+ // IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:%pM, TID:%d, dir:%d\n", pRet->Addr, pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection);
if (memcmp(pRet->Addr, Addr, 6) == 0)
if (pRet->TSpec.f.TSInfo.field.ucTSID == TID)
if(pRet->TSpec.f.TSInfo.field.ucDirection == dir)
@@ -447,7 +447,7 @@ bool GetTs(
ResetRxTsEntry(tmp);
}
- IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:"MAC_FMT"\n", UP, Dir, MAC_ARG(Addr));
+ IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:%pM\n", UP, Dir, Addr);
// Prepare TS Info releated field
pTSInfo->field.ucTrafficType = 0; // Traffic type: WMM is reserved in this field
pTSInfo->field.ucTSID = UP; // TSID
@@ -533,7 +533,7 @@ void RemoveTsEntry(
void RemovePeerTS(struct ieee80211_device* ieee, u8* Addr)
{
PTS_COMMON_INFO pTS, pTmpTS;
- printk("===========>RemovePeerTS,"MAC_FMT"\n", MAC_ARG(Addr));
+ printk("===========>RemovePeerTS,%pM\n", Addr);
#if 1
list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List)
{
diff --git a/drivers/staging/rtl8192su/r8192SU_HWImg.c b/drivers/staging/rtl8192su/r8192SU_HWImg.c
index cbb65795a30..ba8e12c209c 100644
--- a/drivers/staging/rtl8192su/r8192SU_HWImg.c
+++ b/drivers/staging/rtl8192su/r8192SU_HWImg.c
@@ -2,4282 +2,6 @@
#include "r8192SU_HWImg.h"
-u8 Rtl8192SUFwImgArray[ImgArrayLength] = {
-0x92,0x81,0x2b,0x90,0x30,0x00,0x00,0x00,0x08,0x74,0x00,0x00,0x88,0x96,0x00,0x00,
-0x30,0x00,0x00,0x00,0x00,0x95,0x00,0x00,0x00,0x00,0x2b,0x00,0x03,0x03,0x23,0x00,
-0x92,0x81,0x02,0x01,0x00,0x00,0x12,0x04,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x01,0x01,0x01,0x00,0x00,
-0x00,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x7f,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x1f,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x25,0xb0,0x1a,0x3c,0x80,0x03,0x5a,0x37,0x00,0x80,0x1b,0x3c,0x80,0x00,0x7b,0x37,
-0x00,0x00,0x5b,0xaf,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x37,0x00,0x80,0x1b,0x3c,
-0x80,0x00,0x7b,0x37,0x00,0x00,0x5b,0xaf,0x00,0x80,0x1a,0x3c,0x10,0x6d,0x5a,0x27,
-0x08,0x00,0x40,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x04,0x00,0xa1,0xaf,0x08,0x00,0xa2,0xaf,0x0c,0x00,0xa3,0xaf,0x10,0x00,0xa4,0xaf,
-0x14,0x00,0xa5,0xaf,0x18,0x00,0xa6,0xaf,0x1c,0x00,0xa7,0xaf,0x20,0x00,0xa8,0xaf,
-0x24,0x00,0xa9,0xaf,0x28,0x00,0xaa,0xaf,0x2c,0x00,0xab,0xaf,0x30,0x00,0xac,0xaf,
-0x34,0x00,0xad,0xaf,0x38,0x00,0xae,0xaf,0x3c,0x00,0xaf,0xaf,0x12,0x40,0x00,0x00,
-0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40,0x40,0x00,0xb0,0xaf,0x44,0x00,0xb1,0xaf,
-0x48,0x00,0xb2,0xaf,0x4c,0x00,0xb3,0xaf,0x50,0x00,0xb4,0xaf,0x54,0x00,0xb5,0xaf,
-0x58,0x00,0xb6,0xaf,0x5c,0x00,0xb7,0xaf,0x60,0x00,0xb8,0xaf,0x64,0x00,0xb9,0xaf,
-0x68,0x00,0xbc,0xaf,0x6c,0x00,0xbd,0xaf,0x70,0x00,0xbe,0xaf,0x74,0x00,0xbf,0xaf,
-0x78,0x00,0xa8,0xaf,0x7c,0x00,0xa9,0xaf,0x80,0x00,0xaa,0xaf,0xdf,0x1a,0x00,0x08,
-0x21,0x20,0xa0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x25,0xb0,0x06,0x3c,0x00,0x80,0x02,0x3c,0xe8,0xff,0xbd,0x27,0x18,0x03,0xc3,0x34,
-0x00,0x03,0x42,0x24,0x14,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x42,0xb0,0x03,0x3c,
-0x03,0x00,0x63,0x34,0x00,0x00,0x62,0x90,0x02,0x80,0x0a,0x3c,0x02,0x80,0x10,0x3c,
-0xff,0x00,0x42,0x30,0x00,0x46,0x02,0x00,0x10,0x00,0x42,0x30,0x13,0x00,0x40,0x10,
-0x03,0x46,0x08,0x00,0xc4,0x7d,0x42,0x8d,0x68,0x15,0x05,0x26,0xd4,0x63,0xa4,0x94,
-0x01,0x00,0x47,0x24,0x10,0x00,0x02,0x24,0xb0,0x03,0xc9,0x34,0x00,0x00,0x62,0xa0,
-0x07,0x00,0x80,0x10,0x1c,0x03,0xc6,0x34,0xd8,0x63,0xa2,0x8c,0xd4,0x63,0xa0,0xa4,
-0xd8,0x63,0xa0,0xac,0x00,0x00,0x04,0x24,0x00,0x00,0xc2,0xac,0x00,0x00,0x20,0xad,
-0x01,0x00,0x82,0x24,0xc4,0x7d,0x47,0xad,0xd4,0x63,0xa2,0xa4,0x12,0x00,0x00,0x05,
-0x42,0xb0,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
-0x00,0x60,0x81,0x40,0x68,0x15,0x04,0x26,0x0c,0x4b,0x83,0x94,0x08,0x4b,0x85,0x94,
-0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x80,0x00,0x63,0x30,0x41,0xb0,0x02,0x3c,
-0x25,0x18,0x65,0x00,0x08,0x00,0x42,0x34,0x18,0x00,0xbd,0x27,0x00,0x00,0x43,0xa4,
-0x08,0x00,0xe0,0x03,0x08,0x4b,0x83,0xa4,0x80,0xff,0x03,0x24,0x03,0x00,0x42,0x34,
-0x00,0x00,0x43,0xa0,0xc8,0x0e,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x68,0x15,0x04,0x26,
-0x0c,0x4b,0x83,0x94,0x08,0x4b,0x85,0x94,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,
-0x80,0x00,0x63,0x30,0x41,0xb0,0x02,0x3c,0x25,0x18,0x65,0x00,0x08,0x00,0x42,0x34,
-0x18,0x00,0xbd,0x27,0x00,0x00,0x43,0xa4,0x08,0x00,0xe0,0x03,0x08,0x4b,0x83,0xa4,
-0xff,0x00,0x84,0x30,0x0b,0x00,0x82,0x2c,0xff,0xff,0xe7,0x30,0x10,0x00,0xa8,0x93,
-0x19,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0x02,0x80,0x03,0x3c,0x80,0x10,0x04,0x00,
-0xc0,0x91,0x63,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,
-0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x43,0xb0,0x02,0x3c,0x78,0x00,0x44,0x34,
-0x07,0x00,0xe2,0x30,0x00,0x00,0x85,0xac,0x04,0x00,0x86,0xac,0x04,0x00,0x40,0x18,
-0x00,0x00,0x00,0x00,0xf8,0xff,0xe2,0x30,0x08,0x00,0x42,0x24,0xff,0xff,0x47,0x30,
-0x21,0x10,0xe8,0x00,0x00,0x80,0x03,0x3c,0x08,0x00,0x82,0xac,0x25,0x10,0x43,0x00,
-0x08,0x00,0x82,0xac,0x01,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
-0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x6c,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,
-0x20,0x01,0x00,0x08,0x60,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,
-0x54,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x48,0x00,0x44,0x34,
-0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x3c,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,
-0x20,0x01,0x00,0x08,0x30,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,
-0x24,0x00,0x44,0x34,0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x18,0x00,0x44,0x34,
-0x43,0xb0,0x02,0x3c,0x20,0x01,0x00,0x08,0x0c,0x00,0x44,0x34,0x20,0x01,0x00,0x08,
-0x43,0xb0,0x04,0x3c,0x01,0x00,0x02,0x24,0x25,0xb0,0x03,0x3c,0x04,0x20,0x82,0x00,
-0x18,0x03,0x67,0x34,0x00,0x80,0x02,0x3c,0x43,0xb0,0x03,0x3c,0x34,0x05,0x46,0x24,
-0x88,0x00,0x65,0x34,0x21,0x10,0x00,0x00,0x01,0x00,0x42,0x24,0xff,0xff,0x42,0x30,
-0x05,0x00,0x43,0x2c,0xfd,0xff,0x60,0x14,0x01,0x00,0x42,0x24,0x00,0x00,0xe6,0xac,
-0x00,0x00,0xa2,0x94,0x00,0x00,0x00,0x00,0xff,0xff,0x42,0x30,0x24,0x10,0x44,0x00,
-0xf4,0xff,0x40,0x1c,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x25,0xb0,0x08,0x3c,0x00,0x80,0x02,0x3c,0xc8,0xff,0xbd,0x27,0x18,0x03,0x03,0x35,
-0x90,0x05,0x42,0x24,0x00,0x00,0x62,0xac,0x30,0x00,0xb6,0xaf,0x28,0x00,0xb4,0xaf,
-0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf,0x34,0x00,0xbf,0xaf,0x2c,0x00,0xb5,0xaf,
-0x20,0x00,0xb2,0xaf,0x18,0x00,0xb0,0xaf,0x0c,0x00,0xf2,0x84,0x08,0x00,0xf5,0x8c,
-0xff,0x00,0xc6,0x30,0x00,0x01,0x02,0x24,0x23,0x10,0x46,0x00,0xff,0xff,0x51,0x30,
-0xd0,0x03,0x08,0x35,0xff,0x00,0x96,0x30,0x00,0x00,0x12,0xad,0x21,0xa0,0xa0,0x00,
-0x21,0x30,0xc5,0x00,0x00,0x00,0x15,0xad,0x21,0x20,0xc0,0x02,0x21,0x28,0xa0,0x02,
-0x21,0x38,0x20,0x02,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x23,0x18,0x51,0x02,
-0xff,0xff,0x82,0x32,0x00,0x94,0x03,0x00,0x03,0x94,0x12,0x00,0xa6,0x01,0x00,0x08,
-0x02,0x9a,0x02,0x00,0x28,0xb0,0x03,0x3c,0xc0,0x10,0x13,0x00,0x21,0x10,0x43,0x00,
-0x00,0x00,0x44,0x90,0x25,0xb0,0x10,0x3c,0x20,0x10,0x02,0x3c,0xff,0x00,0x93,0x30,
-0x00,0x22,0x13,0x00,0xff,0xff,0x43,0x32,0x01,0x01,0x45,0x2a,0x21,0xa0,0x82,0x00,
-0x21,0xa8,0xb1,0x02,0xd0,0x03,0x02,0x36,0x00,0x01,0x11,0x24,0x0b,0x88,0x65,0x00,
-0x21,0x20,0xc0,0x02,0x00,0x00,0x53,0xac,0x4d,0x01,0x00,0x0c,0xb0,0x03,0x10,0x36,
-0x21,0x30,0x80,0x02,0x21,0x20,0xc0,0x02,0x21,0x28,0xa0,0x02,0x21,0x38,0x20,0x02,
-0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x23,0x18,0x51,0x02,0x00,0x94,0x03,0x00,
-0x03,0x94,0x12,0x00,0x00,0x00,0x12,0xae,0xe2,0xff,0x40,0x1e,0x00,0x00,0x00,0x00,
-0x34,0x00,0xbf,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
-0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
-0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0xc8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,
-0x25,0xb0,0x04,0x3c,0x20,0x00,0xb2,0xaf,0x68,0x15,0x52,0x24,0x00,0x80,0x02,0x3c,
-0x18,0x03,0x83,0x34,0xc8,0x06,0x42,0x24,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,
-0x30,0x00,0xbf,0xaf,0x2c,0x00,0xb5,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
-0x00,0x00,0x62,0xac,0xb0,0x03,0x93,0x34,0x21,0xa0,0x40,0x02,0x54,0x64,0x42,0x8e,
-0xc0,0x64,0x50,0x8e,0x21,0x20,0x00,0x00,0x00,0x00,0x62,0xae,0x58,0x64,0x42,0xae,
-0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0xc0,0x64,0x44,0x8e,
-0xc4,0x64,0x43,0x8e,0x20,0x00,0x84,0x24,0x3f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,
-0x0a,0x18,0x82,0x00,0xc0,0x64,0x43,0xae,0xc0,0x64,0x85,0x8e,0x00,0x00,0x00,0x00,
-0x00,0x00,0x65,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,
-0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0xff,0x00,0x15,0x24,0x21,0x20,0x00,0x00,
-0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0x20,0x10,0x02,0x3c,0x20,0x00,0x07,0x24,
-0x00,0x1a,0x11,0x00,0x21,0x18,0x62,0x00,0x05,0x00,0x35,0x12,0x21,0x30,0x60,0x00,
-0x08,0x64,0x91,0xa2,0x54,0x64,0x83,0xae,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
-0x04,0x00,0x04,0x8e,0x08,0x00,0x03,0x8e,0xff,0xe0,0x02,0x3c,0xff,0xff,0x42,0x34,
-0x1f,0x00,0x84,0x30,0x24,0x18,0x62,0x00,0x00,0x26,0x04,0x00,0xff,0xdf,0x02,0x3c,
-0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x00,0x40,0x04,0x3c,
-0x25,0x18,0x64,0x00,0xc0,0xff,0x02,0x24,0x24,0x18,0x62,0x00,0x08,0x00,0x03,0xae,
-0xc9,0x64,0x84,0x92,0x2a,0xb0,0x02,0x3c,0x01,0x00,0x03,0x24,0x01,0x00,0x84,0x24,
-0x01,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0xc4,0xff,0x35,0x16,0xc9,0x64,0x84,0xa2,
-0xfc,0x4a,0x82,0x8e,0x41,0xb0,0x03,0x3c,0x30,0x00,0xbf,0x8f,0x00,0x38,0x42,0x34,
-0x00,0x00,0x62,0xac,0x2c,0x00,0xb5,0x8f,0xfc,0x4a,0x82,0xae,0x24,0x00,0xb3,0x8f,
-0x28,0x00,0xb4,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
-0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x25,0xb0,0x04,0x3c,0x00,0x80,0x02,0x3c,
-0xc8,0xff,0xbd,0x27,0x18,0x03,0x83,0x34,0x38,0x08,0x42,0x24,0x34,0x00,0xbf,0xaf,
-0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,
-0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x00,0x00,0x62,0xac,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x02,0x80,0x16,0x3c,
-0x68,0x15,0xd2,0x26,0xb0,0x03,0x93,0x34,0x2d,0x02,0x00,0x08,0x21,0xa8,0x40,0x02,
-0x2a,0xb0,0x02,0x3c,0x08,0x00,0x04,0xae,0x09,0x00,0x42,0x34,0x01,0x00,0x03,0x24,
-0x02,0x00,0x04,0x24,0x00,0x00,0x43,0xa0,0x00,0x00,0x44,0xa0,0x42,0x00,0x34,0x12,
-0x00,0x00,0x00,0x00,0x6c,0x64,0x42,0x8e,0xd8,0x64,0x50,0x8e,0x01,0x00,0x04,0x24,
-0x00,0x00,0x62,0xae,0x70,0x64,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,
-0x00,0x00,0x00,0x00,0xd8,0x64,0x44,0x8e,0xdc,0x64,0x43,0x8e,0x20,0x00,0x84,0x24,
-0x3f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0xd8,0x64,0x43,0xae,
-0xd8,0x64,0xa5,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0xae,0x02,0x80,0x02,0x3c,
-0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,
-0xff,0x00,0x14,0x24,0x01,0x00,0x04,0x24,0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,
-0x20,0x10,0x02,0x3c,0x20,0x00,0x07,0x24,0x00,0x1a,0x11,0x00,0x21,0x18,0x62,0x00,
-0x05,0x00,0x34,0x12,0x21,0x30,0x60,0x00,0x6c,0x64,0xa3,0xae,0x10,0x64,0xb1,0xa2,
-0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x04,0x00,0x04,0x8e,0x08,0x00,0x03,0x8e,
-0xff,0xe0,0x02,0x3c,0xff,0xff,0x42,0x34,0x1f,0x00,0x84,0x30,0x24,0x18,0x62,0x00,
-0x00,0x26,0x04,0x00,0xff,0xdf,0x02,0x3c,0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,
-0x24,0x18,0x62,0x00,0x00,0x40,0x04,0x3c,0x25,0x18,0x64,0x00,0xc0,0xff,0x05,0x24,
-0x82,0x11,0x03,0x00,0x24,0x20,0x65,0x00,0x01,0x00,0x42,0x30,0xc0,0xff,0x40,0x10,
-0x04,0x00,0x84,0x34,0x2a,0xb0,0x02,0x3c,0x08,0x00,0x03,0xae,0x09,0x00,0x42,0x34,
-0x01,0x00,0x03,0x24,0x02,0x00,0x04,0x24,0x00,0x00,0x43,0xa0,0x00,0x00,0x44,0xa0,
-0xc0,0xff,0x34,0x16,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x68,0x15,0xc2,0x26,0xfc,0x4a,0x43,0x8c,
-0x34,0x00,0xbf,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
-0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
-0x00,0x38,0x63,0x34,0x41,0xb0,0x04,0x3c,0x38,0x00,0xbd,0x27,0x00,0x00,0x83,0xac,
-0x08,0x00,0xe0,0x03,0xfc,0x4a,0x43,0xac,0x25,0xb0,0x04,0x3c,0x00,0x80,0x02,0x3c,
-0xc0,0xff,0xbd,0x27,0x18,0x03,0x83,0x34,0x08,0x0a,0x42,0x24,0x38,0x00,0xbf,0xaf,
-0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,
-0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
-0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x02,0x80,0x17,0x3c,0x68,0x15,0xf2,0x26,0xb0,0x03,0x93,0x34,0x02,0x80,0x14,0x3c,
-0xab,0x02,0x00,0x08,0x21,0xb0,0x40,0x02,0x2a,0xb0,0x03,0x3c,0x08,0x00,0x04,0xae,
-0x05,0x00,0x63,0x34,0x01,0x00,0x02,0x24,0x02,0x00,0x04,0x24,0x00,0x00,0x62,0xa0,
-0x00,0x00,0x64,0xa0,0xca,0x7d,0x82,0x96,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,
-0xca,0x7d,0x82,0xa6,0xca,0x7d,0x83,0x96,0x25,0xb0,0x02,0x3c,0x66,0x03,0x42,0x34,
-0x00,0x00,0x43,0xa4,0x4a,0x00,0x35,0x12,0x00,0x00,0x00,0x00,0x60,0x64,0x42,0x8e,
-0xcc,0x64,0x50,0x8e,0x01,0x00,0x04,0x24,0x00,0x00,0x62,0xae,0x64,0x64,0x42,0xae,
-0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0xcc,0x64,0x44,0x8e,
-0xd0,0x64,0x43,0x8e,0x20,0x00,0x84,0x24,0x3f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,
-0x0a,0x18,0x82,0x00,0xcc,0x64,0x43,0xae,0xcc,0x64,0xc5,0x8e,0x00,0x00,0x00,0x00,
-0x00,0x00,0x65,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,
-0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0xff,0x00,0x15,0x24,0x01,0x00,0x04,0x24,
-0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0x20,0x10,0x02,0x3c,0x20,0x00,0x07,0x24,
-0x00,0x1a,0x11,0x00,0x21,0x18,0x62,0x00,0x05,0x00,0x35,0x12,0x21,0x30,0x60,0x00,
-0x60,0x64,0xc3,0xae,0x0c,0x64,0xd1,0xa2,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
-0x04,0x00,0x04,0x8e,0x08,0x00,0x03,0x8e,0xff,0xe0,0x02,0x3c,0xff,0xff,0x42,0x34,
-0x1f,0x00,0x84,0x30,0x24,0x18,0x62,0x00,0x00,0x26,0x04,0x00,0xff,0xdf,0x02,0x3c,
-0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x00,0x40,0x04,0x3c,
-0x25,0x18,0x64,0x00,0xc0,0xff,0x05,0x24,0x82,0x11,0x03,0x00,0x24,0x20,0x65,0x00,
-0x01,0x00,0x42,0x30,0xb8,0xff,0x40,0x10,0x04,0x00,0x84,0x34,0x08,0x00,0x03,0xae,
-0x2a,0xb0,0x03,0x3c,0x05,0x00,0x63,0x34,0x01,0x00,0x02,0x24,0x02,0x00,0x04,0x24,
-0x00,0x00,0x62,0xa0,0x00,0x00,0x64,0xa0,0xca,0x7d,0x82,0x96,0x00,0x00,0x00,0x00,
-0x01,0x00,0x42,0x24,0xca,0x7d,0x82,0xa6,0xca,0x7d,0x83,0x96,0x25,0xb0,0x02,0x3c,
-0x66,0x03,0x42,0x34,0x00,0x00,0x43,0xa4,0xb8,0xff,0x35,0x16,0x00,0x00,0x00,0x00,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x68,0x15,0xe2,0x26,0xfc,0x4a,0x43,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
-0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
-0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x38,0x63,0x34,
-0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x83,0xac,0x08,0x00,0xe0,0x03,
-0xfc,0x4a,0x43,0xac,0xc0,0xff,0xbd,0x27,0x2c,0x00,0xb5,0xaf,0x38,0x00,0xbf,0xaf,
-0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,
-0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x02,0x80,0x06,0x3c,
-0x7c,0x7e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,
-0x24,0x0c,0x63,0x24,0x40,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,0x21,0xa8,0x00,0x00,
-0x03,0x00,0x80,0x10,0x7f,0x00,0xa2,0x30,0xbf,0x00,0xa2,0x30,0x01,0x00,0x15,0x24,
-0x7c,0x7e,0xc2,0xa0,0x7c,0x7e,0xc2,0x90,0x25,0xb0,0x04,0x3c,0x88,0x02,0x83,0x34,
-0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x02,0x80,0x16,0x3c,0x68,0x15,0xd2,0x26,0xb0,0x03,0x93,0x34,0x02,0x80,0x14,0x3c,
-0x43,0x03,0x00,0x08,0x21,0xb8,0x40,0x02,0x24,0x10,0xa2,0x00,0x04,0x00,0x42,0x34,
-0x2a,0xb0,0x07,0x3c,0x08,0x00,0x02,0xae,0x0d,0x00,0xe2,0x34,0x04,0x00,0x43,0x24,
-0x0b,0x10,0x75,0x00,0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24,0x00,0x00,0x44,0xa0,
-0x00,0x00,0x43,0xa0,0xca,0x7d,0x84,0x96,0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,
-0x01,0x00,0x84,0x24,0xca,0x7d,0x84,0xa6,0xca,0x7d,0x82,0x96,0xff,0x00,0x03,0x24,
-0x00,0x00,0xa2,0xa4,0x5a,0x00,0x23,0x12,0x00,0x00,0x00,0x00,0x24,0x64,0x42,0x8e,
-0x90,0x64,0x50,0x8e,0x03,0x00,0x04,0x24,0x00,0x00,0x62,0xae,0x28,0x64,0x42,0xae,
-0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0x90,0x64,0x44,0x8e,
-0x94,0x64,0x43,0x8e,0x20,0x00,0x84,0x24,0x3f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,
-0x0a,0x18,0x82,0x00,0x90,0x64,0x43,0xae,0x90,0x64,0xe2,0x8e,0x00,0x00,0x00,0x00,
-0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,
-0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,
-0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,0x0d,0x00,0x22,0x12,0x00,0x12,0x11,0x00,
-0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,0x5a,0x00,0xa0,0x12,0x24,0x64,0xe2,0xae,
-0xec,0x63,0xf1,0xa2,0x68,0x15,0xc2,0x26,0x24,0x64,0x46,0x8c,0x90,0x64,0x45,0x8c,
-0x03,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
-0x04,0x00,0x04,0x8e,0x14,0x00,0x03,0x8e,0x08,0x00,0x05,0x8e,0xff,0xe0,0x02,0x3c,
-0x1f,0x00,0x84,0x30,0x42,0x1a,0x03,0x00,0xff,0xff,0x42,0x34,0x00,0x26,0x04,0x00,
-0x24,0x28,0xa2,0x00,0x3f,0x00,0x63,0x30,0x25,0x28,0xa4,0x00,0x0c,0x00,0x63,0x28,
-0x06,0x00,0x60,0x14,0x21,0x20,0xa0,0x00,0x00,0x00,0x02,0x96,0x00,0x00,0x00,0x00,
-0xfd,0x0f,0x42,0x28,0x08,0x00,0x40,0x14,0x82,0x11,0x05,0x00,0xff,0xdf,0x02,0x3c,
-0xff,0xff,0x42,0x34,0x24,0x28,0x82,0x00,0x00,0x40,0x03,0x3c,0x25,0x20,0xa3,0x00,
-0x21,0x28,0x80,0x00,0x82,0x11,0x05,0x00,0x01,0x00,0x42,0x30,0xa6,0xff,0x40,0x10,
-0xc0,0xff,0x02,0x24,0x2a,0xb0,0x07,0x3c,0x0d,0x00,0xe2,0x34,0x04,0x00,0x43,0x24,
-0x08,0x00,0x04,0xae,0x0b,0x10,0x75,0x00,0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24,
-0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,0xca,0x7d,0x84,0x96,0x25,0xb0,0x06,0x3c,
-0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,0xca,0x7d,0x84,0xa6,0xca,0x7d,0x82,0x96,
-0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,0xa8,0xff,0x23,0x16,0x00,0x00,0x00,0x00,
-0x22,0x00,0xa0,0x12,0x68,0x15,0xc2,0x26,0xec,0x63,0x43,0x90,0x41,0x00,0xe4,0x34,
-0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x68,0x15,0xc5,0x26,0xfc,0x4a,0xa4,0x8c,
-0x01,0x00,0x02,0x3c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,
-0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,
-0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x80,0x42,0x34,0x25,0x20,0x82,0x00,
-0x41,0xb0,0x03,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x64,0xac,0x08,0x00,0xe0,0x03,
-0xfc,0x4a,0xa4,0xac,0x65,0x03,0x00,0x08,0xe8,0x63,0xf1,0xa2,0xe8,0x63,0x43,0x90,
-0x40,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,0x00,0x00,0xa3,0xac,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x68,0x15,0xc5,0x26,
-0xfc,0x4a,0xa4,0x8c,0x01,0x00,0x02,0x3c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
-0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
-0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x00,0x80,0x42,0x34,
-0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x64,0xac,
-0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa4,0xac,0xc0,0xff,0xbd,0x27,0x2c,0x00,0xb5,0xaf,
-0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x28,0x00,0xb4,0xaf,
-0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
-0x02,0x80,0x06,0x3c,0x7c,0x7e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
-0x18,0x03,0x42,0x34,0x78,0x0f,0x63,0x24,0x10,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,
-0x21,0xa8,0x00,0x00,0x03,0x00,0x80,0x10,0xdf,0x00,0xa2,0x30,0xef,0x00,0xa2,0x30,
-0x01,0x00,0x15,0x24,0x7c,0x7e,0xc2,0xa0,0x7c,0x7e,0xc3,0x90,0x25,0xb0,0x02,0x3c,
-0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x02,0x80,0x16,0x3c,0x68,0x15,0xd2,0x26,
-0x21,0x98,0x40,0x00,0x02,0x80,0x14,0x3c,0x19,0x04,0x00,0x08,0x21,0xb8,0x40,0x02,
-0x24,0x10,0xa2,0x00,0x04,0x00,0x42,0x34,0x2a,0xb0,0x07,0x3c,0x08,0x00,0x02,0xae,
-0x15,0x00,0xe2,0x34,0x04,0x00,0x43,0x24,0x0b,0x10,0x75,0x00,0x01,0x00,0x04,0x24,
-0x02,0x00,0x03,0x24,0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,0xca,0x7d,0x84,0x96,
-0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,0xca,0x7d,0x84,0xa6,
-0xca,0x7d,0x82,0x96,0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,0x5a,0x00,0x23,0x12,
-0x00,0x00,0x00,0x00,0x30,0x64,0x42,0x8e,0x9c,0x64,0x50,0x8e,0x04,0x00,0x04,0x24,
-0x00,0x00,0x62,0xae,0x34,0x64,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x9c,0x64,0x44,0x8e,0xa0,0x64,0x43,0x8e,0x20,0x00,0x84,0x24,
-0x3f,0x00,0x62,0x24,0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0x9c,0x64,0x43,0xae,
-0x9c,0x64,0xe2,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c,
-0xff,0xff,0x10,0x32,0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,
-0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,
-0x0d,0x00,0x22,0x12,0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,
-0x59,0x00,0xa0,0x12,0x30,0x64,0xe2,0xae,0xf4,0x63,0xf1,0xa2,0x68,0x15,0xc2,0x26,
-0x30,0x64,0x46,0x8c,0x9c,0x64,0x45,0x8c,0x04,0x00,0x04,0x24,0x20,0x00,0x07,0x24,
-0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x04,0x00,0x04,0x8e,0x14,0x00,0x03,0x8e,
-0x08,0x00,0x05,0x8e,0xff,0xe0,0x02,0x3c,0x1f,0x00,0x84,0x30,0x42,0x1a,0x03,0x00,
-0xff,0xff,0x42,0x34,0x00,0x26,0x04,0x00,0x24,0x28,0xa2,0x00,0x3f,0x00,0x63,0x30,
-0x25,0x28,0xa4,0x00,0x0c,0x00,0x63,0x28,0x06,0x00,0x60,0x14,0x21,0x20,0xa0,0x00,
-0x00,0x00,0x02,0x96,0x00,0x00,0x00,0x00,0xfd,0x0f,0x42,0x28,0x08,0x00,0x40,0x14,
-0x82,0x11,0x05,0x00,0xff,0xdf,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x28,0x82,0x00,
-0x00,0x40,0x03,0x3c,0x25,0x20,0xa3,0x00,0x21,0x28,0x80,0x00,0x82,0x11,0x05,0x00,
-0x01,0x00,0x42,0x30,0xa6,0xff,0x40,0x10,0xc0,0xff,0x02,0x24,0x2a,0xb0,0x07,0x3c,
-0x15,0x00,0xe2,0x34,0x04,0x00,0x43,0x24,0x08,0x00,0x04,0xae,0x0b,0x10,0x75,0x00,
-0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24,0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,
-0xca,0x7d,0x84,0x96,0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,
-0xca,0x7d,0x84,0xa6,0xca,0x7d,0x82,0x96,0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,
-0xa8,0xff,0x23,0x16,0x00,0x00,0x00,0x00,0x21,0x00,0xa0,0x12,0x68,0x15,0xc2,0x26,
-0xf4,0x63,0x43,0x90,0x43,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,
-0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x68,0x15,0xc5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
-0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
-0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x06,0x00,0x03,0x3c,
-0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,
-0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0x3b,0x04,0x00,0x08,0xf0,0x63,0xf1,0xa2,
-0xf0,0x63,0x43,0x90,0x42,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,
-0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x68,0x15,0xc5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
-0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
-0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x06,0x00,0x03,0x3c,
-0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,
-0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0xc0,0xff,0xbd,0x27,0x2c,0x00,0xb5,0xaf,
-0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x28,0x00,0xb4,0xaf,
-0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
-0x02,0x80,0x06,0x3c,0x7c,0x7e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
-0x18,0x03,0x42,0x34,0xc8,0x12,0x63,0x24,0x01,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,
-0x21,0xa8,0x00,0x00,0x03,0x00,0x80,0x10,0xf7,0x00,0xa2,0x30,0xfe,0x00,0xa2,0x30,
-0x01,0x00,0x15,0x24,0x7c,0x7e,0xc2,0xa0,0x7c,0x7e,0xc3,0x90,0x25,0xb0,0x02,0x3c,
-0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x00,0x60,0x81,0x40,0x02,0x80,0x16,0x3c,0x68,0x15,0xd2,0x26,0x21,0x98,0x40,0x00,
-0x02,0x80,0x14,0x3c,0xf8,0x04,0x00,0x08,0x21,0xb8,0x40,0x02,0x00,0x00,0x02,0x96,
-0x00,0x00,0x00,0x00,0xfd,0x0f,0x42,0x28,0x54,0x00,0x40,0x10,0xff,0xdf,0x02,0x3c,
-0x00,0x20,0x02,0x3c,0x25,0x28,0xa2,0x00,0x82,0x11,0x05,0x00,0x01,0x00,0x42,0x30,
-0x57,0x00,0x40,0x14,0x2a,0xb0,0x07,0x3c,0xc0,0xff,0x02,0x24,0x24,0x10,0xa2,0x00,
-0x04,0x00,0x42,0x34,0x2a,0xb0,0x07,0x3c,0x08,0x00,0x02,0xae,0x1d,0x00,0xe2,0x34,
-0x04,0x00,0x43,0x24,0x0b,0x10,0x75,0x00,0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24,
-0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,0xca,0x7d,0x84,0x96,0x25,0xb0,0x06,0x3c,
-0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,0xca,0x7d,0x84,0xa6,0xca,0x7d,0x82,0x96,
-0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,0x53,0x00,0x23,0x12,0x00,0x00,0x00,0x00,
-0x3c,0x64,0x42,0x8e,0xa8,0x64,0x50,0x8e,0x05,0x00,0x04,0x24,0x00,0x00,0x62,0xae,
-0x40,0x64,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,
-0xa8,0x64,0x44,0x8e,0xac,0x64,0x43,0x8e,0x20,0x00,0x84,0x24,0x3f,0x00,0x62,0x24,
-0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0xa8,0x64,0x43,0xae,0xa8,0x64,0xe2,0x8e,
-0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,
-0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0x00,0x00,0x00,0x00,
-0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,0x0d,0x00,0x22,0x12,
-0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,0x52,0x00,0xa0,0x12,
-0x3c,0x64,0xe2,0xae,0x04,0x64,0xf1,0xa2,0x68,0x15,0xc2,0x26,0x3c,0x64,0x46,0x8c,
-0xa8,0x64,0x45,0x8c,0x05,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,
-0x10,0x00,0xa0,0xaf,0x14,0x00,0x03,0x8e,0x04,0x00,0x04,0x8e,0x08,0x00,0x05,0x8e,
-0x42,0x1a,0x03,0x00,0xff,0xe0,0x02,0x3c,0x1f,0x00,0x84,0x30,0x3f,0x00,0x63,0x30,
-0xff,0xff,0x42,0x34,0x24,0x28,0xa2,0x00,0x00,0x26,0x04,0x00,0x0c,0x00,0x63,0x28,
-0xaa,0xff,0x60,0x10,0x25,0x28,0xa4,0x00,0xff,0xdf,0x02,0x3c,0xff,0xff,0x42,0x34,
-0x24,0x10,0xa2,0x00,0x00,0x40,0x03,0x3c,0x25,0x28,0x43,0x00,0x82,0x11,0x05,0x00,
-0x01,0x00,0x42,0x30,0xad,0xff,0x40,0x10,0xc0,0xff,0x02,0x24,0x2a,0xb0,0x07,0x3c,
-0x1d,0x00,0xe2,0x34,0x04,0x00,0x43,0x24,0x0b,0x10,0x75,0x00,0x01,0x00,0x04,0x24,
-0x02,0x00,0x03,0x24,0x08,0x00,0x05,0xae,0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,
-0xca,0x7d,0x84,0x96,0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,
-0xca,0x7d,0x84,0xa6,0xca,0x7d,0x82,0x96,0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,
-0xaf,0xff,0x23,0x16,0x00,0x00,0x00,0x00,0x21,0x00,0xa0,0x12,0x68,0x15,0xc2,0x26,
-0x04,0x64,0x43,0x90,0x45,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,
-0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x68,0x15,0xc5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
-0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
-0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x18,0x00,0x03,0x3c,
-0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,
-0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0x1a,0x05,0x00,0x08,0xf8,0x63,0xf1,0xa2,
-0xf8,0x63,0x43,0x90,0x44,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,
-0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x68,0x15,0xc5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
-0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
-0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x18,0x00,0x03,0x3c,
-0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,
-0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0xc0,0xff,0xbd,0x27,0x2c,0x00,0xb5,0xaf,
-0x38,0x00,0xbf,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x28,0x00,0xb4,0xaf,
-0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
-0x02,0x80,0x06,0x3c,0x7c,0x7e,0xc5,0x90,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
-0x18,0x03,0x42,0x34,0x28,0x16,0x63,0x24,0x02,0x00,0xa4,0x30,0x00,0x00,0x43,0xac,
-0x21,0xa8,0x00,0x00,0x03,0x00,0x80,0x10,0xfb,0x00,0xa2,0x30,0xfd,0x00,0xa2,0x30,
-0x01,0x00,0x15,0x24,0x7c,0x7e,0xc2,0xa0,0x7c,0x7e,0xc3,0x90,0x25,0xb0,0x02,0x3c,
-0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x00,0x60,0x81,0x40,0x02,0x80,0x16,0x3c,0x68,0x15,0xd2,0x26,0x21,0x98,0x40,0x00,
-0x02,0x80,0x14,0x3c,0xd0,0x05,0x00,0x08,0x21,0xb8,0x40,0x02,0x00,0x00,0x02,0x96,
-0x00,0x00,0x00,0x00,0xfd,0x0f,0x42,0x28,0x54,0x00,0x40,0x10,0xff,0xdf,0x02,0x3c,
-0x00,0x20,0x02,0x3c,0x25,0x28,0xa2,0x00,0x82,0x11,0x05,0x00,0x01,0x00,0x42,0x30,
-0x57,0x00,0x40,0x14,0x2a,0xb0,0x07,0x3c,0xc0,0xff,0x02,0x24,0x24,0x10,0xa2,0x00,
-0x04,0x00,0x42,0x34,0x2a,0xb0,0x07,0x3c,0x08,0x00,0x02,0xae,0x25,0x00,0xe2,0x34,
-0x04,0x00,0x43,0x24,0x0b,0x10,0x75,0x00,0x01,0x00,0x04,0x24,0x02,0x00,0x03,0x24,
-0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,0xca,0x7d,0x84,0x96,0x25,0xb0,0x06,0x3c,
-0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,0xca,0x7d,0x84,0xa6,0xca,0x7d,0x82,0x96,
-0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,0x53,0x00,0x23,0x12,0x00,0x00,0x00,0x00,
-0x48,0x64,0x42,0x8e,0xb4,0x64,0x50,0x8e,0x06,0x00,0x04,0x24,0x00,0x00,0x62,0xae,
-0x4c,0x64,0x42,0xae,0x00,0x00,0x70,0xae,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,
-0xb4,0x64,0x44,0x8e,0xb8,0x64,0x43,0x8e,0x20,0x00,0x84,0x24,0x3f,0x00,0x62,0x24,
-0x2b,0x10,0x44,0x00,0x0a,0x18,0x82,0x00,0xb4,0x64,0x43,0xae,0xb4,0x64,0xe2,0x8e,
-0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xae,0x02,0x80,0x02,0x3c,0xff,0xff,0x10,0x32,
-0x25,0x80,0x02,0x02,0x00,0x00,0x70,0xae,0x0c,0x00,0x02,0x92,0x00,0x00,0x00,0x00,
-0x00,0x00,0x62,0xae,0x0c,0x00,0x11,0x92,0xff,0x00,0x02,0x24,0x0d,0x00,0x22,0x12,
-0x00,0x12,0x11,0x00,0x20,0x10,0x03,0x3c,0x21,0x10,0x43,0x00,0x52,0x00,0xa0,0x12,
-0x48,0x64,0xe2,0xae,0x00,0x64,0xf1,0xa2,0x68,0x15,0xc2,0x26,0x48,0x64,0x46,0x8c,
-0xb4,0x64,0x45,0x8c,0x06,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,
-0x10,0x00,0xa0,0xaf,0x14,0x00,0x03,0x8e,0x04,0x00,0x04,0x8e,0x08,0x00,0x05,0x8e,
-0x42,0x1a,0x03,0x00,0xff,0xe0,0x02,0x3c,0x1f,0x00,0x84,0x30,0x3f,0x00,0x63,0x30,
-0xff,0xff,0x42,0x34,0x24,0x28,0xa2,0x00,0x00,0x26,0x04,0x00,0x0c,0x00,0x63,0x28,
-0xaa,0xff,0x60,0x10,0x25,0x28,0xa4,0x00,0xff,0xdf,0x02,0x3c,0xff,0xff,0x42,0x34,
-0x24,0x10,0xa2,0x00,0x00,0x40,0x03,0x3c,0x25,0x28,0x43,0x00,0x82,0x11,0x05,0x00,
-0x01,0x00,0x42,0x30,0xad,0xff,0x40,0x10,0xc0,0xff,0x02,0x24,0x2a,0xb0,0x07,0x3c,
-0x25,0x00,0xe2,0x34,0x04,0x00,0x43,0x24,0x0b,0x10,0x75,0x00,0x01,0x00,0x04,0x24,
-0x02,0x00,0x03,0x24,0x08,0x00,0x05,0xae,0x00,0x00,0x44,0xa0,0x00,0x00,0x43,0xa0,
-0xca,0x7d,0x84,0x96,0x25,0xb0,0x06,0x3c,0x66,0x03,0xc5,0x34,0x01,0x00,0x84,0x24,
-0xca,0x7d,0x84,0xa6,0xca,0x7d,0x82,0x96,0xff,0x00,0x03,0x24,0x00,0x00,0xa2,0xa4,
-0xaf,0xff,0x23,0x16,0x00,0x00,0x00,0x00,0x21,0x00,0xa0,0x12,0x68,0x15,0xc2,0x26,
-0x00,0x64,0x43,0x90,0x47,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,
-0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x68,0x15,0xc5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
-0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
-0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x60,0x00,0x03,0x3c,
-0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,
-0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0xf2,0x05,0x00,0x08,0xfc,0x63,0xf1,0xa2,
-0xfc,0x63,0x43,0x90,0x46,0x00,0xe4,0x34,0xb0,0x03,0xc5,0x34,0x00,0x00,0x83,0xa0,
-0x00,0x00,0xa3,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x68,0x15,0xc5,0x26,0xfc,0x4a,0xa2,0x8c,0x38,0x00,0xbf,0x8f,0x34,0x00,0xb7,0x8f,
-0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
-0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x60,0x00,0x03,0x3c,
-0x25,0x10,0x43,0x00,0x41,0xb0,0x04,0x3c,0x40,0x00,0xbd,0x27,0x00,0x00,0x82,0xac,
-0x08,0x00,0xe0,0x03,0xfc,0x4a,0xa2,0xac,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
-0x88,0x19,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x05,0x3c,0x68,0x15,0xa5,0x24,
-0x04,0x4b,0xa2,0x8c,0xfc,0x4a,0xa4,0x8c,0x00,0x08,0x03,0x3c,0x24,0x10,0x43,0x00,
-0x25,0x20,0x82,0x00,0x41,0xb0,0x03,0x3c,0x00,0x00,0x64,0xac,0x08,0x00,0xe0,0x03,
-0xfc,0x4a,0xa4,0xac,0x25,0xb0,0x04,0x3c,0x00,0x80,0x02,0x3c,0xc0,0xff,0xbd,0x27,
-0x18,0x03,0x83,0x34,0xe4,0x19,0x42,0x24,0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf,
-0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x28,0x00,0xb4,0xaf,
-0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
-0x00,0x00,0x62,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x02,0x80,0x02,0x3c,0x2a,0xb0,0x03,0x3c,0x68,0x15,0x51,0x24,0xb0,0x03,0x93,0x34,
-0x2c,0x00,0x77,0x34,0x02,0x80,0x15,0x3c,0x02,0x80,0x16,0x3c,0x9c,0x06,0x00,0x08,
-0x02,0x80,0x1e,0x3c,0x14,0x64,0x26,0x92,0xe4,0x64,0x25,0x8e,0x00,0x32,0x06,0x00,
-0x21,0x30,0xc2,0x00,0x78,0x64,0x26,0xae,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
-0xe4,0x64,0x30,0x8e,0x0a,0x00,0x04,0x24,0x21,0x90,0x00,0x00,0x00,0x00,0x70,0xae,
-0x4d,0x01,0x00,0x0c,0xff,0xff,0x10,0x32,0x02,0x80,0x02,0x3c,0x25,0x80,0x02,0x02,
-0x0c,0x00,0x05,0x92,0x02,0x00,0x04,0x92,0xff,0x00,0x02,0x24,0xff,0x00,0xa3,0x30,
-0x04,0x00,0x62,0x10,0x21,0x80,0x04,0x02,0x00,0x00,0x63,0xae,0x01,0x00,0x12,0x24,
-0x14,0x64,0x25,0xa2,0x88,0x96,0xb0,0xae,0x21,0x28,0x00,0x02,0x02,0x00,0xa2,0x90,
-0x08,0x00,0x10,0x26,0x21,0x20,0x00,0x02,0xff,0x00,0x42,0x30,0x00,0x00,0x62,0xae,
-0x03,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x7f,0x00,0x63,0x30,0x00,0x00,0x63,0xae,
-0x00,0x00,0x72,0xae,0x03,0x00,0xa2,0x90,0x84,0x96,0xc3,0x92,0x02,0x00,0xa2,0x90,
-0x00,0x00,0x00,0x00,0xff,0x00,0x42,0x30,0x2c,0x00,0x42,0x28,0x11,0x00,0x40,0x10,
-0x08,0x00,0x02,0x24,0x03,0x00,0xa2,0x90,0x00,0x00,0x00,0x00,0x7f,0x00,0x42,0x30,
-0x84,0x96,0xc2,0xa2,0x02,0x00,0xa3,0x90,0x02,0x80,0x02,0x3c,0x74,0x84,0x42,0x24,
-0xff,0x00,0x63,0x30,0xc0,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x04,0x00,0x62,0x8c,
-0x00,0x00,0x00,0x00,0x09,0xf8,0x40,0x00,0x80,0x96,0xc2,0xaf,0x21,0xa0,0x40,0x00,
-0x08,0x00,0x02,0x24,0x0a,0x00,0x04,0x24,0x05,0x00,0x82,0x12,0x00,0x01,0x07,0x24,
-0x01,0x00,0x02,0x24,0x02,0x00,0x03,0x24,0x01,0x00,0xe2,0xa2,0x01,0x00,0xe3,0xa2,
-0xbc,0xff,0x40,0x16,0x20,0x10,0x02,0x3c,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0xfc,0x4a,0x22,0x8e,0x00,0x04,0x03,0x3c,
-0x41,0xb0,0x04,0x3c,0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xac,0x3c,0x00,0xbf,0x8f,
-0xfc,0x4a,0x22,0xae,0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,
-0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,
-0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,
-0xc8,0xff,0xbd,0x27,0xff,0xff,0xa8,0x30,0x02,0x80,0x02,0x3c,0x25,0x40,0x02,0x01,
-0x30,0x00,0xb6,0xaf,0x20,0x00,0xb2,0xaf,0x34,0x00,0xbf,0xaf,0x2c,0x00,0xb5,0xaf,
-0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
-0x00,0x00,0x03,0x8d,0xff,0xff,0xd2,0x30,0x21,0xb0,0xa0,0x00,0x00,0xc0,0x02,0x24,
-0x08,0x00,0x45,0x26,0x04,0x00,0x06,0x8d,0x24,0x18,0x62,0x00,0xff,0x3f,0xa5,0x30,
-0xf0,0xff,0x02,0x3c,0x25,0x18,0x65,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,
-0x00,0x80,0x05,0x3c,0x25,0x18,0x65,0x00,0xff,0x01,0xc6,0x34,0x00,0x00,0x03,0xad,
-0x04,0x00,0x06,0xad,0x21,0x48,0x80,0x00,0xff,0xff,0xe7,0x30,0x18,0x00,0x12,0xa5,
-0x1a,0x00,0x07,0xa1,0x18,0x00,0x03,0x8d,0xff,0x7f,0x02,0x3c,0xff,0xff,0x42,0x34,
-0x24,0x18,0x62,0x00,0x02,0x80,0x15,0x3c,0x18,0x00,0x03,0xad,0x68,0x15,0xa5,0x26,
-0xd6,0x63,0xa3,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x62,0x24,0xd6,0x63,0xa2,0xa0,
-0x18,0x00,0x04,0x8d,0xff,0x80,0x02,0x3c,0x20,0x00,0x45,0x26,0xff,0xff,0x42,0x34,
-0x7f,0x00,0x63,0x30,0xff,0xff,0xb2,0x30,0x24,0x20,0x82,0x00,0x00,0x1e,0x03,0x00,
-0x25,0xb0,0x02,0x3c,0xc0,0x00,0x42,0x34,0x25,0x20,0x83,0x00,0x07,0x00,0x45,0x32,
-0x18,0x00,0x04,0xad,0x00,0x00,0x52,0xa4,0x03,0x00,0xa0,0x10,0xff,0xff,0x42,0x32,
-0x08,0x00,0x42,0x26,0xff,0xff,0x42,0x30,0x68,0x15,0xb4,0x26,0x54,0x65,0x86,0x8e,
-0x58,0x65,0x90,0x8e,0xf8,0xff,0x52,0x30,0x21,0x10,0xd2,0x00,0x2b,0x10,0x02,0x02,
-0x31,0x00,0x40,0x10,0xff,0x00,0x33,0x31,0x23,0x80,0x06,0x02,0x21,0x28,0xc0,0x02,
-0xff,0xff,0x07,0x32,0x01,0x00,0x11,0x24,0x21,0x20,0x60,0x02,0x10,0x01,0x00,0x0c,
-0x10,0x00,0xb1,0xaf,0x23,0x18,0x50,0x02,0xff,0xff,0x72,0x30,0x22,0x10,0x02,0x3c,
-0x21,0x10,0x42,0x02,0x21,0x20,0x60,0x02,0x4d,0x01,0x00,0x0c,0x54,0x65,0x82,0xae,
-0x21,0x28,0xd0,0x02,0x21,0x38,0x40,0x02,0x21,0x20,0x60,0x02,0x10,0x00,0xb1,0xaf,
-0x22,0x10,0x06,0x3c,0x10,0x01,0x00,0x0c,0x68,0x15,0xb1,0x26,0x54,0x65,0x23,0x8e,
-0x25,0xb0,0x10,0x3c,0xb0,0x03,0x02,0x36,0x21,0x20,0x60,0x02,0x00,0x00,0x43,0xac,
-0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0x54,0x65,0x25,0x8e,0xec,0x00,0x02,0x36,
-0xbd,0x00,0x04,0x36,0x00,0x00,0x45,0xac,0x00,0x00,0x83,0x90,0xc2,0x00,0x10,0x36,
-0x34,0x00,0xbf,0x8f,0x10,0x00,0x63,0x34,0x00,0x00,0x83,0xa0,0x30,0x00,0xb6,0x8f,
-0x00,0x00,0x05,0xa6,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,
-0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,
-0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x21,0x28,0xc0,0x02,0x21,0x20,0x60,0x02,
-0x21,0x38,0x40,0x02,0x01,0x00,0x02,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa2,0xaf,
-0x54,0x65,0x83,0x8e,0x68,0x15,0xb1,0x26,0x25,0xb0,0x10,0x3c,0x21,0x18,0x72,0x00,
-0x54,0x65,0x83,0xae,0x54,0x65,0x23,0x8e,0xb0,0x03,0x02,0x36,0x21,0x20,0x60,0x02,
-0x00,0x00,0x43,0xac,0x4d,0x01,0x00,0x0c,0x00,0x00,0x00,0x00,0x54,0x65,0x25,0x8e,
-0xec,0x00,0x02,0x36,0xbd,0x00,0x04,0x36,0x00,0x00,0x45,0xac,0x00,0x00,0x83,0x90,
-0xc2,0x00,0x10,0x36,0x34,0x00,0xbf,0x8f,0x10,0x00,0x63,0x34,0x00,0x00,0x83,0xa0,
-0x30,0x00,0xb6,0x8f,0x00,0x00,0x05,0xa6,0x2c,0x00,0xb5,0x8f,0x28,0x00,0xb4,0x8f,
-0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
-0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,
-0x25,0xb0,0x02,0x3c,0x14,0x00,0xb1,0xaf,0x18,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,
-0xbf,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0x21,0x28,0x00,0x00,0x08,0x00,0x06,0x24,
-0x04,0x00,0x63,0x2c,0x12,0x00,0x60,0x14,0x21,0x88,0x80,0x00,0x00,0x60,0x02,0x40,
-0x01,0x00,0x41,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x03,0x3c,
-0x00,0x7b,0x63,0x24,0x04,0x00,0x64,0x8c,0x00,0x00,0x23,0xae,0x04,0x00,0x71,0xac,
-0x00,0x00,0x91,0xac,0x04,0x00,0x24,0xae,0x00,0x60,0x82,0x40,0x18,0x00,0xbf,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
-0x08,0x00,0x82,0x94,0x02,0x80,0x04,0x3c,0x97,0x45,0x00,0x0c,0x25,0x20,0x44,0x00,
-0x00,0x60,0x10,0x40,0x01,0x00,0x01,0x36,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x08,0x00,0x25,0x8e,0x0c,0x00,0x26,0x96,0x14,0x00,0x27,0x96,0xf0,0x06,0x00,0x0c,
-0x09,0x00,0x04,0x24,0x04,0x00,0x23,0x8e,0x00,0x00,0x22,0x8e,0x21,0x20,0x20,0x02,
-0x00,0x00,0x62,0xac,0x04,0x00,0x43,0xac,0x00,0x00,0x31,0xae,0xbd,0x4e,0x00,0x0c,
-0x04,0x00,0x31,0xae,0x00,0x60,0x90,0x40,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x02,0x80,0x02,0x3c,
-0x68,0x15,0x47,0x24,0x8c,0x64,0xe3,0x90,0xff,0xff,0xa5,0x30,0x09,0x00,0xa3,0x10,
-0x21,0x20,0xc0,0x00,0xfc,0x64,0xe2,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0xc2,0xac,
-0x06,0x65,0xe3,0x94,0x0e,0x00,0x02,0x24,0x14,0x00,0xc2,0xac,0x8b,0x07,0x00,0x08,
-0x0c,0x00,0xc3,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x80,0x03,0x3c,
-0x25,0xb0,0x02,0x3c,0xd0,0xff,0xbd,0x27,0x4c,0x1f,0x63,0x24,0x18,0x03,0x42,0x34,
-0x28,0x00,0xbf,0xaf,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,
-0x18,0x00,0xb0,0xaf,0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x00,0x60,0x81,0x40,0x2a,0xb0,0x02,0x3c,0x36,0x00,0x42,0x34,0x00,0x00,0x43,0x90,
-0x02,0x80,0x13,0x3c,0x68,0x15,0x66,0x26,0xc0,0x18,0x03,0x00,0x5c,0x65,0xc5,0x8c,
-0x23,0xb0,0x04,0x3c,0xf0,0x07,0x63,0x30,0xff,0x1f,0x02,0x3c,0x21,0x18,0x64,0x00,
-0xff,0xff,0x42,0x34,0x24,0x20,0x62,0x00,0x23,0x88,0x85,0x00,0x2b,0x38,0x85,0x00,
-0x00,0x04,0x22,0x26,0x00,0x65,0xc3,0x8c,0x0b,0x88,0x47,0x00,0x01,0x04,0x25,0x2e,
-0xfc,0x64,0xc3,0xac,0x60,0x65,0xc4,0xac,0x06,0x65,0xc0,0xa4,0x11,0x00,0xa0,0x14,
-0x05,0x65,0xc0,0xa0,0x00,0xfc,0x83,0x24,0x23,0x10,0x02,0x3c,0x0b,0x18,0x87,0x00,
-0xff,0x03,0x42,0x34,0x2b,0x10,0x43,0x00,0x33,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
-0x23,0x88,0x83,0x00,0x2b,0x10,0x83,0x00,0x5c,0x65,0xc3,0xac,0x03,0x00,0x40,0x10,
-0x01,0x04,0x25,0x2e,0x00,0x04,0x31,0x26,0x01,0x04,0x25,0x2e,0x0e,0x00,0xa0,0x10,
-0x68,0x15,0x70,0x26,0x68,0x15,0x70,0x26,0x60,0x65,0x03,0x8e,0x5c,0x65,0x04,0x8e,
-0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00,0x25,0x00,0x40,0x14,0x2b,0x10,0x64,0x00,
-0x51,0x00,0x40,0x14,0x25,0xb0,0x02,0x3c,0x80,0x00,0x03,0x24,0xd0,0x03,0x42,0x34,
-0x00,0x00,0x43,0xac,0x68,0x15,0x70,0x26,0x5c,0x65,0x03,0x96,0x2a,0xb0,0x02,0x3c,
-0x35,0x00,0x42,0x34,0xc2,0x88,0x03,0x00,0x00,0x00,0x51,0xa0,0x8f,0x10,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x06,0x65,0x03,0x96,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,
-0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
-0x00,0x60,0x81,0x40,0xfc,0x4a,0x02,0x8e,0x80,0x00,0x03,0x3c,0x41,0xb0,0x04,0x3c,
-0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xac,0x28,0x00,0xbf,0x8f,0xfc,0x4a,0x02,0xae,
-0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
-0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0x00,0x08,0x00,0x08,0x00,0xfc,0x63,0x24,
-0xfc,0x64,0x05,0x8e,0x21,0x30,0x80,0x00,0xff,0xff,0x27,0x32,0x09,0x00,0x04,0x24,
-0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0xfc,0x64,0x03,0x8e,0x06,0x65,0x05,0x96,
-0x5c,0x65,0x02,0x8e,0x21,0x18,0x71,0x00,0x21,0x28,0x25,0x02,0x21,0x10,0x51,0x00,
-0x09,0x00,0x04,0x24,0x5c,0x65,0x02,0xae,0xfc,0x64,0x03,0xae,0x4d,0x01,0x00,0x0c,
-0x06,0x65,0x05,0xa6,0x68,0x15,0x70,0x26,0x5c,0x65,0x03,0x96,0x2a,0xb0,0x02,0x3c,
-0x35,0x00,0x42,0x34,0xc2,0x88,0x03,0x00,0x00,0x00,0x51,0xa0,0x8f,0x10,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x06,0x65,0x03,0x96,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,
-0x00,0x00,0x43,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
-0x00,0x60,0x81,0x40,0xfc,0x4a,0x02,0x8e,0x80,0x00,0x03,0x3c,0x41,0xb0,0x04,0x3c,
-0x25,0x10,0x43,0x00,0x00,0x00,0x82,0xac,0x28,0x00,0xbf,0x8f,0xfc,0x4a,0x02,0xae,
-0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
-0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0x64,0x65,0x02,0x8e,0xfc,0x64,0x05,0x8e,
-0x21,0x30,0x80,0x00,0x23,0x88,0x44,0x00,0xff,0xff,0x27,0x32,0x09,0x00,0x04,0x24,
-0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0xfc,0x64,0x03,0x8e,0x06,0x65,0x02,0x96,
-0x60,0x65,0x12,0x96,0x21,0x18,0x71,0x00,0x21,0x10,0x22,0x02,0x23,0x10,0x11,0x3c,
-0xfc,0x64,0x03,0xae,0x06,0x65,0x02,0xa6,0x06,0x00,0x40,0x16,0x5c,0x65,0x11,0xae,
-0x09,0x00,0x04,0x24,0x4d,0x01,0x00,0x0c,0x68,0x15,0x70,0x26,0x46,0x08,0x00,0x08,
-0x00,0x00,0x00,0x00,0x4d,0x01,0x00,0x0c,0x09,0x00,0x04,0x24,0xfc,0x64,0x05,0x8e,
-0x09,0x00,0x04,0x24,0x23,0x10,0x06,0x3c,0x21,0x38,0x40,0x02,0x10,0x01,0x00,0x0c,
-0x10,0x00,0xa0,0xaf,0xfc,0x64,0x03,0x8e,0x06,0x65,0x02,0x96,0x21,0x20,0x51,0x02,
-0x21,0x18,0x72,0x00,0x21,0x10,0x42,0x02,0x5c,0x65,0x04,0xae,0x09,0x00,0x04,0x24,
-0xfc,0x64,0x03,0xae,0x75,0x08,0x00,0x08,0x06,0x65,0x02,0xa6,0x02,0x80,0x09,0x3c,
-0x68,0x15,0x28,0x25,0xdc,0x63,0x06,0x8d,0xff,0xff,0x02,0x34,0x3f,0x00,0xc2,0x10,
-0x21,0x38,0x80,0x00,0x2b,0x10,0xc7,0x00,0x30,0x00,0x40,0x10,0x02,0x19,0x06,0x00,
-0x21,0x10,0xc7,0x00,0x23,0x10,0x43,0x00,0x10,0x00,0x46,0x24,0xdc,0x63,0x06,0xad,
-0x68,0x15,0x26,0x25,0x04,0x40,0xc4,0x8c,0xe0,0x63,0x02,0xad,0xff,0xff,0x02,0x34,
-0x2f,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0x2b,0x10,0x87,0x00,0x1f,0x00,0x40,0x10,
-0x02,0x19,0x04,0x00,0x21,0x10,0x87,0x00,0x23,0x10,0x43,0x00,0x10,0x00,0x44,0x24,
-0x04,0x40,0xc4,0xac,0xe0,0x63,0xc2,0xac,0xc0,0x10,0x05,0x00,0x21,0x10,0x45,0x00,
-0x80,0x10,0x02,0x00,0x21,0x10,0x45,0x00,0x68,0x15,0x23,0x25,0x80,0x10,0x02,0x00,
-0x21,0x28,0x43,0x00,0x68,0x51,0xa6,0x8c,0x00,0x21,0x07,0x00,0xff,0xff,0xc2,0x38,
-0x0a,0x30,0x82,0x00,0x2b,0x18,0xc7,0x00,0x07,0x00,0x60,0x10,0x21,0x10,0xc7,0x00,
-0x02,0x19,0x06,0x00,0x23,0x10,0x43,0x00,0x10,0x00,0x46,0x24,0x68,0x51,0xa6,0xac,
-0x08,0x00,0xe0,0x03,0x6c,0x51,0xa2,0xac,0x02,0x19,0x06,0x00,0x23,0x10,0x43,0x00,
-0x68,0x51,0xa2,0xac,0x08,0x00,0xe0,0x03,0x6c,0x51,0xa2,0xac,0x21,0x10,0x87,0x00,
-0x23,0x10,0x43,0x00,0xa5,0x08,0x00,0x08,0x04,0x40,0xc2,0xac,0x21,0x10,0xc7,0x00,
-0x68,0x15,0x26,0x25,0x04,0x40,0xc4,0x8c,0x23,0x10,0x43,0x00,0xdc,0x63,0x02,0xad,
-0xe0,0x63,0x02,0xad,0xff,0xff,0x02,0x34,0xd4,0xff,0x82,0x14,0x2b,0x10,0x87,0x00,
-0x00,0x21,0x07,0x00,0x9e,0x08,0x00,0x08,0x04,0x40,0xc4,0xac,0x00,0x31,0x04,0x00,
-0x91,0x08,0x00,0x08,0xdc,0x63,0x06,0xad,0x63,0x00,0x82,0x24,0x77,0x00,0x42,0x2c,
-0x00,0x00,0x85,0x28,0x04,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0x64,0x00,0x82,0x24,
-0x64,0x00,0x03,0x24,0x0b,0x18,0x45,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
-0x0c,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30,0x04,0x00,0x42,0x28,
-0x17,0x00,0x40,0x10,0x25,0xb0,0x02,0x3c,0x24,0x08,0x42,0x34,0x00,0x00,0x43,0x8c,
-0x00,0x00,0x00,0x00,0x00,0x02,0x63,0x30,0x16,0x00,0x60,0x14,0x01,0x00,0x02,0x24,
-0x05,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x82,0x21,0x03,0x00,0x28,0x00,0x82,0x10,
-0xf5,0xff,0x02,0x24,0x02,0x00,0x82,0x28,0x39,0x00,0x40,0x14,0x02,0x00,0x02,0x24,
-0x2e,0x00,0x82,0x10,0xe9,0xff,0x02,0x24,0x03,0x00,0x02,0x24,0x24,0x00,0x82,0x10,
-0x3e,0x00,0x63,0x30,0x05,0x00,0xc4,0x24,0xd2,0x08,0x00,0x08,0x00,0x00,0x00,0x00,
-0x04,0x00,0xa4,0x90,0x00,0x00,0x00,0x00,0x42,0x20,0x04,0x00,0xd2,0x08,0x00,0x08,
-0x96,0xff,0x84,0x24,0x05,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x60,0x00,0x64,0x30,
-0x42,0x21,0x04,0x00,0x0e,0x00,0x82,0x10,0x1f,0x00,0x62,0x30,0x02,0x00,0x82,0x28,
-0x1d,0x00,0x40,0x14,0x02,0x00,0x02,0x24,0x14,0x00,0x82,0x10,0x1f,0x00,0x62,0x30,
-0x03,0x00,0x02,0x24,0xeb,0xff,0x82,0x14,0x1f,0x00,0x62,0x30,0x40,0x10,0x02,0x00,
-0xdd,0xff,0x03,0x24,0x23,0x30,0x62,0x00,0xf6,0x08,0x00,0x08,0x05,0x00,0xc4,0x24,
-0x40,0x10,0x02,0x00,0xf5,0xff,0x03,0x24,0x0e,0x09,0x00,0x08,0x23,0x30,0x62,0x00,
-0x3e,0x00,0x63,0x30,0x23,0x30,0x43,0x00,0xf6,0x08,0x00,0x08,0x05,0x00,0xc4,0x24,
-0xdd,0xff,0x02,0x24,0x16,0x09,0x00,0x08,0x23,0x30,0x43,0x00,0x40,0x10,0x02,0x00,
-0xe9,0xff,0x03,0x24,0x0e,0x09,0x00,0x08,0x23,0x30,0x62,0x00,0x3e,0x00,0x63,0x30,
-0x16,0x09,0x00,0x08,0x23,0x30,0x43,0x00,0xd2,0xff,0x80,0x14,0x1f,0x00,0x62,0x30,
-0x40,0x10,0x02,0x00,0xf8,0xff,0x03,0x24,0x0e,0x09,0x00,0x08,0x23,0x30,0x62,0x00,
-0xcc,0xff,0x80,0x14,0x3e,0x00,0x63,0x30,0xf8,0xff,0x02,0x24,0x16,0x09,0x00,0x08,
-0x23,0x30,0x43,0x00,0xa0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x4c,0x00,0xb5,0xaf,
-0x5c,0x00,0xbf,0xaf,0x58,0x00,0xbe,0xaf,0x54,0x00,0xb7,0xaf,0x50,0x00,0xb6,0xaf,
-0x48,0x00,0xb4,0xaf,0x44,0x00,0xb3,0xaf,0x40,0x00,0xb2,0xaf,0x3c,0x00,0xb1,0xaf,
-0x38,0x00,0xb0,0xaf,0x68,0x15,0x55,0x24,0x25,0xb0,0x03,0x3c,0x04,0x01,0x62,0x34,
-0x00,0x00,0x43,0x8c,0x44,0x65,0xa7,0x8e,0x00,0x00,0x00,0x00,0x33,0x00,0xe3,0x10,
-0x48,0x65,0xa3,0xae,0x2b,0x10,0x67,0x00,0xa8,0x00,0x40,0x14,0x2b,0x10,0xe3,0x00,
-0xd1,0x00,0x40,0x14,0x02,0x80,0x02,0x3c,0x68,0x15,0x44,0x24,0x18,0x65,0x83,0x94,
-0x02,0x80,0x02,0x3c,0x21,0x88,0x00,0x00,0x19,0x00,0x40,0x1a,0x25,0x98,0x62,0x00,
-0x21,0xb8,0x80,0x00,0x21,0xb0,0x80,0x00,0x01,0x00,0x14,0x24,0x21,0x20,0x00,0x00,
-0x21,0x80,0x93,0x00,0x00,0x00,0x05,0x8e,0x00,0x00,0x00,0x00,0x07,0x00,0xa0,0x10,
-0x01,0x00,0x22,0x26,0x04,0x00,0x02,0x8e,0x00,0xf0,0x03,0x3c,0x00,0x20,0x04,0x3c,
-0x24,0x10,0x43,0x00,0x1e,0x00,0x44,0x10,0x06,0x00,0x22,0x26,0xff,0xff,0x51,0x30,
-0x82,0x16,0x05,0x00,0x01,0x00,0x42,0x30,0x34,0x00,0x54,0x10,0x00,0x00,0x00,0x00,
-0x80,0x20,0x11,0x00,0x2a,0x10,0x92,0x00,0xed,0xff,0x40,0x14,0x00,0x00,0x00,0x00,
-0xbd,0x4e,0x00,0x0c,0x21,0x20,0xc0,0x03,0x02,0x80,0x02,0x3c,0x08,0x04,0x44,0x24,
-0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,0x31,0x1c,0x00,0x0c,0x21,0x38,0x00,0x00,
-0x25,0xb0,0x03,0x3c,0x04,0x01,0x62,0x34,0x00,0x00,0x43,0x8c,0x44,0x65,0xa7,0x8e,
-0x00,0x00,0x00,0x00,0xcf,0xff,0xe3,0x14,0x48,0x65,0xa3,0xae,0x25,0xb0,0x03,0x3c,
-0x00,0x01,0x62,0x34,0x00,0x00,0x47,0xac,0x66,0x09,0x00,0x08,0x44,0x65,0xa7,0xae,
-0xb0,0x4c,0xe2,0x8e,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xb0,0x4c,0xe2,0xae,
-0x0c,0x00,0x04,0x8e,0x0c,0x00,0x02,0x24,0x3f,0x00,0x83,0x30,0x64,0x00,0x62,0x10,
-0x21,0x28,0xe0,0x02,0x3f,0x00,0x83,0x30,0x0d,0x00,0x02,0x24,0x59,0x00,0x62,0x10,
-0x00,0x00,0x00,0x00,0x3f,0x00,0x83,0x30,0x0e,0x00,0x02,0x24,0x04,0x00,0x62,0x10,
-0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x8e,0x5b,0x09,0x00,0x08,0x06,0x00,0x22,0x26,
-0xbc,0x4c,0xe2,0x8e,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xbc,0x4c,0xe2,0xae,
-0x00,0x00,0x05,0x8e,0x5b,0x09,0x00,0x08,0x06,0x00,0x22,0x26,0x00,0x40,0xc2,0x8e,
-0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x0f,0x00,0x42,0x30,0x05,0x00,0x54,0x10,
-0xc2,0x13,0x05,0x00,0x1e,0x00,0x42,0x30,0x21,0x10,0x51,0x00,0x60,0x09,0x00,0x08,
-0xff,0xff,0x51,0x30,0x02,0x40,0xc2,0x92,0x00,0x00,0x00,0x00,0x1e,0x00,0x40,0x14,
-0x02,0x80,0x03,0x3c,0x04,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x02,0x14,0x03,0x00,
-0x0f,0x00,0x42,0x30,0x17,0x00,0x40,0x14,0x02,0x17,0x03,0x00,0x03,0x00,0x44,0x30,
-0x08,0x00,0x80,0x10,0x00,0xc0,0x02,0x3c,0x24,0x10,0x62,0x00,0x11,0x00,0x40,0x14,
-0x03,0x00,0x02,0x24,0x10,0x00,0x82,0x10,0x02,0x80,0x03,0x3c,0x0f,0x00,0x80,0x10,
-0x68,0x15,0x63,0x24,0x80,0x10,0x11,0x00,0x21,0x28,0x53,0x00,0xec,0xff,0xa3,0x8c,
-0x25,0xb0,0x02,0x3c,0xd4,0x02,0x42,0x34,0x21,0x20,0x00,0x02,0x00,0x00,0x43,0xac,
-0xdc,0x08,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x20,0x40,0x00,0x8b,0x08,0x00,0x0c,
-0x21,0x28,0x00,0x00,0x02,0x80,0x03,0x3c,0x68,0x15,0x63,0x24,0x02,0x40,0x62,0x90,
-0x00,0x00,0x00,0x00,0x85,0x00,0x54,0x10,0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,
-0x68,0x15,0x84,0x24,0x02,0x40,0x83,0x90,0x02,0x00,0x02,0x24,0x68,0x00,0x62,0x10,
-0x00,0x00,0x00,0x00,0x25,0xb0,0x03,0x3c,0x4c,0x00,0x63,0x34,0x00,0x00,0x62,0x90,
-0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,0x08,0x00,0x54,0x10,0x02,0x80,0x04,0x3c,
-0x00,0x00,0x05,0x8e,0x00,0x00,0x00,0x00,0xc2,0x13,0x05,0x00,0x1e,0x00,0x42,0x30,
-0x21,0x10,0x51,0x00,0x60,0x09,0x00,0x08,0xff,0xff,0x51,0x30,0xd0,0x02,0x02,0x24,
-0x68,0x15,0x84,0x24,0xdc,0x63,0x82,0xac,0x00,0x00,0x05,0x8e,0xd3,0x09,0x00,0x08,
-0xc2,0x13,0x05,0x00,0xb8,0x4c,0xa2,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,
-0xb8,0x4c,0xa2,0xac,0x0c,0x00,0x04,0x8e,0x86,0x09,0x00,0x08,0x3f,0x00,0x83,0x30,
-0xb4,0x4c,0xe2,0x8e,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xb4,0x4c,0xe2,0xae,
-0x0c,0x00,0x04,0x8e,0x82,0x09,0x00,0x08,0x3f,0x00,0x83,0x30,0x4c,0x65,0xa2,0x8e,
-0xff,0xff,0x71,0x30,0x23,0x10,0x47,0x00,0xff,0xff,0x50,0x30,0x21,0x18,0x11,0x02,
-0xff,0xff,0x72,0x30,0xa1,0x4e,0x00,0x0c,0x21,0x20,0x40,0x02,0x76,0x00,0x40,0x10,
-0x21,0xf0,0x40,0x00,0x08,0x00,0x42,0x8c,0x44,0x65,0xa6,0x8e,0x21,0x38,0x00,0x02,
-0x21,0x18,0x52,0x00,0x21,0x28,0x40,0x00,0x08,0x00,0x04,0x24,0x14,0x65,0xa3,0xae,
-0x18,0x65,0xa2,0xae,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x4d,0x01,0x00,0x0c,
-0x08,0x00,0x04,0x24,0x18,0x65,0xa5,0x8e,0x25,0xb0,0x03,0x3c,0x24,0x10,0x02,0x3c,
-0x21,0x28,0xb0,0x00,0x00,0x01,0x70,0x34,0x00,0x00,0x02,0xae,0x21,0x38,0x20,0x02,
-0x08,0x00,0x04,0x24,0x24,0x10,0x06,0x3c,0x44,0x65,0xa2,0xae,0x10,0x01,0x00,0x0c,
-0x10,0x00,0xa0,0xaf,0x48,0x65,0xa3,0x8e,0x08,0x00,0x04,0x24,0x4d,0x01,0x00,0x0c,
-0x44,0x65,0xa3,0xae,0x44,0x65,0xa2,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xae,
-0x46,0x09,0x00,0x08,0x02,0x80,0x02,0x3c,0x23,0x10,0x67,0x00,0xff,0xff,0x52,0x30,
-0xa1,0x4e,0x00,0x0c,0x21,0x20,0x40,0x02,0x56,0x00,0x40,0x10,0x21,0xf0,0x40,0x00,
-0x08,0x00,0x42,0x8c,0x44,0x65,0xa6,0x8e,0x08,0x00,0x04,0x24,0x21,0x18,0x52,0x00,
-0x21,0x28,0x40,0x00,0x21,0x38,0x40,0x02,0x14,0x65,0xa3,0xae,0x18,0x65,0xa2,0xae,
-0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x48,0x65,0xa3,0x8e,0x08,0x00,0x04,0x24,
-0x4d,0x01,0x00,0x0c,0x44,0x65,0xa3,0xae,0x44,0x65,0xa3,0x8e,0x25,0xb0,0x04,0x3c,
-0x00,0x01,0x82,0x34,0x00,0x00,0x43,0xac,0x46,0x09,0x00,0x08,0x02,0x80,0x02,0x3c,
-0x04,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,0x02,0x14,0x03,0x00,0x0f,0x00,0x42,0x30,
-0x08,0x00,0x42,0x28,0x93,0xff,0x40,0x10,0x02,0x17,0x03,0x00,0x03,0x00,0x42,0x30,
-0x90,0xff,0x40,0x14,0x80,0x10,0x11,0x00,0x21,0x28,0x53,0x00,0xec,0xff,0xa3,0x8c,
-0x25,0xb0,0x02,0x3c,0xd4,0x02,0x42,0x34,0x21,0x20,0x00,0x02,0x00,0x00,0x43,0xac,
-0xdc,0x08,0x00,0x0c,0x00,0x00,0x00,0x00,0x21,0x20,0x40,0x00,0x8b,0x08,0x00,0x0c,
-0x21,0x28,0x00,0x00,0xca,0x09,0x00,0x08,0x25,0xb0,0x03,0x3c,0x04,0x00,0x03,0x8e,
-0x00,0x00,0x00,0x00,0x02,0x14,0x03,0x00,0x0f,0x00,0x42,0x30,0x08,0x00,0x42,0x28,
-0x06,0x00,0x40,0x10,0x00,0xc0,0x02,0x3c,0x02,0x17,0x03,0x00,0x03,0x00,0x42,0x30,
-0x0c,0x00,0x40,0x10,0x80,0x10,0x11,0x00,0x00,0xc0,0x02,0x3c,0x24,0x10,0x62,0x00,
-0x6f,0xff,0x40,0x14,0x02,0x80,0x04,0x3c,0x02,0x17,0x03,0x00,0x03,0x00,0x42,0x30,
-0x03,0x00,0x03,0x24,0x6b,0xff,0x43,0x10,0x68,0x15,0x84,0x24,0x67,0xff,0x40,0x10,
-0x80,0x10,0x11,0x00,0x21,0x28,0x53,0x00,0xec,0xff,0xa3,0x8c,0x25,0xb0,0x02,0x3c,
-0xd4,0x02,0x42,0x34,0x21,0x20,0x00,0x02,0x00,0x00,0x43,0xac,0xdc,0x08,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x21,0x20,0x40,0x00,0x8b,0x08,0x00,0x0c,0x21,0x28,0x00,0x00,
-0xc4,0x09,0x00,0x08,0x02,0x80,0x04,0x3c,0x25,0xb0,0x04,0x3c,0x44,0x44,0x02,0x3c,
-0xbc,0x02,0x83,0x34,0x44,0x44,0x42,0x34,0x00,0x00,0x62,0xac,0x67,0x09,0x00,0x08,
-0x02,0x80,0x02,0x3c,0x48,0x65,0xa5,0x8e,0x25,0xb0,0x04,0x3c,0x66,0x66,0x02,0x3c,
-0x00,0x01,0x83,0x34,0x66,0x66,0x42,0x34,0xbc,0x02,0x84,0x34,0x00,0x00,0x65,0xac,
-0x00,0x00,0x82,0xac,0x66,0x09,0x00,0x08,0x44,0x65,0xa5,0xae,0x00,0x60,0x02,0x40,
-0x01,0x00,0x41,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x02,0x80,0x03,0x3c,
-0xd8,0x8c,0x64,0xac,0x00,0x60,0x82,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x02,0x80,0x02,0x3c,0xd8,0x8c,0x45,0x8c,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
-0x18,0x03,0x42,0x34,0x10,0x2a,0x63,0x24,0x00,0x00,0x43,0xac,0x04,0x00,0x02,0x24,
-0x1e,0x00,0xa2,0x10,0x05,0x00,0xa2,0x2c,0x10,0x00,0x40,0x10,0x05,0x00,0x02,0x24,
-0x03,0x00,0x02,0x24,0x08,0x00,0xa2,0x10,0x00,0x19,0x04,0x00,0x80,0x10,0x04,0x00,
-0x21,0x10,0x44,0x00,0xc0,0x10,0x02,0x00,0x23,0x10,0x44,0x00,0x00,0x11,0x02,0x00,
-0x21,0x10,0x44,0x00,0x40,0x19,0x02,0x00,0xff,0xff,0x63,0x24,0xfe,0xff,0x60,0x14,
-0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xf3,0xff,0xa2,0x10,
-0x06,0x00,0x02,0x24,0xf2,0xff,0xa2,0x14,0x80,0x10,0x04,0x00,0x40,0x11,0x04,0x00,
-0x23,0x10,0x44,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,0x00,0x19,0x02,0x00,
-0x23,0x18,0x62,0x00,0x9a,0x0a,0x00,0x08,0x00,0x19,0x03,0x00,0x80,0x10,0x04,0x00,
-0x21,0x10,0x44,0x00,0xc0,0x10,0x02,0x00,0x23,0x10,0x44,0x00,0x00,0x11,0x02,0x00,
-0x21,0x10,0x44,0x00,0x9a,0x0a,0x00,0x08,0x00,0x19,0x02,0x00,0x02,0x80,0x02,0x3c,
-0xd8,0x8c,0x45,0x8c,0x00,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x18,0x03,0x42,0x34,
-0xcc,0x2a,0x63,0x24,0x00,0x00,0x43,0xac,0x05,0x00,0x02,0x24,0x10,0x00,0xa2,0x10,
-0x06,0x00,0xa2,0x2c,0x09,0x00,0x40,0x14,0x04,0x00,0x02,0x24,0x06,0x00,0x02,0x24,
-0x0f,0x00,0xa2,0x10,0x00,0x11,0x04,0x00,0xff,0xff,0x84,0x24,0xfe,0xff,0x80,0x14,
-0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xfa,0xff,0xa2,0x14,
-0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0xc2,0x0a,0x00,0x08,0x40,0x20,0x02,0x00,
-0x80,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0xc2,0x0a,0x00,0x08,0x80,0x20,0x02,0x00,
-0x23,0x10,0x44,0x00,0xc2,0x0a,0x00,0x08,0x40,0x20,0x02,0x00,0xff,0xff,0x85,0x30,
-0x21,0x30,0x00,0x00,0x25,0xb0,0x03,0x3c,0x2a,0xb0,0x04,0x3c,0xb4,0x00,0x63,0x34,
-0x01,0x00,0xa2,0x24,0x31,0x00,0x84,0x34,0x00,0x00,0x65,0xa0,0x00,0x00,0x85,0xa0,
-0xff,0xff,0x45,0x30,0x12,0x00,0xa0,0x10,0x01,0x00,0x03,0x24,0x28,0xb0,0x07,0x3c,
-0xe8,0x0a,0x00,0x08,0xff,0xff,0x08,0x24,0x00,0x00,0x83,0xa0,0x01,0x00,0x63,0x24,
-0xff,0xff,0x63,0x30,0x2b,0x10,0xa3,0x00,0x09,0x00,0x40,0x14,0x08,0x00,0xc6,0x24,
-0xf9,0xff,0x65,0x14,0x21,0x20,0xc7,0x00,0x01,0x00,0x63,0x24,0xff,0xff,0x63,0x30,
-0x2b,0x10,0xa3,0x00,0x00,0x00,0x88,0xa0,0xf9,0xff,0x40,0x10,0x08,0x00,0xc6,0x24,
-0x00,0x01,0xa2,0x2c,0x13,0x00,0x40,0x10,0x21,0x18,0xa0,0x00,0xff,0x00,0x08,0x24,
-0x28,0xb0,0x07,0x3c,0xfc,0x0a,0x00,0x08,0xff,0xff,0x09,0x24,0xff,0xff,0x43,0x30,
-0x00,0x00,0xa2,0xa0,0x00,0x01,0x62,0x2c,0x0a,0x00,0x40,0x10,0x08,0x00,0xc6,0x24,
-0x01,0x00,0x62,0x24,0xf9,0xff,0x68,0x14,0x21,0x28,0xc7,0x00,0x00,0x01,0x02,0x24,
-0xff,0xff,0x43,0x30,0x00,0x01,0x62,0x2c,0x00,0x00,0xa9,0xa0,0xf8,0xff,0x40,0x14,
-0x08,0x00,0xc6,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xd8,0xff,0xbd,0x27,
-0x24,0x00,0xbf,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,
-0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x10,0x3c,0x42,0x00,0x14,0x36,
-0xff,0xff,0x02,0x24,0x00,0x00,0x82,0xa2,0xd8,0x00,0x05,0x36,0x40,0x00,0x11,0x36,
-0xa8,0x00,0x13,0x36,0xa0,0x00,0x12,0x36,0x00,0x10,0x03,0x24,0xa4,0x00,0x10,0x36,
-0x00,0x80,0x02,0x3c,0x00,0x00,0x23,0xa6,0x00,0x00,0xa0,0xa0,0x00,0x00,0x40,0xae,
-0x00,0x00,0x00,0xae,0x00,0x00,0x62,0xae,0x00,0x00,0xa3,0x90,0x80,0xff,0x02,0x24,
-0xfd,0x00,0x04,0x24,0x25,0x18,0x62,0x00,0xfc,0x17,0x02,0x24,0x00,0x00,0xa3,0xa0,
-0x00,0x00,0x22,0xa6,0xd3,0x0a,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,
-0x68,0x15,0x42,0x24,0x68,0x4b,0x45,0x8c,0x60,0x4b,0x43,0x8c,0x64,0x4b,0x44,0x8c,
-0xfc,0x37,0x02,0x24,0x00,0x00,0x43,0xae,0x00,0x00,0x04,0xae,0x00,0x00,0x65,0xae,
-0x00,0x00,0x22,0xa6,0x00,0x00,0x80,0xa2,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x00,0x60,0x81,0x40,0x24,0x00,0xbf,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,
-0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
-0x28,0x00,0xbd,0x27,0xd0,0xff,0xbd,0x27,0x2c,0x00,0xbf,0xaf,0x28,0x00,0xb6,0xaf,
-0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,
-0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x10,0x3c,0x40,0x00,0x05,0x36,
-0x00,0x00,0xa2,0x94,0x24,0xfa,0x03,0x24,0xa8,0x00,0x13,0x36,0x24,0x10,0x43,0x00,
-0x00,0x00,0xa2,0xa4,0xa0,0x00,0x12,0x36,0xa4,0x00,0x10,0x36,0x00,0x00,0x55,0x8e,
-0x00,0x00,0x16,0x8e,0x00,0x00,0x71,0x8e,0x00,0x80,0x14,0x3c,0xfc,0x37,0x02,0x24,
-0x00,0x00,0x40,0xae,0xfd,0x00,0x04,0x24,0x00,0x00,0x00,0xae,0x21,0x88,0x34,0x02,
-0x00,0x00,0x74,0xae,0x00,0x00,0xa2,0xa4,0xd3,0x0a,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x00,0x00,0x55,0xae,0x00,0x00,0x16,0xae,0x00,0x00,0x71,0xae,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb6,0x8f,
-0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,
-0xd0,0xff,0xbd,0x27,0x2c,0x00,0xbf,0xaf,0x28,0x00,0xb6,0xaf,0x24,0x00,0xb5,0xaf,
-0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,
-0x10,0x00,0xb0,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
-0x00,0x60,0x81,0x40,0x25,0xb0,0x10,0x3c,0x40,0x00,0x05,0x36,0x00,0x00,0xa2,0x94,
-0xaf,0xff,0x03,0x24,0xa8,0x00,0x13,0x36,0x24,0x10,0x43,0x00,0x00,0x00,0xa2,0xa4,
-0xa0,0x00,0x12,0x36,0xa4,0x00,0x10,0x36,0x00,0x00,0x55,0x8e,0x00,0x00,0x16,0x8e,
-0x00,0x00,0x71,0x8e,0x00,0x80,0x14,0x3c,0xfc,0x37,0x02,0x24,0x00,0x00,0x40,0xae,
-0xfd,0x00,0x04,0x24,0x00,0x00,0x00,0xae,0x21,0x88,0x34,0x02,0x00,0x00,0x74,0xae,
-0x00,0x00,0xa2,0xa4,0xd3,0x0a,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x55,0xae,
-0x00,0x00,0x16,0xae,0x00,0x00,0x71,0xae,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x00,0x60,0x81,0x40,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,
-0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x25,0xb0,0x04,0x3c,
-0x40,0x00,0x84,0x34,0x00,0x00,0x82,0x94,0xd8,0xfd,0x03,0x24,0x24,0x10,0x43,0x00,
-0xfc,0x37,0x03,0x24,0x00,0x00,0x82,0xa4,0x00,0x00,0x83,0xa4,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x00,0x00,0x82,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0xff,0xc6,0x30,
-0x10,0x00,0x02,0x24,0x0c,0x00,0xc2,0x10,0x11,0x00,0xc3,0x28,0x06,0x00,0x60,0x10,
-0x20,0x00,0x02,0x24,0x08,0x00,0x02,0x24,0x0d,0x00,0xc2,0x10,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x06,0x00,0xc2,0x10,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xa4,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x00,0x00,0x85,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x25,0xb0,0x02,0x3c,
-0x0a,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0xff,0xff,0xa5,0x24,0x00,0x2c,0x05,0x00,
-0xfd,0x00,0x63,0x30,0x03,0x2c,0x05,0x00,0xff,0xff,0x87,0x30,0x00,0x00,0x43,0xa0,
-0x1a,0x00,0xa0,0x04,0x00,0x00,0x00,0x00,0x21,0x30,0x40,0x00,0x07,0x10,0xa7,0x00,
-0x01,0x00,0x42,0x30,0xfd,0x00,0x64,0x30,0x00,0x00,0x42,0x38,0x02,0x00,0x63,0x34,
-0x0a,0x18,0x82,0x00,0x00,0x00,0xc3,0xa0,0x04,0x00,0x63,0x34,0x00,0x00,0xc3,0xa0,
-0x09,0x00,0x02,0x24,0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,
-0xfb,0x00,0x63,0x30,0x00,0x00,0xc3,0xa0,0x04,0x00,0x02,0x24,0xff,0xff,0x42,0x24,
-0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0xff,0xff,0xa2,0x24,0x00,0x2c,0x02,0x00,
-0x03,0x2c,0x05,0x00,0xea,0xff,0xa1,0x04,0x07,0x10,0xa7,0x00,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0x0a,0x00,0x42,0x34,0x00,0x00,0x43,0x90,
-0xff,0xff,0x84,0x24,0x00,0x24,0x04,0x00,0x03,0x24,0x04,0x00,0xff,0x00,0x65,0x30,
-0x1d,0x00,0x80,0x04,0x21,0x38,0x00,0x00,0x21,0x30,0x40,0x00,0x01,0x00,0x08,0x24,
-0x04,0x00,0xa5,0x34,0x00,0x00,0xc5,0xa0,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,
-0xff,0x00,0x45,0x30,0x01,0x00,0xa3,0x30,0x05,0x00,0x60,0x10,0x04,0x00,0x02,0x24,
-0x04,0x10,0x88,0x00,0x25,0x10,0x47,0x00,0xff,0xff,0x47,0x30,0x04,0x00,0x02,0x24,
-0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0xfb,0x00,0xa5,0x30,
-0x00,0x00,0xc5,0xa0,0x09,0x00,0x02,0x24,0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,
-0xff,0xff,0x42,0x24,0xff,0xff,0x82,0x24,0x00,0x24,0x02,0x00,0x03,0x24,0x04,0x00,
-0xe7,0xff,0x81,0x04,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0xe0,0x00,
-0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x25,0xb0,0x10,0x3c,0x0a,0x00,0x10,0x36,
-0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x00,0x00,0x02,0x92,0xff,0xff,0x91,0x30,
-0x03,0x00,0x05,0x24,0xc0,0x00,0x42,0x30,0x80,0x00,0x43,0x34,0x00,0x00,0x03,0xa2,
-0x04,0x00,0x63,0x34,0x00,0x00,0x03,0xa2,0xfb,0x00,0x63,0x30,0x00,0x00,0x03,0xa2,
-0x08,0x00,0x63,0x34,0x00,0x00,0x03,0xa2,0x04,0x00,0x63,0x34,0x00,0x00,0x03,0xa2,
-0xfb,0x00,0x63,0x30,0x00,0x00,0x03,0xa2,0xd7,0x0b,0x00,0x0c,0x06,0x00,0x04,0x24,
-0x42,0x20,0x11,0x00,0xd7,0x0b,0x00,0x0c,0x06,0x00,0x05,0x24,0xfd,0x0b,0x00,0x0c,
-0x10,0x00,0x04,0x24,0x00,0x00,0x03,0x92,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,
-0xc0,0x00,0x63,0x30,0x00,0x00,0x03,0xa2,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
-0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0xff,0xff,0xb1,0x30,
-0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x1c,0x00,0xbf,0xaf,0x21,0x90,0xc0,0x00,
-0x0a,0x00,0x20,0x12,0xff,0xff,0x90,0x30,0x24,0x0c,0x00,0x0c,0x21,0x20,0x00,0x02,
-0xfe,0xff,0x23,0x26,0x02,0x00,0x04,0x26,0x00,0x00,0x42,0xa6,0xff,0xff,0x71,0x30,
-0xff,0xff,0x90,0x30,0xf8,0xff,0x20,0x16,0x02,0x00,0x52,0x26,0x1c,0x00,0xbf,0x8f,
-0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
-0x20,0x00,0xbd,0x27,0x25,0xb0,0x03,0x3c,0x0a,0x00,0x68,0x34,0x00,0x00,0x02,0x91,
-0xff,0xff,0xa5,0x30,0xff,0x00,0x84,0x30,0x1f,0x00,0xa0,0x10,0xff,0x00,0x47,0x30,
-0x21,0x48,0x00,0x01,0x0c,0x00,0x6c,0x34,0x0b,0x00,0x6b,0x34,0xc0,0xff,0x0a,0x24,
-0x21,0x68,0x00,0x01,0x25,0x10,0xea,0x00,0xff,0x00,0x47,0x30,0x00,0x00,0x64,0xa1,
-0x00,0x00,0x27,0xa1,0x00,0x00,0x22,0x91,0x00,0x00,0x00,0x00,0xff,0x00,0x47,0x30,
-0xc0,0x00,0xe3,0x30,0x08,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x21,0x40,0xa0,0x01,
-0x00,0x00,0x02,0x91,0x00,0x00,0x00,0x00,0xff,0x00,0x47,0x30,0xc0,0x00,0xe3,0x30,
-0xfb,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0x8d,0xfc,0xff,0xa3,0x24,
-0x04,0x00,0x84,0x24,0xff,0xff,0x65,0x30,0x00,0x00,0xc2,0xac,0xff,0x00,0x84,0x30,
-0xe8,0xff,0xa0,0x14,0x04,0x00,0xc6,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0xff,0x00,0x84,0x30,0x21,0x68,0xe0,0x00,0xff,0xff,0xa5,0x30,0xc0,0x50,0x04,0x00,
-0x00,0x60,0x0c,0x40,0x01,0x00,0x81,0x35,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x00,0x00,0xc2,0x90,0x01,0x00,0xc3,0x90,0x25,0xb0,0x07,0x3c,0x00,0x14,0x02,0x00,
-0x25,0x28,0xa2,0x00,0x00,0x1e,0x03,0x00,0x01,0x80,0x08,0x3c,0x25,0x20,0xa3,0x00,
-0x40,0x02,0xe9,0x34,0x25,0x18,0x48,0x01,0x44,0x02,0xe7,0x34,0x00,0x00,0xe4,0xac,
-0x00,0x00,0x23,0xad,0x03,0x00,0xc2,0x90,0x02,0x00,0xc4,0x90,0x04,0x00,0xc3,0x90,
-0x05,0x00,0xc5,0x90,0x00,0x12,0x02,0x00,0x25,0x20,0x82,0x00,0x00,0x1c,0x03,0x00,
-0x01,0x00,0x4a,0x25,0x25,0x20,0x83,0x00,0x00,0x2e,0x05,0x00,0x25,0x40,0x48,0x01,
-0x25,0x20,0x85,0x00,0x00,0x00,0xe4,0xac,0x01,0x00,0x4a,0x25,0x00,0x00,0x28,0xad,
-0x01,0x80,0x0b,0x3c,0x21,0x40,0x00,0x00,0x21,0x10,0xa8,0x01,0x01,0x00,0x43,0x90,
-0x00,0x00,0x45,0x90,0x02,0x00,0x44,0x90,0x03,0x00,0x46,0x90,0x00,0x1a,0x03,0x00,
-0x25,0x28,0xa3,0x00,0x00,0x24,0x04,0x00,0x25,0x28,0xa4,0x00,0x00,0x36,0x06,0x00,
-0x04,0x00,0x08,0x25,0x25,0x10,0x4b,0x01,0x25,0x20,0xa6,0x00,0x10,0x00,0x03,0x2d,
-0x00,0x00,0xe4,0xac,0x01,0x00,0x4a,0x25,0x00,0x00,0x22,0xad,0xee,0xff,0x60,0x14,
-0x00,0x00,0x00,0x00,0x00,0x60,0x8c,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0xff,0xff,0x84,0x30,0x42,0xb0,0x08,0x3c,0x80,0x10,0x04,0x00,0x21,0x10,0x48,0x00,
-0x04,0x00,0x46,0xac,0x00,0x00,0x07,0x91,0x40,0x18,0x04,0x00,0x03,0x00,0x06,0x24,
-0xff,0x00,0xe7,0x30,0x04,0x30,0x66,0x00,0x01,0x00,0x02,0x24,0x04,0x10,0x62,0x00,
-0x25,0x30,0xc7,0x00,0xff,0xff,0xa5,0x30,0x25,0x10,0x47,0x00,0x02,0x00,0xa0,0x14,
-0xff,0x00,0xc7,0x30,0xff,0x00,0x47,0x30,0x42,0xb0,0x02,0x3c,0x00,0x00,0x47,0xa0,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x42,0xb0,0x02,0x3c,0x03,0x00,0x47,0x34,
-0x00,0x00,0xe3,0x90,0xff,0x00,0x84,0x30,0x04,0x00,0x84,0x24,0xff,0x00,0x65,0x30,
-0x01,0x00,0x02,0x24,0x04,0x30,0x82,0x00,0x07,0x18,0x85,0x00,0x25,0xb0,0x02,0x3c,
-0xe8,0x03,0x42,0x34,0x01,0x00,0x63,0x30,0x21,0x20,0xc0,0x00,0x00,0x00,0x45,0xa0,
-0x02,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xe6,0xa0,0x08,0x00,0xe0,0x03,
-0x24,0x10,0x85,0x00,0x00,0x60,0x03,0x40,0x01,0x00,0x61,0x34,0x01,0x00,0x21,0x38,
-0x00,0x60,0x81,0x40,0x02,0x80,0x02,0x3c,0xdc,0x8c,0x42,0x24,0x04,0x00,0x45,0x8c,
-0x00,0x00,0x82,0xac,0x04,0x00,0x44,0xac,0x00,0x00,0xa4,0xac,0x04,0x00,0x85,0xac,
-0x00,0x60,0x83,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x14,0x00,0x83,0x90,
-0x01,0x00,0x02,0x24,0x08,0x00,0x86,0xac,0x18,0x00,0x85,0xac,0x00,0x00,0x84,0xac,
-0x03,0x00,0x62,0x10,0x04,0x00,0x84,0xac,0xed,0x0c,0x00,0x08,0x0c,0x00,0x80,0xac,
-0x0c,0x00,0x82,0x8c,0xed,0x0c,0x00,0x08,0x10,0x00,0x82,0xac,0x00,0x60,0x03,0x40,
-0x01,0x00,0x61,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x04,0x00,0x85,0x8c,
-0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xac,0x04,0x00,0x45,0xac,
-0x00,0x00,0x84,0xac,0x04,0x00,0x84,0xac,0x00,0x60,0x83,0x40,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0xd0,0xff,0xbd,0x27,0x28,0x00,0xb6,0xaf,0x24,0x00,0xb5,0xaf,
-0x20,0x00,0xb4,0xaf,0x14,0x00,0xb1,0xaf,0x2c,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf,
-0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x80,0x16,0x3c,0x02,0x80,0x14,0x3c,
-0x02,0x80,0x11,0x3c,0x02,0x80,0x15,0x3c,0xc4,0x7d,0x24,0x8e,0x25,0xb0,0x02,0x3c,
-0x54,0x34,0xc3,0x26,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0xdc,0x8c,0x90,0x8e,
-0x18,0x00,0x80,0x10,0xdc,0x8c,0x82,0x26,0x15,0x00,0x02,0x12,0x00,0x00,0x00,0x00,
-0x21,0x98,0x40,0x00,0x01,0x00,0x12,0x24,0x14,0x00,0x02,0x92,0x00,0x00,0x00,0x00,
-0x1d,0x00,0x52,0x10,0x00,0x00,0x00,0x00,0x09,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
-0x0c,0x00,0x03,0x8e,0xc4,0x7d,0x22,0x8e,0x00,0x00,0x00,0x00,0x23,0x20,0x62,0x00,
-0x2b,0x10,0x43,0x00,0x0e,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x0c,0x00,0x04,0xae,
-0x00,0x00,0x10,0x8e,0x00,0x00,0x00,0x00,0xef,0xff,0x13,0x16,0x00,0x00,0x00,0x00,
-0xc4,0x7d,0x20,0xae,0x08,0x0c,0xa4,0x26,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,
-0x31,0x1c,0x00,0x0c,0x21,0x38,0x00,0x00,0x22,0x0d,0x00,0x08,0x00,0x00,0x00,0x00,
-0x08,0x00,0x02,0x8e,0x18,0x00,0x04,0x8e,0x09,0xf8,0x40,0x00,0x00,0x00,0x00,0x00,
-0x3c,0x0d,0x00,0x08,0x0c,0x00,0x02,0xae,0x0c,0x00,0x03,0x8e,0xc4,0x7d,0x22,0x8e,
-0x00,0x00,0x00,0x00,0x23,0x20,0x62,0x00,0x2b,0x10,0x43,0x00,0xe7,0xff,0x40,0x14,
-0x00,0x00,0x00,0x00,0x08,0x00,0x02,0x8e,0x18,0x00,0x04,0x8e,0x09,0xf8,0x40,0x00,
-0x00,0x00,0x00,0x00,0x10,0x00,0x03,0x8e,0x3c,0x0d,0x00,0x08,0x0c,0x00,0x03,0xae,
-0xff,0x00,0xa5,0x30,0x25,0xb0,0x02,0x3c,0x21,0x28,0xa2,0x00,0xff,0x00,0x84,0x30,
-0x60,0x01,0xa4,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0x00,0x84,0x30,
-0x01,0x00,0x03,0x24,0x10,0x00,0x02,0x3c,0x04,0x18,0x83,0x00,0xf0,0x70,0x42,0x34,
-0x15,0x00,0x84,0x2c,0x06,0x00,0x80,0x10,0x24,0x28,0x62,0x00,0x0f,0x00,0x63,0x30,
-0x04,0x00,0xa0,0x14,0x01,0x00,0x02,0x24,0x02,0x00,0x60,0x14,0x02,0x00,0x02,0x24,
-0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0x00,0xa5,0x30,
-0x04,0x00,0xa2,0x2c,0x14,0x00,0x40,0x10,0xff,0x00,0x84,0x30,0x02,0x80,0x03,0x3c,
-0x8e,0x7d,0x62,0x90,0x00,0x00,0x00,0x00,0xef,0xff,0x42,0x24,0xff,0x00,0x42,0x30,
-0x02,0x00,0x42,0x2c,0x0e,0x00,0x40,0x10,0x02,0x00,0x03,0x24,0x24,0x00,0x83,0x10,
-0x0f,0x10,0x02,0x3c,0x03,0x00,0x82,0x28,0x14,0x00,0x40,0x10,0x03,0x00,0x02,0x24,
-0x01,0x00,0x02,0x24,0x2f,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0xff,0x1f,0x02,0x3c,
-0x08,0x00,0xe0,0x03,0xff,0xff,0x42,0x34,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x35,0x00,0x83,0x10,0x0f,0x1f,0x02,0x3c,0x03,0x00,0x82,0x28,0x16,0x00,0x40,0x10,
-0x03,0x00,0x02,0x24,0x01,0x00,0x02,0x24,0xf4,0xff,0x82,0x14,0x00,0x00,0x00,0x00,
-0x0f,0x1f,0x02,0x3c,0x08,0x00,0xe0,0x03,0x00,0x80,0x42,0x34,0xf0,0xff,0x82,0x14,
-0xff,0x1f,0x02,0x3c,0x01,0x00,0x02,0x24,0x29,0x00,0xa2,0x10,0x0f,0x10,0x02,0x3c,
-0x02,0x00,0xa2,0x28,0x1f,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x28,0x00,0xa3,0x10,
-0x00,0x00,0x00,0x00,0xe5,0xff,0xa4,0x14,0x00,0x00,0x00,0x00,0x0f,0x10,0x02,0x3c,
-0x08,0x00,0xe0,0x03,0x00,0xf0,0x42,0x34,0xe1,0xff,0x82,0x14,0xff,0x1f,0x02,0x3c,
-0x01,0x00,0x02,0x24,0x1c,0x00,0xa2,0x10,0x0f,0x00,0x02,0x3c,0x02,0x00,0xa2,0x28,
-0x0b,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x1c,0x00,0xa3,0x10,0x00,0x00,0x00,0x00,
-0xd6,0xff,0xa4,0x14,0x00,0x00,0x00,0x00,0x0f,0x00,0x02,0x3c,0x08,0x00,0xe0,0x03,
-0x00,0xf0,0x42,0x34,0x0f,0x10,0x02,0x3c,0x08,0x00,0xe0,0x03,0x00,0x80,0x42,0x34,
-0xce,0xff,0xa0,0x14,0x00,0x00,0x00,0x00,0x0f,0x00,0x02,0x3c,0x08,0x00,0xe0,0x03,
-0x15,0xf0,0x42,0x34,0xc9,0xff,0xa0,0x14,0x00,0x00,0x00,0x00,0x0f,0x10,0x02,0x3c,
-0x08,0x00,0xe0,0x03,0x15,0xf0,0x42,0x34,0x08,0x00,0xe0,0x03,0x00,0xf0,0x42,0x34,
-0x08,0x00,0xe0,0x03,0x10,0xf0,0x42,0x34,0x08,0x00,0xe0,0x03,0x10,0xf0,0x42,0x34,
-0x0f,0x10,0x02,0x3c,0x08,0x00,0xe0,0x03,0x05,0xf0,0x42,0x34,0x0f,0x00,0x02,0x3c,
-0x08,0x00,0xe0,0x03,0x05,0xf0,0x42,0x34,0xc0,0x40,0x04,0x00,0x21,0x18,0x04,0x01,
-0x80,0x18,0x03,0x00,0x21,0x18,0x64,0x00,0x02,0x80,0x02,0x3c,0x80,0x18,0x03,0x00,
-0x68,0x15,0x42,0x24,0x21,0x18,0x62,0x00,0x74,0x51,0x66,0x8c,0x21,0x38,0x60,0x00,
-0x7a,0x51,0x60,0xa0,0x7b,0x51,0x60,0xa0,0x1c,0x00,0x05,0x24,0xdf,0x0d,0x00,0x08,
-0x01,0x00,0x03,0x24,0x08,0x00,0xa0,0x04,0x21,0x10,0x04,0x01,0x04,0x10,0xa3,0x00,
-0x24,0x10,0xc2,0x00,0xfb,0xff,0x40,0x10,0xff,0xff,0xa5,0x24,0x01,0x00,0xa5,0x24,
-0x7a,0x51,0xe5,0xa0,0x21,0x10,0x04,0x01,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,
-0x02,0x80,0x03,0x3c,0x80,0x10,0x02,0x00,0x68,0x15,0x63,0x24,0x21,0x18,0x43,0x00,
-0x74,0x51,0x66,0x8c,0x21,0x28,0x00,0x00,0xf3,0x0d,0x00,0x08,0x01,0x00,0x07,0x24,
-0x1d,0x00,0xa2,0x28,0x08,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x04,0x10,0xa7,0x00,
-0x24,0x10,0xc2,0x00,0xfa,0xff,0x40,0x10,0x01,0x00,0xa5,0x24,0xff,0xff,0xa5,0x24,
-0x08,0x00,0xe0,0x03,0x7b,0x51,0x65,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0xc8,0xff,0xbd,0x27,0x28,0x00,0xb6,0xaf,0x02,0x80,0x16,0x3c,0x30,0x00,0xbe,0xaf,
-0x2c,0x00,0xb7,0xaf,0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x18,0x00,0xb2,0xaf,
-0x14,0x00,0xb1,0xaf,0x01,0x00,0x15,0x24,0x21,0x88,0x00,0x00,0x68,0x15,0xde,0x26,
-0x21,0xa0,0x00,0x00,0x21,0x90,0x00,0x00,0x25,0xb0,0x17,0x3c,0x34,0x00,0xbf,0xaf,
-0x1c,0x00,0xb3,0xaf,0x14,0x0e,0x00,0x08,0x10,0x00,0xb0,0xaf,0x01,0x00,0x31,0x26,
-0x20,0x00,0x22,0x2e,0x94,0x00,0x52,0x26,0x2e,0x00,0x40,0x10,0x94,0x00,0x94,0x26,
-0x68,0x15,0xc2,0x26,0x21,0x30,0x42,0x02,0x78,0x51,0xc5,0x8c,0x00,0x00,0x00,0x00,
-0x02,0x13,0x05,0x00,0x01,0x00,0x42,0x30,0xf4,0xff,0x55,0x14,0x42,0x1a,0x05,0x00,
-0x68,0x51,0xc2,0x8c,0x07,0x00,0x64,0x30,0x02,0x11,0x02,0x00,0x7f,0x00,0x43,0x30,
-0x2d,0x00,0x95,0x10,0x07,0x00,0xb3,0x30,0x02,0x00,0x82,0x28,0x3a,0x00,0x40,0x14,
-0x02,0x00,0x02,0x24,0x30,0x00,0x82,0x10,0x03,0x00,0x02,0x24,0x3c,0x00,0x82,0x10,
-0x1a,0x00,0x62,0x2c,0x21,0x80,0x9e,0x02,0x78,0x51,0x02,0x8e,0x04,0x00,0x63,0x2e,
-0x42,0x12,0x02,0x00,0x0a,0x00,0x60,0x10,0x07,0x00,0x44,0x30,0x73,0x0d,0x00,0x0c,
-0x21,0x28,0x60,0x02,0x80,0x20,0x13,0x00,0x70,0x51,0x02,0xae,0x21,0x20,0x97,0x00,
-0x84,0x01,0x83,0x8c,0x00,0x00,0x00,0x00,0x24,0x18,0x62,0x00,0x74,0x51,0x03,0xae,
-0xce,0x0d,0x00,0x0c,0x21,0x20,0x20,0x02,0x21,0x10,0x37,0x02,0x01,0x00,0x31,0x26,
-0x60,0x01,0x43,0x90,0x20,0x00,0x22,0x2e,0x94,0x00,0x52,0x26,0xd4,0xff,0x40,0x14,
-0x94,0x00,0x94,0x26,0x34,0x00,0xbf,0x8f,0x30,0x00,0xbe,0x8f,0x2c,0x00,0xb7,0x8f,
-0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,
-0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x32,0x00,0x62,0x2c,0xda,0xff,0x40,0x10,
-0x21,0x80,0x9e,0x02,0xff,0xf1,0x03,0x24,0x24,0x10,0xa3,0x00,0x00,0x04,0x42,0x34,
-0x29,0x0e,0x00,0x08,0x78,0x51,0xc2,0xac,0x38,0x00,0x62,0x2c,0x12,0x00,0x40,0x14,
-0x14,0x00,0x62,0x2c,0xff,0xf1,0x03,0x24,0x24,0x10,0xa3,0x00,0x00,0x02,0x42,0x34,
-0x29,0x0e,0x00,0x08,0x78,0x51,0xc2,0xac,0xcb,0xff,0x80,0x14,0x21,0x80,0x9e,0x02,
-0xff,0xf1,0x03,0x24,0x24,0x10,0xa3,0x00,0x2a,0x0e,0x00,0x08,0x78,0x51,0xc2,0xac,
-0xc5,0xff,0x40,0x14,0x21,0x80,0x9e,0x02,0xff,0xf1,0x03,0x24,0x24,0x10,0xa3,0x00,
-0x54,0x0e,0x00,0x08,0x00,0x04,0x42,0x34,0xbf,0xff,0x40,0x10,0x21,0x80,0x9e,0x02,
-0xff,0xf1,0x03,0x24,0x24,0x10,0xa3,0x00,0x00,0x06,0x42,0x34,0x2a,0x0e,0x00,0x08,
-0x78,0x51,0xc2,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xd8,0xff,0xbd,0x27,
-0x10,0x00,0xb0,0xaf,0xc0,0x80,0x04,0x00,0x21,0x80,0x04,0x02,0x80,0x80,0x10,0x00,
-0x21,0x80,0x04,0x02,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0x80,0x80,0x10,0x00,
-0x20,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x21,0x80,0x02,0x02,
-0x14,0x00,0xb1,0xaf,0x78,0x51,0x03,0x8e,0x25,0xb0,0x02,0x3c,0x80,0x01,0x53,0x34,
-0x07,0x00,0x63,0x30,0x80,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x00,0x00,0x71,0x92,
-0x70,0x51,0x05,0x8e,0x84,0x01,0x62,0x8c,0x21,0x90,0x80,0x00,0xff,0x00,0x31,0x32,
-0x24,0x10,0x45,0x00,0xce,0x0d,0x00,0x0c,0x74,0x51,0x02,0xae,0x7a,0x51,0x04,0x92,
-0x5c,0x0d,0x00,0x0c,0xff,0x00,0x45,0x32,0x7a,0x51,0x04,0x92,0x63,0x0d,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24,0x0a,0x88,0x62,0x00,
-0x00,0x00,0x71,0xa2,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,
-0xff,0xff,0x84,0x30,0x00,0x02,0x82,0x30,0x07,0x00,0x03,0x24,0x0d,0x00,0x40,0x14,
-0x0b,0x00,0x84,0x30,0x0c,0x00,0x82,0x2c,0x0a,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
-0x02,0x80,0x03,0x3c,0x80,0x10,0x04,0x00,0xf0,0x91,0x63,0x24,0x21,0x10,0x43,0x00,
-0x00,0x00,0x44,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,
-0x07,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x06,0x00,0x03,0x24,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x05,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,
-0x21,0x10,0x60,0x00,0x04,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
-0x03,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x02,0x00,0x03,0x24,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0x01,0x00,0x03,0x24,0x08,0x00,0xe0,0x03,
-0x21,0x10,0x60,0x00,0x21,0x18,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
-0xa0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x58,0x00,0xbe,0xaf,0x54,0x00,0xb7,0xaf,
-0x50,0x00,0xb6,0xaf,0x4c,0x00,0xb5,0xaf,0x48,0x00,0xb4,0xaf,0x40,0x00,0xb2,0xaf,
-0x3c,0x00,0xb1,0xaf,0x5c,0x00,0xbf,0xaf,0x44,0x00,0xb3,0xaf,0x38,0x00,0xb0,0xaf,
-0x20,0x92,0x42,0x24,0x00,0x00,0x53,0x8c,0x08,0x00,0x03,0x24,0x02,0x80,0x0b,0x3c,
-0x21,0x90,0x00,0x00,0x21,0xa0,0x00,0x00,0x21,0xb8,0x00,0x00,0x21,0xf0,0x00,0x00,
-0x21,0xa8,0x00,0x00,0x21,0xb0,0x00,0x00,0x21,0x88,0x60,0x02,0x10,0x00,0xa3,0xaf,
-0x14,0x00,0xa0,0xaf,0x18,0x00,0xa0,0xaf,0x1c,0x00,0xa0,0xaf,0x20,0x00,0xa0,0xaf,
-0x24,0x00,0xa0,0xaf,0x28,0x00,0xa0,0xaf,0x7a,0x0f,0x00,0x08,0x2c,0x00,0xa0,0xaf,
-0x44,0x51,0x22,0xae,0x60,0x51,0x24,0x8e,0x5c,0x51,0x27,0x8e,0x48,0x51,0x28,0x8e,
-0x4c,0x51,0x25,0x8e,0x54,0x51,0x26,0x8e,0x58,0x51,0x23,0x8e,0x21,0x38,0xe4,0x00,
-0x02,0x80,0x04,0x3c,0x68,0x15,0x84,0x24,0x21,0x10,0x04,0x02,0x21,0x40,0x05,0x01,
-0x21,0x30,0xc3,0x00,0xca,0x44,0x42,0x90,0x44,0x51,0x2a,0x8e,0x0c,0x00,0xe0,0x10,
-0x21,0x48,0x00,0x00,0x2b,0x48,0x47,0x00,0x0b,0x00,0x20,0x15,0x02,0x80,0x02,0x3c,
-0x07,0x00,0x02,0x2e,0x59,0x01,0x40,0x14,0xc0,0x10,0x07,0x00,0x0c,0x00,0x02,0x24,
-0x55,0x01,0x02,0x12,0x0d,0x00,0x02,0x24,0x54,0x01,0x02,0x12,0xc0,0x10,0x07,0x00,
-0x92,0x00,0x20,0x11,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0x80,0x18,0x10,0x00,
-0x21,0x18,0x62,0x00,0x21,0x20,0x30,0x02,0xb6,0x51,0x85,0x90,0xec,0x44,0x62,0x8c,
-0x00,0x00,0x00,0x00,0x04,0x10,0xa2,0x00,0x2b,0x10,0x4a,0x00,0x87,0x00,0x40,0x10,
-0x00,0x00,0x00,0x00,0xd4,0x51,0x22,0x8e,0x01,0x00,0x07,0x24,0x04,0x18,0x07,0x02,
-0x24,0x10,0x43,0x00,0xf0,0x00,0x40,0x10,0x1c,0x00,0x02,0x2e,0x21,0x28,0x30,0x02,
-0x7c,0x51,0xa6,0x90,0xb6,0x51,0xa2,0x90,0x0a,0x00,0x04,0x24,0xff,0x00,0xc3,0x30,
-0x04,0x20,0x44,0x00,0x2a,0x18,0x64,0x00,0xe7,0x00,0x60,0x10,0x1c,0x00,0x02,0x2e,
-0x01,0x00,0xc2,0x24,0xff,0x00,0x43,0x30,0x56,0x01,0x64,0x10,0x7c,0x51,0xa2,0xa0,
-0x68,0x15,0x65,0x25,0x80,0x10,0x10,0x00,0x21,0x10,0x45,0x00,0x60,0x45,0x44,0x8c,
-0xec,0x44,0x43,0x8c,0x21,0x30,0xc5,0x02,0x40,0x10,0x04,0x00,0x21,0x10,0x44,0x00,
-0x21,0x18,0x62,0x00,0x82,0x50,0x03,0x00,0x44,0x51,0xca,0xac,0x8c,0x65,0xa3,0x8c,
-0xff,0xff,0x02,0x34,0x07,0x00,0x62,0x10,0x21,0x20,0x00,0x02,0x21,0x20,0x00,0x02,
-0xff,0x00,0x45,0x32,0x5c,0x0d,0x00,0x0c,0x30,0x00,0xab,0xaf,0x30,0x00,0xab,0x8f,
-0x21,0x20,0x00,0x02,0x63,0x0d,0x00,0x0c,0x30,0x00,0xab,0xaf,0x10,0x00,0xa4,0x8f,
-0x01,0x00,0x42,0x38,0x04,0x00,0x03,0x24,0x0a,0x20,0x62,0x00,0x10,0x00,0xa4,0xaf,
-0x30,0x00,0xab,0x8f,0x11,0x00,0x40,0x16,0x68,0x15,0x62,0x25,0x58,0x51,0x47,0x8c,
-0x54,0x51,0x43,0x8c,0x4c,0x51,0x44,0x94,0x48,0x51,0x45,0x94,0x50,0x51,0x46,0x94,
-0x21,0x18,0x67,0x00,0x00,0x24,0x04,0x00,0x25,0xb0,0x02,0x3c,0x00,0x1c,0x03,0x00,
-0x21,0x28,0xa4,0x00,0x21,0x30,0xc3,0x00,0x6c,0x0c,0x44,0x34,0x68,0x0c,0x42,0x34,
-0x00,0x00,0x45,0xac,0x00,0x00,0x86,0xac,0x68,0x15,0x62,0x25,0x21,0x10,0x82,0x02,
-0x58,0x51,0x40,0xac,0x5c,0x51,0x40,0xac,0x60,0x51,0x40,0xac,0x48,0x51,0x40,0xac,
-0x4c,0x51,0x40,0xac,0x50,0x51,0x40,0xac,0x54,0x51,0x40,0xac,0x2c,0x00,0xa2,0x8f,
-0x28,0x00,0xa4,0x8f,0x01,0x00,0x52,0x26,0x94,0x00,0x42,0x24,0x2c,0x00,0xa2,0xaf,
-0x24,0x00,0xa2,0x8f,0x94,0x00,0x84,0x24,0x28,0x00,0xa4,0xaf,0x94,0x00,0x42,0x24,
-0x20,0x00,0xa4,0x8f,0x24,0x00,0xa2,0xaf,0x1c,0x00,0xa2,0x8f,0x94,0x00,0x84,0x24,
-0x20,0x00,0xa4,0xaf,0x94,0x00,0x42,0x24,0x18,0x00,0xa4,0x8f,0x1c,0x00,0xa2,0xaf,
-0x14,0x00,0xa2,0x8f,0x94,0x00,0x84,0x24,0x20,0x00,0x43,0x2a,0x94,0x00,0x42,0x24,
-0x94,0x00,0x31,0x26,0x94,0x00,0xd6,0x26,0x94,0x00,0xb5,0x26,0x18,0x00,0xa4,0xaf,
-0x14,0x00,0xa2,0xaf,0x94,0x00,0xde,0x27,0x94,0x00,0x73,0x26,0x94,0x00,0xf7,0x26,
-0xe5,0x00,0x60,0x10,0x94,0x00,0x94,0x26,0x78,0x51,0x22,0x8e,0x00,0x00,0x00,0x00,
-0x02,0x13,0x02,0x00,0x01,0x00,0x42,0x30,0xd3,0xff,0x40,0x10,0x25,0xb0,0x02,0x3c,
-0x21,0x10,0x42,0x02,0x60,0x01,0x44,0x90,0x60,0x51,0x23,0x8e,0x5c,0x51,0x26,0x8e,
-0xff,0x00,0x90,0x30,0x02,0x80,0x04,0x3c,0x68,0x15,0x84,0x24,0x21,0x10,0x04,0x02,
-0x73,0x44,0x44,0x90,0x56,0x44,0x45,0x90,0x44,0x51,0x27,0x8e,0x18,0x00,0x64,0x00,
-0x12,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0xc5,0x00,
-0x12,0x30,0x00,0x00,0x21,0x30,0xc3,0x00,0x2b,0x10,0xe6,0x00,0x54,0xff,0x40,0x10,
-0x23,0x10,0xe6,0x00,0xe9,0x0e,0x00,0x08,0x44,0x51,0x20,0xae,0x62,0x00,0xe0,0x10,
-0x00,0x00,0x00,0x00,0x63,0x00,0x20,0x15,0x68,0x15,0x62,0x25,0x40,0x10,0x07,0x00,
-0x21,0x10,0x47,0x00,0x82,0x10,0x02,0x00,0x2b,0x10,0x46,0x00,0x99,0xff,0x40,0x10,
-0x21,0x20,0x00,0x02,0x68,0x15,0x68,0x25,0x21,0x20,0xa8,0x02,0x21,0x30,0x90,0x00,
-0xd4,0x51,0x83,0x8c,0x01,0x00,0x05,0x24,0x04,0x10,0x05,0x02,0x99,0x51,0xc7,0x90,
-0x27,0x10,0x02,0x00,0x24,0x18,0x62,0x00,0xd4,0x51,0x83,0xac,0x09,0x00,0xe5,0x10,
-0x7c,0x51,0xc0,0xa0,0x18,0x00,0xa2,0x8f,0x21,0x38,0x00,0x00,0x21,0x20,0x48,0x00,
-0x21,0x18,0x87,0x00,0x01,0x00,0xe7,0x24,0x1d,0x00,0xe2,0x28,0xfc,0xff,0x40,0x14,
-0xb6,0x51,0x60,0xa0,0x14,0x00,0xa4,0x8f,0x68,0x15,0x63,0x25,0x21,0x50,0x60,0x00,
-0x21,0x10,0x83,0x00,0x21,0x10,0x50,0x00,0x99,0x51,0x40,0xa0,0x02,0x80,0x03,0x3c,
-0x02,0x80,0x02,0x3c,0x4c,0x91,0x49,0x24,0xd8,0x90,0x68,0x24,0x21,0x38,0x00,0x00,
-0x80,0x18,0x07,0x00,0x21,0x10,0x69,0x00,0x21,0x20,0x68,0x00,0x00,0x00,0x46,0x8c,
-0x00,0x00,0x85,0x8c,0x01,0x00,0xe7,0x24,0x21,0x18,0x6a,0x00,0x1d,0x00,0xe2,0x28,
-0xec,0x44,0x65,0xac,0xf6,0xff,0x40,0x14,0x60,0x45,0x66,0xac,0x14,0x00,0x00,0x12,
-0x68,0x15,0x63,0x25,0x7b,0x51,0x62,0x92,0xff,0xff,0x07,0x26,0x2a,0x10,0xe2,0x00,
-0x0e,0x00,0x40,0x14,0x02,0x80,0x0b,0x3c,0x68,0x15,0x62,0x25,0x21,0x10,0xc2,0x03,
-0x7b,0x51,0x45,0x90,0x74,0x51,0x44,0x8c,0x01,0x00,0x06,0x24,0x04,0x18,0xe6,0x00,
-0x24,0x10,0x83,0x00,0xb3,0x00,0x43,0x10,0x00,0x00,0x00,0x00,0xff,0xff,0xe7,0x24,
-0x2a,0x10,0xe5,0x00,0xfa,0xff,0x40,0x10,0x04,0x18,0xe6,0x00,0x68,0x15,0x63,0x25,
-0x80,0x10,0x10,0x00,0x21,0x10,0x43,0x00,0x60,0x45,0x45,0x8c,0xec,0x44,0x44,0x8c,
-0x02,0x80,0x03,0x3c,0x40,0x10,0x05,0x00,0x8e,0x7d,0x66,0x90,0x21,0x10,0x45,0x00,
-0x21,0x20,0x82,0x00,0x22,0x00,0x02,0x24,0x98,0x00,0xc2,0x10,0x82,0x50,0x04,0x00,
-0xd4,0x51,0x63,0x8e,0x01,0x00,0x02,0x24,0x04,0x10,0x02,0x02,0x25,0x18,0x62,0x00,
-0xd4,0x51,0x63,0xae,0x68,0x15,0x63,0x25,0x21,0x10,0xe3,0x02,0x44,0x51,0x4a,0xac,
-0x8c,0x65,0x64,0x8c,0xff,0xff,0x02,0x34,0x3c,0xff,0x82,0x14,0x21,0x20,0x00,0x02,
-0x39,0x0f,0x00,0x08,0x00,0x00,0x00,0x00,0x3e,0xff,0x20,0x11,0x21,0x20,0x00,0x02,
-0x68,0x15,0x62,0x25,0x80,0x18,0x10,0x00,0x21,0x18,0x62,0x00,0x60,0x45,0x64,0x8c,
-0x00,0x00,0x00,0x00,0x2b,0x20,0x44,0x01,0x36,0xff,0x80,0x10,0x21,0x20,0x00,0x02,
-0xa2,0x0f,0x00,0x08,0x68,0x15,0x68,0x25,0x1e,0xff,0x40,0x10,0x68,0x15,0x65,0x25,
-0x21,0x20,0x30,0x02,0x99,0x51,0x83,0x90,0x01,0x00,0x02,0x24,0x63,0x00,0x62,0x10,
-0x02,0x80,0x02,0x3c,0x2c,0x00,0xa3,0x8f,0x68,0x15,0x42,0x24,0x21,0x38,0x00,0x00,
-0x21,0x20,0x62,0x00,0x21,0x18,0x87,0x00,0x01,0x00,0xe7,0x24,0x1d,0x00,0xe2,0x28,
-0xfc,0xff,0x40,0x14,0xb6,0x51,0x60,0xa0,0x28,0x00,0xa3,0x8f,0x02,0x80,0x0b,0x3c,
-0x68,0x15,0x65,0x25,0x21,0x30,0x65,0x00,0xd4,0x51,0xc2,0x8c,0x01,0x00,0x03,0x24,
-0x04,0x18,0x03,0x02,0x27,0x18,0x03,0x00,0x21,0x20,0xd0,0x00,0x24,0x10,0x43,0x00,
-0x99,0x51,0x80,0xa0,0xd4,0x51,0xc2,0xac,0x12,0x00,0x00,0x16,0x7c,0x51,0x80,0xa0,
-0x7a,0x51,0xc2,0x90,0x00,0x00,0x00,0x00,0x0e,0x00,0x40,0x10,0x01,0x00,0x07,0x24,
-0x24,0x00,0xa4,0x8f,0x01,0x00,0x06,0x24,0x21,0x10,0x85,0x00,0x7a,0x51,0x44,0x90,
-0x74,0x51,0x45,0x8c,0x04,0x18,0xe6,0x00,0x24,0x10,0xa3,0x00,0x5b,0x00,0x43,0x10,
-0x00,0x00,0x00,0x00,0x01,0x00,0xe7,0x24,0x2a,0x10,0x87,0x00,0xfa,0xff,0x40,0x10,
-0x04,0x18,0xe6,0x00,0x20,0x00,0xa2,0x8f,0x02,0x80,0x0b,0x3c,0x68,0x15,0x64,0x25,
-0x21,0x18,0x44,0x00,0x7a,0x51,0x62,0x90,0x01,0x00,0x07,0x26,0x2a,0x10,0x47,0x00,
-0x0e,0x00,0x40,0x14,0x01,0x00,0x06,0x24,0x1c,0x00,0xa3,0x8f,0x00,0x00,0x00,0x00,
-0x21,0x10,0x64,0x00,0x7a,0x51,0x45,0x90,0x74,0x51,0x44,0x8c,0x04,0x18,0xe6,0x00,
-0x24,0x10,0x83,0x00,0x42,0x00,0x43,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0xe7,0x24,
-0x2a,0x10,0xa7,0x00,0xfa,0xff,0x40,0x10,0x04,0x18,0xe6,0x00,0x02,0x80,0x02,0x3c,
-0x8e,0x7d,0x44,0x90,0x22,0x00,0x03,0x24,0xd6,0xfe,0x83,0x14,0x68,0x15,0x65,0x25,
-0xee,0xff,0x02,0x26,0xff,0x00,0x42,0x30,0x02,0x00,0x42,0x2c,0x18,0x00,0x03,0x24,
-0x25,0x0f,0x00,0x08,0x0b,0x80,0x62,0x00,0xc0,0x10,0x07,0x00,0x23,0x10,0x47,0x00,
-0xc2,0x10,0x02,0x00,0x2b,0x10,0x48,0x00,0xb6,0xfe,0x40,0x14,0x00,0x00,0x00,0x00,
-0x04,0x0f,0x00,0x08,0x00,0x00,0x00,0x00,0x10,0x00,0xa3,0x8f,0x5c,0x00,0xbf,0x8f,
-0x58,0x00,0xbe,0x8f,0x54,0x00,0xb7,0x8f,0x50,0x00,0xb6,0x8f,0x4c,0x00,0xb5,0x8f,
-0x48,0x00,0xb4,0x8f,0x44,0x00,0xb3,0x8f,0x40,0x00,0xb2,0x8f,0x3c,0x00,0xb1,0x8f,
-0x38,0x00,0xb0,0x8f,0x25,0xb0,0x02,0x3c,0x80,0x01,0x42,0x34,0x60,0x00,0xbd,0x27,
-0x00,0x00,0x43,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x18,0x00,0x02,0x2e,
-0x0a,0x00,0x40,0x14,0x05,0x00,0x02,0x2e,0xb6,0x51,0x83,0x90,0x00,0x00,0x00,0x00,
-0x05,0x00,0x62,0x2c,0xa0,0xff,0x40,0x10,0x01,0x00,0x62,0x24,0x16,0x10,0x00,0x08,
-0xb6,0x51,0x82,0xa0,0x24,0x0f,0x00,0x08,0x99,0x51,0xa7,0xa0,0x04,0x00,0x40,0x10,
-0x00,0x00,0x00,0x00,0xb6,0x51,0x83,0x90,0x75,0x10,0x00,0x08,0x03,0x00,0x62,0x2c,
-0xb6,0x51,0x83,0x90,0x75,0x10,0x00,0x08,0x04,0x00,0x62,0x2c,0x13,0x00,0x02,0x24,
-0x67,0xff,0x02,0x16,0x68,0x15,0x63,0x25,0xf3,0x0f,0x00,0x08,0x21,0x10,0xe3,0x02,
-0xff,0x00,0xf0,0x30,0x4c,0x10,0x00,0x08,0x02,0x80,0x02,0x3c,0x35,0x10,0x00,0x08,
-0xff,0x00,0xf0,0x30,0xdf,0x0f,0x00,0x08,0xff,0x00,0xf0,0x30,0xd8,0xff,0xbd,0x27,
-0x02,0x80,0x02,0x3c,0x14,0x00,0xb1,0xaf,0x24,0x00,0xbf,0xaf,0x20,0x00,0xb4,0xaf,
-0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x68,0x15,0x45,0x24,
-0x05,0x65,0xa4,0x90,0x00,0x65,0xa3,0x8c,0xfc,0x64,0xa2,0x8c,0x21,0x88,0x64,0x00,
-0x2b,0x10,0x22,0x02,0x60,0x00,0x40,0x10,0x21,0x80,0xa0,0x00,0x02,0x80,0x14,0x3c,
-0x21,0x98,0xa0,0x00,0xa8,0x10,0x00,0x08,0x21,0x90,0xa0,0x00,0xfc,0x64,0x42,0x8e,
-0x10,0x00,0x31,0x26,0x2b,0x10,0x22,0x02,0x57,0x00,0x40,0x10,0x21,0x80,0x40,0x02,
-0x05,0x65,0x02,0x92,0xff,0xff,0x23,0x32,0x02,0x80,0x05,0x3c,0x10,0x00,0x42,0x24,
-0x25,0x28,0x65,0x00,0x2c,0x79,0x84,0x26,0x10,0x00,0x06,0x24,0x9f,0x45,0x00,0x0c,
-0x05,0x65,0x02,0xa2,0xc8,0x63,0x06,0x8e,0x00,0x00,0x00,0x00,0x42,0x24,0x06,0x00,
-0x1f,0x00,0x84,0x30,0xc0,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x80,0x10,0x02,0x00,
-0x21,0x10,0x44,0x00,0x80,0x10,0x02,0x00,0x21,0x38,0x50,0x00,0x78,0x51,0xe3,0x8c,
-0x00,0x00,0x00,0x00,0x02,0x1b,0x03,0x00,0x01,0x00,0x63,0x30,0xe3,0xff,0x60,0x10,
-0x25,0xb0,0x02,0x3c,0xc4,0x63,0x05,0x8e,0x21,0x10,0x82,0x00,0x60,0x01,0x44,0x90,
-0x82,0x1d,0x05,0x00,0x3f,0x00,0x63,0x30,0x04,0x00,0x0a,0x24,0x05,0x00,0x62,0x28,
-0x21,0x40,0x40,0x01,0x0b,0x40,0x62,0x00,0x07,0x00,0xa0,0x04,0xff,0x00,0x89,0x30,
-0x64,0x51,0xe2,0x8c,0x04,0x00,0x08,0x24,0x01,0x00,0x42,0x24,0x64,0x51,0xe2,0xac,
-0xc8,0x63,0x66,0x8e,0x00,0x00,0x00,0x00,0x02,0x13,0x06,0x00,0x1f,0x00,0x42,0x30,
-0x08,0x00,0x42,0x28,0xcd,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0xc4,0x63,0x62,0x8e,
-0x00,0x00,0x00,0x00,0x3f,0x00,0x42,0x30,0xc8,0xff,0x49,0x14,0x00,0x00,0x00,0x00,
-0x29,0x00,0x00,0x11,0x01,0x00,0x02,0x24,0x2e,0x00,0x02,0x11,0x02,0x00,0x02,0x24,
-0x33,0x00,0x02,0x11,0x03,0x00,0x02,0x24,0x38,0x00,0x02,0x11,0x00,0x00,0x00,0x00,
-0x3b,0x00,0x0a,0x11,0x00,0x00,0x00,0x00,0x68,0x51,0xe2,0x8c,0x21,0x18,0x33,0x01,
-0x90,0x44,0x64,0x90,0x02,0x11,0x02,0x00,0x2b,0x10,0x44,0x00,0x3e,0x00,0x40,0x14,
-0x00,0x00,0x00,0x00,0x5c,0x51,0xe3,0x8c,0x80,0x10,0x09,0x00,0x21,0x10,0x49,0x00,
-0x01,0x00,0x63,0x24,0x21,0x10,0x53,0x00,0x5c,0x51,0xe3,0xac,0x21,0x10,0x48,0x00,
-0x34,0x43,0x44,0x90,0x44,0x51,0xe3,0x8c,0x00,0x00,0x00,0x00,0x21,0x18,0x64,0x00,
-0x44,0x51,0xe3,0xac,0xfc,0x64,0x42,0x8e,0x10,0x00,0x31,0x26,0x2b,0x10,0x22,0x02,
-0xab,0xff,0x40,0x14,0x21,0x80,0x40,0x02,0x24,0x00,0xbf,0x8f,0x20,0x00,0xb4,0x8f,
-0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
-0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x48,0x51,0xe2,0x8c,0x00,0x00,0x00,0x00,
-0x01,0x00,0x42,0x24,0x48,0x51,0xe2,0xac,0x01,0x00,0x02,0x24,0xd4,0xff,0x02,0x15,
-0x02,0x00,0x02,0x24,0x4c,0x51,0xe2,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,
-0x4c,0x51,0xe2,0xac,0x02,0x00,0x02,0x24,0xcf,0xff,0x02,0x15,0x03,0x00,0x02,0x24,
-0x50,0x51,0xe2,0x8c,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0x50,0x51,0xe2,0xac,
-0x03,0x00,0x02,0x24,0xca,0xff,0x02,0x15,0x00,0x00,0x00,0x00,0x54,0x51,0xe2,0x8c,
-0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xc7,0xff,0x0a,0x15,0x54,0x51,0xe2,0xac,
-0x58,0x51,0xe2,0x8c,0x21,0x18,0x33,0x01,0x01,0x00,0x42,0x24,0x58,0x51,0xe2,0xac,
-0x68,0x51,0xe2,0x8c,0x90,0x44,0x64,0x90,0x02,0x11,0x02,0x00,0x2b,0x10,0x44,0x00,
-0xc4,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x60,0x51,0xe3,0x8c,0x80,0x10,0x09,0x00,
-0x21,0x10,0x49,0x00,0x01,0x00,0x63,0x24,0x21,0x10,0x53,0x00,0x60,0x51,0xe3,0xac,
-0x21,0x10,0x48,0x00,0xc5,0x43,0x44,0x90,0x44,0x51,0xe3,0x8c,0x00,0x00,0x00,0x00,
-0x21,0x18,0x64,0x00,0xf9,0x10,0x00,0x08,0x44,0x51,0xe3,0xac,0x25,0xb0,0x02,0x3c,
-0x25,0xb0,0x05,0x3c,0x02,0x80,0x03,0x3c,0x58,0x00,0x4a,0x34,0x5c,0x00,0x4b,0x34,
-0x4c,0x00,0xa2,0x34,0x00,0x00,0x44,0x90,0x68,0x15,0x66,0x24,0xed,0x4a,0xc2,0x90,
-0x29,0xb0,0x07,0x3c,0x03,0x00,0x84,0x30,0x21,0x18,0xc0,0x00,0x0f,0x00,0x44,0x10,
-0x04,0x00,0xe8,0x34,0x07,0x00,0x80,0x14,0x58,0x0c,0xa9,0x34,0xe6,0x42,0xc2,0x90,
-0x1c,0x00,0x06,0x24,0x03,0x00,0x40,0x14,0x50,0x0c,0xa5,0x34,0x00,0x00,0xa6,0xa0,
-0x00,0x00,0x26,0xa1,0x00,0x00,0x42,0x8d,0xed,0x4a,0x64,0xa0,0x00,0x00,0xe2,0xac,
-0x00,0x00,0x62,0x8d,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xad,0x08,0x00,0xe0,0x03,
-0x21,0x10,0x00,0x00,0x25,0xb0,0x0d,0x3c,0xe8,0xff,0xbd,0x27,0x10,0x00,0xbf,0xaf,
-0x2d,0x0a,0xa7,0x35,0xa2,0x0d,0xa2,0x35,0xa4,0x0d,0xa3,0x35,0xa6,0x0d,0xa4,0x35,
-0xa8,0x0d,0xa5,0x35,0x00,0x00,0x48,0x94,0x00,0x00,0x69,0x94,0x00,0x00,0x8a,0x94,
-0x00,0x00,0xab,0x94,0x00,0x00,0xe3,0x90,0x5b,0x0a,0xa4,0x35,0x5c,0x0a,0xa6,0x35,
-0x00,0x2e,0x03,0x00,0x03,0x2e,0x05,0x00,0x40,0x00,0xa2,0x34,0x00,0x00,0xe2,0xa0,
-0x00,0x00,0x85,0x90,0x00,0x00,0xc3,0x90,0x02,0x80,0x0e,0x3c,0x68,0x15,0xcc,0x25,
-0xff,0xff,0x22,0x31,0xff,0x00,0xa5,0x30,0xff,0xff,0x04,0x31,0x21,0x20,0x82,0x00,
-0xff,0x00,0x63,0x30,0x00,0x40,0x87,0x8d,0x00,0x2a,0x05,0x00,0xff,0xff,0x46,0x31,
-0x21,0x28,0xa3,0x00,0xff,0xff,0x62,0x31,0x21,0x20,0x86,0x00,0x21,0x20,0x82,0x00,
-0xff,0xff,0xa3,0x30,0x64,0x0c,0xa2,0x35,0x00,0x00,0x45,0xa4,0x21,0x20,0x83,0x00,
-0x0f,0x00,0xe7,0x30,0x01,0x00,0x02,0x24,0xe0,0x42,0x84,0xad,0xd8,0x42,0x88,0xa5,
-0xda,0x42,0x89,0xa5,0xdc,0x42,0x8a,0xa5,0xde,0x42,0x8b,0xa5,0x07,0x00,0xe2,0x10,
-0xe4,0x42,0x85,0xa5,0xa8,0x56,0x00,0x0c,0x00,0x00,0x00,0x00,0x10,0x00,0xbf,0x8f,
-0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x4c,0x00,0xa3,0x35,
-0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,0x67,0x00,0x47,0x10,
-0x68,0x15,0xc4,0x25,0xe6,0x42,0x82,0x90,0x00,0x00,0x00,0x00,0x2d,0x00,0x40,0x10,
-0x01,0x00,0x03,0x24,0x68,0x15,0xc5,0x25,0xe6,0x42,0xa3,0x90,0xff,0x00,0x02,0x24,
-0xec,0xff,0x62,0x14,0x25,0xb0,0x03,0x3c,0xc8,0x42,0xa2,0x94,0xe0,0x42,0xa6,0x8c,
-0x50,0x0c,0x63,0x34,0x00,0x00,0x64,0x90,0x2b,0x10,0xc2,0x00,0x5e,0x00,0x40,0x14,
-0x7f,0x00,0x84,0x30,0xca,0x42,0xa2,0x94,0x00,0x00,0x00,0x00,0x2b,0x10,0xc2,0x00,
-0x09,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0xcc,0x42,0xa2,0x94,0x00,0x00,0x00,0x00,
-0x2b,0x10,0xc2,0x00,0x02,0x00,0x40,0x10,0x02,0x00,0x82,0x24,0x01,0x00,0x82,0x24,
-0xff,0x00,0x44,0x30,0x68,0x15,0xc5,0x25,0xd0,0x42,0xa3,0x90,0x00,0x00,0x00,0x00,
-0x2b,0x10,0x64,0x00,0x4e,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x21,0x20,0x60,0x00,
-0x68,0x15,0xc3,0x25,0xe0,0x42,0x62,0x8c,0x00,0x00,0x00,0x00,0xe9,0x03,0x42,0x2c,
-0x02,0x00,0x40,0x14,0x25,0xb0,0x02,0x3c,0xd0,0x42,0x64,0x90,0x58,0x0c,0x43,0x34,
-0x50,0x0c,0x42,0x34,0x00,0x00,0x44,0xa0,0x00,0x00,0x64,0xa0,0x85,0x11,0x00,0x08,
-0x00,0x00,0x00,0x00,0x00,0x40,0x82,0x8c,0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,
-0x0f,0x00,0x42,0x30,0xd0,0xff,0x43,0x14,0x68,0x15,0xc5,0x25,0x25,0xb0,0x02,0x3c,
-0x4c,0x00,0x42,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x63,0x30,
-0xb8,0xff,0x60,0x10,0xff,0xff,0x02,0x34,0xdc,0x63,0x83,0x8c,0x00,0x00,0x00,0x00,
-0xb4,0xff,0x62,0x10,0x00,0x00,0x00,0x00,0xe0,0x42,0x83,0x8c,0x00,0x00,0x00,0x00,
-0x65,0x00,0x62,0x2c,0x3b,0x00,0x40,0x14,0x28,0x00,0x62,0x2c,0xd2,0x42,0x83,0x90,
-0x00,0x00,0x00,0x00,0x00,0x16,0x03,0x00,0x03,0x16,0x02,0x00,0xfe,0xff,0x42,0x24,
-0xfc,0xff,0x42,0x28,0x02,0x00,0x40,0x10,0xfe,0xff,0x62,0x24,0xfc,0xff,0x02,0x24,
-0xd2,0x42,0x82,0xa0,0x68,0x15,0xc4,0x25,0xdc,0x63,0x82,0x8c,0xd2,0x42,0x83,0x90,
-0xce,0x42,0x86,0x90,0x02,0x11,0x02,0x00,0x7f,0x00,0x42,0x30,0x0a,0x00,0x45,0x24,
-0x23,0x18,0xa3,0x00,0x00,0x2e,0x03,0x00,0x03,0x2e,0x05,0x00,0xff,0x00,0xc2,0x30,
-0x2a,0x10,0x45,0x00,0x17,0x00,0x40,0x10,0x25,0xb0,0x02,0x3c,0x00,0x2e,0x06,0x00,
-0x03,0x2e,0x05,0x00,0x58,0x0c,0x43,0x34,0x50,0x0c,0x42,0x34,0x00,0x00,0x45,0xa0,
-0x00,0x00,0x65,0xa0,0x85,0x11,0x00,0x08,0x00,0x00,0x00,0x00,0xe6,0x42,0x82,0x91,
-0x00,0x00,0x00,0x00,0x97,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x24,
-0x91,0x11,0x00,0x08,0xe6,0x42,0x82,0xa1,0xac,0x11,0x00,0x08,0xff,0xff,0x82,0x24,
-0xd1,0x42,0xa3,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x83,0x00,0xb4,0x11,0x00,0x08,
-0x0b,0x20,0x62,0x00,0xcf,0x42,0x83,0x80,0x00,0x00,0x00,0x00,0xff,0x00,0x62,0x30,
-0x2a,0x10,0xa2,0x00,0x0b,0x28,0x62,0x00,0x25,0xb0,0x02,0x3c,0x58,0x0c,0x43,0x34,
-0x50,0x0c,0x42,0x34,0x00,0x00,0x45,0xa0,0x00,0x00,0x65,0xa0,0x85,0x11,0x00,0x08,
-0x00,0x00,0x00,0x00,0xcf,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0xd2,0x42,0x83,0x90,
-0x00,0x00,0x00,0x00,0x00,0x16,0x03,0x00,0x03,0x16,0x02,0x00,0x02,0x00,0x42,0x24,
-0x0d,0x00,0x42,0x28,0x03,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0xe0,0x11,0x00,0x08,
-0x0c,0x00,0x02,0x24,0xe0,0x11,0x00,0x08,0x02,0x00,0x62,0x24,0xc0,0xff,0xbd,0x27,
-0x18,0x00,0xb0,0xaf,0x25,0xb0,0x10,0x3c,0x28,0x00,0xb4,0xaf,0x24,0x00,0xb3,0xaf,
-0x1c,0x00,0xb1,0xaf,0x3c,0x00,0xbf,0xaf,0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,
-0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,0x20,0x00,0xb2,0xaf,0xd8,0x00,0x06,0x36,
-0x00,0x00,0xc3,0x90,0x02,0x80,0x02,0x3c,0x68,0x15,0x54,0x24,0x2a,0xb0,0x11,0x3c,
-0xa0,0xff,0x02,0x24,0x25,0x18,0x62,0x00,0x34,0x00,0x25,0x36,0xfe,0xff,0x02,0x24,
-0xbc,0x42,0x92,0x92,0x40,0x00,0x04,0x24,0x00,0x00,0xc3,0xa0,0x00,0x00,0xa2,0xa0,
-0xa1,0x4e,0x00,0x0c,0x00,0x96,0x12,0x00,0x21,0x98,0x40,0x00,0x6b,0x00,0x60,0x12,
-0x00,0x40,0x02,0x3c,0x08,0x00,0x63,0x8e,0xb0,0x03,0x02,0x36,0x21,0x20,0x60,0x02,
-0x00,0x00,0x43,0xac,0x3a,0x45,0x00,0x0c,0x21,0xb8,0x80,0x02,0x01,0x00,0x1e,0x24,
-0x42,0x00,0x16,0x36,0x03,0x0c,0x11,0x36,0x17,0x0e,0x15,0x36,0x04,0x00,0x14,0x24,
-0x2a,0xb0,0x03,0x3c,0x06,0x00,0x63,0x34,0x00,0x00,0x62,0x94,0x00,0x00,0x00,0x00,
-0x00,0xff,0x42,0x30,0x0a,0x00,0x40,0x18,0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,
-0xc8,0x94,0x84,0x24,0x00,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0x94,
-0x00,0x00,0x00,0x00,0x00,0xff,0x42,0x30,0xfc,0xff,0x40,0x1c,0x00,0x00,0x00,0x00,
-0x08,0x00,0x65,0x8e,0x20,0x10,0x06,0x3c,0x00,0xfe,0xc6,0x34,0x40,0x00,0x07,0x24,
-0x01,0x00,0x04,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xbe,0xaf,0x4d,0x01,0x00,0x0c,
-0x01,0x00,0x04,0x24,0x2a,0xb0,0x02,0x3c,0x05,0x00,0x42,0x34,0xff,0xff,0x03,0x24,
-0x00,0x00,0x5e,0xa0,0x00,0x00,0xc3,0xa2,0x00,0x00,0x22,0x92,0xc1,0x42,0xe5,0x92,
-0x2a,0xb0,0x04,0x3c,0x02,0x00,0x03,0x24,0x40,0x00,0x42,0x34,0x05,0x00,0x84,0x34,
-0x00,0x00,0x22,0xa2,0x00,0x00,0x83,0xa0,0xef,0xff,0x02,0x24,0x00,0x00,0xb0,0x92,
-0x64,0x00,0x04,0x24,0x00,0x00,0xa5,0xa2,0x00,0x00,0xc2,0xa2,0xb3,0x0a,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x92,0xbf,0xff,0x03,0x24,0x84,0x03,0x04,0x24,
-0x24,0x10,0x43,0x00,0x00,0x00,0x22,0xa2,0xb3,0x0a,0x00,0x0c,0xff,0x00,0x10,0x32,
-0x25,0xb0,0x02,0x3c,0xf4,0x08,0x42,0x34,0x00,0x00,0x44,0x8c,0x00,0x00,0xb0,0xa2,
-0x00,0x00,0xc0,0xa2,0x00,0x00,0x22,0x92,0xbe,0x42,0xe3,0x92,0x1f,0x00,0x85,0x30,
-0x40,0x00,0x42,0x34,0x00,0x00,0x22,0xa2,0x00,0x80,0x02,0x3c,0xdf,0x07,0x42,0x34,
-0x2b,0x18,0xa3,0x00,0x09,0x00,0x60,0x10,0x24,0x20,0x82,0x00,0xbf,0x42,0xe2,0x92,
-0x00,0x00,0x00,0x00,0x2b,0x10,0x45,0x00,0x05,0x00,0x40,0x10,0x02,0x80,0x02,0x3c,
-0x01,0x00,0x02,0x3c,0x25,0x10,0xa2,0x00,0x21,0x90,0x42,0x02,0x02,0x80,0x02,0x3c,
-0x8e,0x7d,0x43,0x90,0x22,0x00,0x02,0x24,0x1c,0x00,0x62,0x10,0x92,0x00,0x02,0x24,
-0x1b,0x00,0x62,0x10,0x02,0x80,0x03,0x3c,0xff,0xff,0x94,0x26,0xb3,0x0a,0x00,0x0c,
-0xf4,0x01,0x04,0x24,0xab,0xff,0x81,0x06,0x2a,0xb0,0x03,0x3c,0x04,0x00,0x60,0x12,
-0x25,0xb0,0x02,0x3c,0xbd,0x4e,0x00,0x0c,0x21,0x20,0x60,0x02,0x25,0xb0,0x02,0x3c,
-0xd8,0x02,0x42,0x34,0x00,0x00,0x52,0xac,0x21,0x10,0x40,0x02,0x3c,0x00,0xbf,0x8f,
-0x38,0x00,0xbe,0x8f,0x34,0x00,0xb7,0x8f,0x30,0x00,0xb6,0x8f,0x2c,0x00,0xb5,0x8f,
-0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,
-0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x40,0x00,0xbd,0x27,0x02,0x80,0x03,0x3c,
-0x68,0x15,0x63,0x24,0xbe,0x42,0x62,0x90,0xc0,0x07,0x83,0x30,0x82,0x19,0x03,0x00,
-0x2b,0x10,0x62,0x00,0xe0,0xff,0x40,0x10,0x02,0x80,0x04,0x3c,0x68,0x15,0x84,0x24,
-0xbf,0x42,0x82,0x90,0x00,0x00,0x00,0x00,0x2b,0x10,0x43,0x00,0xda,0xff,0x40,0x10,
-0x00,0x12,0x03,0x00,0x10,0x00,0x03,0x3c,0x25,0x10,0x43,0x00,0x9a,0x12,0x00,0x08,
-0x21,0x90,0x42,0x02,0xe8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x0f,0x00,0x10,0x3c,
-0xff,0xff,0x05,0x36,0xf0,0xf8,0x06,0x34,0x14,0x00,0xbf,0xaf,0xba,0x44,0x00,0x0c,
-0x15,0x00,0x04,0x24,0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0xff,0xff,0x05,0x36,
-0x56,0x30,0x06,0x24,0xba,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,0xb3,0x0a,0x00,0x0c,
-0x64,0x00,0x04,0x24,0x02,0x80,0x0b,0x3c,0x68,0x15,0x64,0x25,0x04,0x43,0x83,0x90,
-0x04,0x00,0x02,0x24,0x19,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c,0x14,0x43,0x8a,0x8c,
-0x18,0x43,0x88,0x8c,0x25,0xb0,0x02,0x3c,0x1c,0x0e,0x49,0x34,0x00,0x0e,0x43,0x34,
-0x04,0x0e,0x44,0x34,0x08,0x0e,0x45,0x34,0x10,0x0e,0x46,0x34,0x14,0x0e,0x47,0x34,
-0x18,0x0e,0x42,0x34,0x00,0x00,0x6a,0xac,0x00,0x00,0x8a,0xac,0x00,0x00,0xa8,0xac,
-0x00,0x00,0xca,0xac,0x00,0x00,0xea,0xac,0x00,0x00,0x4a,0xac,0x00,0x00,0x2a,0xad,
-0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x68,0x15,0x63,0x25,0x04,0x00,0x02,0x24,
-0x18,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x04,0x43,0x62,0xa0,0x00,0x0e,0x42,0x34,
-0x00,0x00,0x43,0x8c,0x14,0x43,0x8a,0x8c,0x00,0x00,0x00,0x00,0xe4,0xff,0x6a,0x14,
-0x00,0x00,0x00,0x00,0xec,0x12,0x00,0x08,0x00,0x00,0x00,0x00,0xe8,0xff,0xbd,0x27,
-0x10,0x00,0xb0,0xaf,0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,0xf0,0xf8,0x06,0x34,
-0x14,0x00,0xbf,0xaf,0xba,0x44,0x00,0x0c,0x15,0x00,0x04,0x24,0xb3,0x0a,0x00,0x0c,
-0x64,0x00,0x04,0x24,0xff,0xff,0x05,0x36,0x56,0x30,0x06,0x24,0xba,0x44,0x00,0x0c,
-0x1a,0x00,0x04,0x24,0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0x02,0x80,0x04,0x3c,
-0x68,0x15,0x83,0x24,0x04,0x43,0x65,0x90,0x21,0x70,0x60,0x00,0x10,0x10,0x03,0x3c,
-0x25,0xb0,0x02,0x3c,0x10,0x10,0x66,0x34,0x01,0x00,0x03,0x24,0x1c,0x0e,0x4d,0x34,
-0x00,0x0e,0x4a,0x34,0x04,0x0e,0x4b,0x34,0x08,0x0e,0x4c,0x34,0x10,0x0e,0x47,0x34,
-0x14,0x0e,0x48,0x34,0x0f,0x00,0xa3,0x10,0x18,0x0e,0x49,0x34,0x10,0x10,0x02,0x24,
-0x00,0x00,0x46,0xad,0x00,0x00,0x66,0xad,0x00,0x00,0x82,0xad,0x00,0x00,0xe6,0xac,
-0x00,0x00,0x06,0xad,0x00,0x00,0x26,0xad,0x00,0x00,0xa6,0xad,0x14,0x00,0xbf,0x8f,
-0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x18,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,
-0x04,0x43,0xc2,0xa1,0x00,0x00,0x44,0x8d,0x00,0x00,0x00,0x00,0xf0,0xff,0x86,0x14,
-0x10,0x10,0x02,0x24,0x23,0x13,0x00,0x08,0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27,
-0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x01,0x00,0x11,0x3c,0x0f,0x00,0x10,0x3c,
-0xff,0xff,0x05,0x36,0xf4,0x98,0x26,0x36,0x18,0x00,0xbf,0xaf,0xba,0x44,0x00,0x0c,
-0x15,0x00,0x04,0x24,0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0xff,0xff,0x05,0x36,
-0x56,0x30,0x26,0x36,0xba,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,0x02,0x80,0x10,0x3c,
-0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0x68,0x15,0x04,0x26,0x04,0x43,0x82,0x90,
-0x00,0x00,0x00,0x00,0x0d,0x00,0x40,0x14,0x25,0xb0,0x02,0x3c,0x00,0x0e,0x42,0x34,
-0x00,0x00,0x43,0x8c,0xec,0x42,0x8f,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x6f,0x14,
-0x68,0x15,0x02,0x26,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
-0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x04,0x43,0x40,0xa0,0xec,0x42,0x8f,0x8c,
-0xe8,0x42,0x88,0x8c,0xf0,0x42,0x8a,0x8c,0xf4,0x42,0x8b,0x8c,0xf8,0x42,0x8c,0x8c,
-0xfc,0x42,0x8d,0x8c,0x25,0xb0,0x02,0x3c,0x00,0x43,0x8e,0x8c,0x1c,0x0e,0x49,0x34,
-0x08,0x0e,0x43,0x34,0x00,0x0e,0x44,0x34,0x04,0x0e,0x45,0x34,0x10,0x0e,0x46,0x34,
-0x14,0x0e,0x47,0x34,0x18,0x0e,0x42,0x34,0x00,0x00,0x68,0xac,0x18,0x00,0xbf,0x8f,
-0x00,0x00,0x8f,0xac,0x14,0x00,0xb1,0x8f,0x00,0x00,0xaa,0xac,0x00,0x00,0xcb,0xac,
-0x00,0x00,0xec,0xac,0x00,0x00,0x4d,0xac,0x68,0x15,0x02,0x26,0x10,0x00,0xb0,0x8f,
-0x20,0x00,0xbd,0x27,0x00,0x00,0x2e,0xad,0x08,0x00,0xe0,0x03,0x04,0x43,0x40,0xa0,
-0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x01,0x00,0x11,0x3c,
-0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,0xf4,0x98,0x26,0x36,0x18,0x00,0xbf,0xaf,
-0xba,0x44,0x00,0x0c,0x15,0x00,0x04,0x24,0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,
-0xff,0xff,0x05,0x36,0x56,0x30,0x26,0x36,0xba,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,
-0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0x02,0x80,0x18,0x3c,0x68,0x15,0x05,0x27,
-0x04,0x43,0xa3,0x90,0x03,0x00,0x02,0x24,0x2a,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c,
-0xec,0x42,0xaf,0x8c,0x08,0x43,0xa3,0x8c,0xe8,0x42,0xa2,0x8c,0xf0,0x42,0xac,0x8c,
-0xf4,0x42,0xad,0x8c,0xf8,0x42,0xa9,0x8c,0xfc,0x42,0xaa,0x8c,0x00,0x43,0xab,0x8c,
-0x21,0x70,0x43,0x00,0xff,0xff,0x02,0x3c,0x25,0xb0,0x03,0x3c,0xff,0x00,0x42,0x34,
-0x00,0xff,0xc4,0x31,0x04,0x0e,0x65,0x34,0x10,0x0e,0x66,0x34,0x14,0x0e,0x67,0x34,
-0x18,0x0e,0x68,0x34,0x24,0x80,0xc2,0x01,0x08,0x0e,0x71,0x34,0x00,0x0e,0x62,0x34,
-0x01,0x3f,0x84,0x2c,0x1c,0x0e,0x63,0x34,0x00,0x00,0x4f,0xac,0x00,0x00,0xac,0xac,
-0x00,0x00,0xcd,0xac,0x00,0x00,0xe9,0xac,0x00,0x00,0x0a,0xad,0x00,0x00,0x6b,0xac,
-0x0a,0x00,0x80,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x2e,0xae,0x18,0x00,0xbf,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x68,0x15,0x03,0x27,0x03,0x00,0x02,0x24,
-0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x04,0x43,0x62,0xa0,0xa6,0x13,0x00,0x08,
-0x00,0x3f,0x0e,0x36,0x00,0x0e,0x42,0x34,0x00,0x00,0x43,0x8c,0xec,0x42,0xaf,0x8c,
-0x00,0x00,0x00,0x00,0xd3,0xff,0x6f,0x14,0x00,0x00,0x00,0x00,0xa7,0x13,0x00,0x08,
-0x00,0x00,0x00,0x00,0xd0,0xff,0xbd,0x27,0x18,0x00,0xb2,0xaf,0x02,0x80,0x12,0x3c,
-0x24,0x00,0xb5,0xaf,0x20,0x00,0xb4,0xaf,0x28,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf,
-0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x68,0x15,0x44,0x26,0x02,0x80,0x14,0x3c,
-0x00,0x40,0x85,0x8c,0xdc,0x63,0x83,0x8c,0x8e,0x7d,0x86,0x92,0x25,0xb0,0x02,0x3c,
-0x0f,0x0c,0x42,0x34,0x00,0x00,0x46,0xa0,0x02,0x19,0x03,0x00,0xf0,0xf0,0xa5,0x30,
-0x00,0x10,0x02,0x24,0x04,0x43,0x93,0x90,0x71,0x00,0xa2,0x10,0x7f,0x00,0x75,0x30,
-0x25,0xb0,0x09,0x3c,0x4c,0x00,0x23,0x35,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,
-0x03,0x00,0x42,0x30,0x09,0x00,0x40,0x10,0x68,0x15,0x45,0x26,0x68,0x15,0x4a,0x26,
-0x00,0x40,0x42,0x8d,0x00,0x00,0x00,0x00,0x02,0x13,0x02,0x00,0x0f,0x00,0x42,0x30,
-0x33,0x00,0x40,0x10,0x00,0x0e,0x25,0x35,0x68,0x15,0x45,0x26,0x04,0x43,0xa2,0x8c,
-0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x0f,0x00,0x40,0x14,0x68,0x15,0x4a,0x26,
-0x25,0xb0,0x02,0x3c,0x84,0x01,0x42,0x34,0x00,0x00,0x44,0x8c,0x0d,0x00,0x03,0x24,
-0x7e,0x00,0x83,0x10,0x3e,0x00,0x02,0x24,0x4a,0x00,0x03,0x24,0x1f,0x43,0xa2,0xa0,
-0x1c,0x43,0xa3,0xa0,0x45,0x00,0x02,0x24,0x43,0x00,0x03,0x24,0x1d,0x43,0xa2,0xa0,
-0x1e,0x43,0xa3,0xa0,0x68,0x15,0x4a,0x26,0xdc,0x63,0x4c,0x8d,0x04,0x40,0x42,0x8d,
-0x00,0x40,0x4b,0x8d,0x1e,0x43,0x4d,0x91,0x1c,0x43,0x4e,0x91,0x25,0xb0,0x09,0x3c,
-0x02,0x11,0x02,0x00,0x60,0x0c,0x27,0x35,0x02,0x19,0x0c,0x00,0x98,0x0c,0x24,0x35,
-0x00,0x00,0xe3,0xa0,0x66,0x0c,0x25,0x35,0x00,0x00,0x82,0xa0,0x67,0x0c,0x26,0x35,
-0xf0,0xf0,0x68,0x31,0x10,0x10,0x02,0x24,0x00,0x00,0xad,0xa0,0x00,0x00,0xce,0xa0,
-0x43,0x00,0x02,0x11,0xff,0xff,0x02,0x34,0x28,0x00,0xbf,0x8f,0x24,0x00,0xb5,0x8f,
-0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,
-0x00,0x00,0xa2,0x8c,0x00,0x00,0x00,0x00,0x5d,0x00,0x40,0x10,0x10,0x0e,0x28,0x35,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x08,0x0e,0x22,0x35,0x04,0x0e,0x24,0x35,0x00,0x00,0x43,0x8c,0x00,0x00,0xa5,0x8c,
-0x00,0x00,0x82,0x8c,0xe8,0x42,0x43,0xad,0xec,0x42,0x45,0xad,0xf0,0x42,0x42,0xad,
-0x14,0x0e,0x24,0x35,0x18,0x0e,0x22,0x35,0x1c,0x0e,0x25,0x35,0x00,0x00,0x08,0x8d,
-0x8e,0x7d,0x8b,0x92,0x00,0x00,0x86,0x8c,0x00,0xff,0x63,0x30,0x00,0x00,0x47,0x8c,
-0x00,0x00,0xa4,0x8c,0x9a,0x0c,0x22,0x35,0x02,0x1a,0x03,0x00,0x00,0x00,0x43,0xa0,
-0x22,0x00,0x02,0x24,0xf4,0x42,0x48,0xad,0xf8,0x42,0x46,0xad,0xfc,0x42,0x47,0xad,
-0x58,0x00,0x62,0x11,0x00,0x43,0x44,0xad,0x92,0x00,0x02,0x24,0x56,0x00,0x62,0x11,
-0x0d,0x08,0x22,0x35,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x68,0x15,0x44,0x26,0x00,0x40,0x83,0x8c,0xff,0xff,0x02,0x3c,0xff,0x0f,0x42,0x34,
-0x24,0x18,0x62,0x00,0x00,0x10,0x63,0x34,0xde,0x13,0x00,0x08,0x00,0x40,0x83,0xac,
-0x01,0x00,0x02,0x24,0x35,0x00,0x62,0x12,0x04,0x00,0x02,0x24,0x33,0x00,0x62,0x12,
-0x68,0x15,0x43,0x26,0xff,0xff,0x02,0x24,0xd0,0x13,0x00,0x08,0x04,0x43,0x62,0xa0,
-0xbd,0xff,0x82,0x11,0x02,0x12,0x0b,0x00,0x0f,0x00,0x48,0x30,0x01,0x00,0x03,0x24,
-0xb9,0xff,0x03,0x15,0x4c,0x00,0x23,0x35,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,
-0x03,0x00,0x42,0x30,0xb4,0xff,0x40,0x10,0x03,0x00,0x02,0x24,0x5f,0x00,0x62,0x12,
-0x04,0x00,0x62,0x2a,0x45,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x64,0x00,0x60,0x12,
-0xff,0x00,0xa2,0x31,0xac,0xff,0x68,0x16,0xff,0x00,0xc2,0x31,0x2b,0x10,0xa2,0x02,
-0x52,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x1f,0x43,0x42,0x91,0x00,0x00,0x00,0x00,
-0x2b,0x10,0x55,0x00,0x44,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x2f,0x13,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x06,0x14,0x00,0x08,0x00,0x00,0x00,0x00,0x3b,0x00,0x02,0x24,
-0x46,0x00,0x03,0x24,0x1f,0x43,0xa2,0xa0,0x1c,0x43,0xa3,0xa0,0x41,0x00,0x02,0x24,
-0x40,0x00,0x03,0x24,0x1d,0x43,0xa2,0xa0,0xf1,0x13,0x00,0x08,0x1e,0x43,0xa3,0xa0,
-0x00,0x00,0x03,0x8d,0x3f,0x3f,0x02,0x3c,0x3f,0x3f,0x42,0x34,0xa0,0xff,0x62,0x14,
-0x00,0x00,0x00,0x00,0xdf,0x13,0x00,0x08,0x68,0x15,0x45,0x26,0x0f,0x00,0x10,0x3c,
-0x01,0x00,0x11,0x3c,0xff,0xff,0x05,0x36,0xf4,0x98,0x26,0x36,0xba,0x44,0x00,0x0c,
-0x15,0x00,0x04,0x24,0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0xff,0xff,0x05,0x36,
-0x56,0x30,0x26,0x36,0xba,0x44,0x00,0x0c,0x1a,0x00,0x04,0x24,0xb3,0x0a,0x00,0x0c,
-0x64,0x00,0x04,0x24,0x68,0x15,0x43,0x26,0xff,0xff,0x02,0x24,0xd0,0x13,0x00,0x08,
-0x04,0x43,0x62,0xa0,0x0d,0x08,0x22,0x35,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,
-0x0f,0x00,0x63,0x30,0x08,0x00,0x62,0x2c,0x0f,0x00,0x63,0x38,0xa5,0xff,0x40,0x14,
-0x01,0x00,0x65,0x24,0x00,0x16,0x05,0x00,0x00,0x24,0x05,0x00,0x00,0x1a,0x05,0x00,
-0x25,0x10,0x44,0x00,0x25,0x10,0x43,0x00,0x25,0x10,0x45,0x00,0x25,0x18,0x65,0x00,
-0x18,0x43,0x43,0xad,0x35,0x14,0x00,0x08,0x14,0x43,0x42,0xad,0x04,0x00,0x02,0x24,
-0x0d,0x00,0x62,0x12,0xff,0x00,0x02,0x24,0x67,0xff,0x62,0x16,0xff,0x00,0xa2,0x31,
-0x2b,0x10,0xa2,0x02,0x1d,0x00,0x40,0x14,0xff,0x00,0xc2,0x31,0x2b,0x10,0xa2,0x02,
-0x0a,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xfb,0x12,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x06,0x14,0x00,0x08,0x00,0x00,0x00,0x00,0x1d,0x43,0x42,0x91,0x00,0x00,0x00,0x00,
-0x2b,0x10,0x55,0x00,0xf8,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0xc5,0x12,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x06,0x14,0x00,0x08,0x00,0x00,0x00,0x00,0x20,0x43,0x42,0x91,
-0x00,0x00,0x00,0x00,0x2b,0x10,0xa2,0x02,0xac,0xff,0x40,0x10,0x00,0x00,0x00,0x00,
-0x70,0x13,0x00,0x0c,0x00,0x00,0x00,0x00,0x06,0x14,0x00,0x08,0x00,0x00,0x00,0x00,
-0x2b,0x10,0xa2,0x02,0xe8,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x21,0x43,0x42,0x91,
-0x00,0x00,0x00,0x00,0x2b,0x10,0x55,0x00,0xa0,0xff,0x40,0x14,0x00,0x00,0x00,0x00,
-0x70,0x13,0x00,0x0c,0x00,0x00,0x00,0x00,0x06,0x14,0x00,0x08,0x00,0x00,0x00,0x00,
-0x02,0x80,0x08,0x3c,0x68,0x15,0x05,0x25,0xdc,0x63,0xa4,0x8c,0xe6,0x42,0xa3,0x90,
-0x02,0x11,0x04,0x00,0x1f,0x00,0x60,0x14,0x7f,0x00,0x46,0x30,0x25,0xb0,0x07,0x3c,
-0x4c,0x00,0xe2,0x34,0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x19,0x00,0x60,0x10,
-0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x34,0x16,0x00,0x82,0x10,0x00,0x00,0x00,0x00,
-0x00,0x08,0xe3,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,
-0x12,0x00,0x40,0x10,0x4b,0x00,0xc2,0x2c,0x29,0x00,0x40,0x10,0x01,0x00,0x04,0x24,
-0xd8,0xff,0xc2,0x24,0x1e,0x00,0x42,0x2c,0x2f,0x00,0x40,0x10,0x23,0x00,0xc2,0x2c,
-0x68,0x15,0x04,0x25,0xd3,0x42,0x82,0x90,0x00,0x00,0x00,0x00,0x29,0x00,0x40,0x10,
-0x25,0xb0,0x02,0x3c,0x20,0x00,0x03,0x24,0x87,0x0c,0x42,0x34,0x00,0x00,0x43,0xa0,
-0xd3,0x42,0x80,0xa0,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x0f,0x00,0x40,0x10,
-0x01,0x00,0x04,0x24,0xd8,0xff,0xc2,0x24,0x1e,0x00,0x42,0x2c,0x2c,0x00,0x40,0x10,
-0x23,0x00,0xc2,0x2c,0x68,0x15,0x04,0x25,0xd3,0x42,0x82,0x90,0x00,0x00,0x00,0x00,
-0x26,0x00,0x40,0x10,0x25,0xb0,0x02,0x3c,0x44,0x00,0x03,0x24,0x30,0x0c,0x42,0x34,
-0x00,0x00,0x43,0xa0,0xed,0x14,0x00,0x08,0xd3,0x42,0x80,0xa0,0xd3,0x42,0xa2,0x90,
-0x00,0x00,0x00,0x00,0xef,0xff,0x44,0x10,0x30,0x0c,0xe3,0x34,0x43,0x00,0x02,0x24,
-0xd3,0x42,0xa4,0xa0,0x00,0x00,0x62,0xa0,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0xd3,0x42,0xa2,0x90,0x00,0x00,0x00,0x00,0xd5,0xff,0x44,0x10,0x87,0x0c,0xe3,0x34,
-0x10,0x00,0x02,0x24,0xd3,0x42,0xa4,0xa0,0x00,0x00,0x62,0xa0,0x06,0x15,0x00,0x08,
-0x00,0x00,0x00,0x00,0x23,0x00,0xc2,0x2c,0xda,0xff,0x40,0x10,0x00,0x00,0x00,0x00,
-0x68,0x15,0x04,0x25,0xd3,0x42,0x82,0x90,0x02,0x00,0x03,0x24,0xd5,0xff,0x43,0x10,
-0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,0x87,0x0c,0x42,0x34,0xd3,0x42,0x83,0xa0,
-0x00,0x00,0x40,0xa0,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x23,0x00,0xc2,0x2c,
-0xcc,0xff,0x40,0x10,0x00,0x00,0x00,0x00,0x68,0x15,0x04,0x25,0xd3,0x42,0x82,0x90,
-0x02,0x00,0x03,0x24,0xc7,0xff,0x43,0x10,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,
-0xd3,0x42,0x83,0xa0,0x30,0x0c,0x42,0x34,0x42,0x00,0x03,0x24,0x00,0x00,0x43,0xa0,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x02,0x80,0x02,0x3c,0x68,0x15,0x45,0x24,
-0xd5,0x42,0xa3,0x90,0x02,0x00,0x02,0x24,0x03,0x00,0x62,0x10,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xdc,0x63,0xa2,0x8c,0x25,0xb0,0x03,0x3c,
-0x0a,0x0a,0x68,0x34,0x02,0x11,0x02,0x00,0x7f,0x00,0x42,0x30,0x1a,0x00,0x44,0x2c,
-0x14,0x00,0x42,0x2c,0x01,0x0a,0x66,0x34,0x0b,0x00,0x40,0x14,0x2e,0x0a,0x67,0x34,
-0xf3,0xff,0x80,0x14,0x00,0x00,0x00,0x00,0xd4,0x42,0xa4,0x90,0x01,0x00,0x02,0x24,
-0x01,0x0a,0x67,0x34,0x0f,0x00,0x82,0x10,0x2e,0x0a,0x66,0x34,0xd4,0x42,0xa0,0xa0,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x40,0x00,0x02,0x24,0x00,0x00,0xc2,0xa0,
-0x01,0x00,0x03,0x24,0xdf,0xff,0x02,0x24,0xd4,0x42,0xa3,0xa0,0x00,0x00,0xe2,0xa0,
-0x03,0x00,0x03,0x24,0x21,0x10,0x00,0x00,0x00,0x00,0x03,0xa1,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x47,0x00,0x02,0x24,0x00,0x00,0xe2,0xa0,0xd3,0xff,0x03,0x24,
-0x83,0xff,0x02,0x24,0x00,0x00,0xc3,0xa0,0x00,0x00,0x02,0xa1,0x48,0x15,0x00,0x08,
-0xd4,0x42,0xa0,0xa0,0xd0,0xff,0xbd,0x27,0x1c,0x00,0xb1,0xaf,0x28,0x00,0xbf,0xaf,
-0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x18,0x00,0xb0,0xaf,0xff,0xff,0x11,0x24,
-0x02,0x80,0x13,0x3c,0x41,0xb0,0x02,0x3c,0x68,0x15,0x66,0x26,0x04,0x00,0x42,0x34,
-0x00,0x00,0x47,0x8c,0x00,0x4b,0xc5,0x8c,0x02,0x80,0x03,0x3c,0x96,0x7d,0x64,0x90,
-0xfc,0x4a,0xc8,0x8c,0x02,0x80,0x02,0x3c,0xb8,0x7d,0x49,0x90,0x25,0xb0,0x0a,0x3c,
-0x25,0x90,0xa7,0x00,0xb0,0x03,0x42,0x35,0x00,0x00,0x52,0xac,0x00,0x24,0x04,0x00,
-0x00,0x00,0x48,0xac,0x84,0x02,0x43,0x35,0x8c,0x02,0x45,0x35,0x01,0x00,0x02,0x24,
-0x00,0x00,0x72,0xac,0x00,0x00,0xa4,0xac,0xb9,0x04,0x22,0x11,0x00,0x4b,0xd2,0xac,
-0x68,0x15,0x66,0x26,0xfc,0x4a,0xc2,0x8c,0x00,0x00,0x00,0x00,0x24,0x28,0x52,0x00,
-0x01,0x00,0xa3,0x30,0x09,0x00,0x60,0x10,0x04,0x00,0xa2,0x30,0x00,0x4b,0xc2,0x8c,
-0x25,0xb0,0x03,0x3c,0x01,0x00,0x04,0x24,0x01,0x00,0x42,0x38,0xb0,0x03,0x63,0x34,
-0x00,0x00,0x64,0xac,0x00,0x4b,0xc2,0xac,0x04,0x00,0xa2,0x30,0x09,0x00,0x40,0x10,
-0x08,0x00,0xa2,0x30,0x00,0x4b,0xc2,0x8c,0x25,0xb0,0x03,0x3c,0x04,0x00,0x04,0x24,
-0x04,0x00,0x42,0x38,0xb0,0x03,0x63,0x34,0x00,0x00,0x64,0xac,0x00,0x4b,0xc2,0xac,
-0x08,0x00,0xa2,0x30,0x0e,0x00,0x40,0x10,0x68,0x15,0x64,0x26,0xc9,0x64,0xc2,0x90,
-0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x18,0x2a,0xb0,0x02,0x3c,0x02,0x00,0x03,0x24,
-0x01,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0xc9,0x64,0xc0,0xa0,0x00,0x4b,0xc2,0x8c,
-0x00,0x00,0x00,0x00,0x08,0x00,0x42,0x38,0x00,0x4b,0xc2,0xac,0x68,0x15,0x64,0x26,
-0xfc,0x4a,0x82,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,0x10,0x00,0x42,0x30,
-0x0d,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xc9,0x64,0x82,0x90,0x00,0x00,0x00,0x00,
-0x05,0x00,0x40,0x18,0x2a,0xb0,0x02,0x3c,0x02,0x00,0x03,0x24,0x01,0x00,0x42,0x34,
-0x00,0x00,0x43,0xa0,0xc9,0x64,0x80,0xa0,0x00,0x4b,0x82,0x8c,0x00,0x00,0x00,0x00,
-0x10,0x00,0x42,0x38,0x00,0x4b,0x82,0xac,0x68,0x15,0x64,0x26,0xfc,0x4a,0x82,0x8c,
-0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,0x20,0x00,0x42,0x30,0x0e,0x00,0x40,0x10,
-0x00,0x00,0x00,0x00,0xc9,0x64,0x82,0x90,0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x18,
-0x2a,0xb0,0x02,0x3c,0x02,0x00,0x03,0x24,0x01,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,
-0xc9,0x64,0x80,0xa0,0x00,0x4b,0x82,0x8c,0x00,0x00,0x00,0x00,0x20,0x00,0x42,0x38,
-0x00,0x4b,0x82,0xac,0x68,0x15,0x64,0x26,0xfc,0x4a,0x82,0x8c,0x00,0x00,0x00,0x00,
-0x24,0x10,0x52,0x00,0x40,0x00,0x42,0x30,0x0d,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
-0xc9,0x64,0x82,0x90,0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x18,0x2a,0xb0,0x02,0x3c,
-0x02,0x00,0x03,0x24,0x01,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0xc9,0x64,0x80,0xa0,
-0x00,0x4b,0x82,0x8c,0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x38,0x00,0x4b,0x82,0xac,
-0x68,0x15,0x64,0x26,0xfc,0x4a,0x82,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,
-0x80,0x00,0x42,0x30,0x0e,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xc9,0x64,0x82,0x90,
-0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x18,0x2a,0xb0,0x02,0x3c,0x02,0x00,0x03,0x24,
-0x01,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0xc9,0x64,0x80,0xa0,0x00,0x4b,0x82,0x8c,
-0x00,0x00,0x00,0x00,0x80,0x00,0x42,0x38,0x00,0x4b,0x82,0xac,0x68,0x15,0x64,0x26,
-0xfc,0x4a,0x82,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,0x00,0x01,0x42,0x30,
-0x0d,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xc9,0x64,0x82,0x90,0x00,0x00,0x00,0x00,
-0x05,0x00,0x40,0x18,0x2a,0xb0,0x02,0x3c,0x02,0x00,0x03,0x24,0x01,0x00,0x42,0x34,
-0x00,0x00,0x43,0xa0,0xc9,0x64,0x80,0xa0,0x00,0x4b,0x82,0x8c,0x00,0x00,0x00,0x00,
-0x00,0x01,0x42,0x38,0x00,0x4b,0x82,0xac,0x68,0x15,0x64,0x26,0xfc,0x4a,0x82,0x8c,
-0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,0x00,0x02,0x42,0x30,0x0e,0x00,0x40,0x10,
-0x00,0x00,0x00,0x00,0xc9,0x64,0x82,0x90,0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x18,
-0x2a,0xb0,0x02,0x3c,0x02,0x00,0x03,0x24,0x01,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,
-0xc9,0x64,0x80,0xa0,0x00,0x4b,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x02,0x42,0x38,
-0x00,0x4b,0x82,0xac,0x68,0x15,0x64,0x26,0xfc,0x4a,0x82,0x8c,0x00,0x00,0x00,0x00,
-0x24,0x10,0x52,0x00,0x00,0x04,0x42,0x30,0x0d,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
-0xc9,0x64,0x82,0x90,0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x18,0x2a,0xb0,0x02,0x3c,
-0x02,0x00,0x03,0x24,0x01,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0xc9,0x64,0x80,0xa0,
-0x00,0x4b,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x04,0x42,0x38,0x00,0x4b,0x82,0xac,
-0x68,0x15,0x63,0x26,0xfc,0x4a,0x62,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,
-0x00,0x08,0x42,0x30,0x3a,0x00,0x40,0x10,0x2a,0xb0,0x05,0x3c,0x00,0x00,0xa8,0x8c,
-0xff,0x00,0x02,0x24,0xff,0x00,0x04,0x31,0x31,0x00,0x82,0x10,0x00,0x80,0x02,0x31,
-0x08,0x04,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x02,0x01,
-0x05,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0xc9,0x64,0x62,0x90,0x00,0x00,0x00,0x00,
-0x0b,0x00,0x40,0x18,0xff,0x00,0x02,0x24,0x08,0x64,0x62,0x90,0x20,0xb0,0x03,0x3c,
-0x00,0x12,0x02,0x00,0x21,0x10,0x43,0x00,0x0c,0x00,0x48,0x8c,0x25,0xb0,0x03,0x3c,
-0xb0,0x03,0x63,0x34,0x00,0x00,0x68,0xac,0xff,0x00,0x04,0x31,0xff,0x00,0x02,0x24,
-0x1a,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x03,0x31,0xc0,0x64,0x05,0x8e,
-0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,
-0x54,0x64,0x03,0xae,0x21,0x20,0x00,0x00,0x08,0x64,0x08,0xa2,0x20,0x00,0x07,0x24,
-0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0xfc,0x4a,0x05,0x8e,0x02,0x80,0x06,0x3c,
-0x6c,0x7e,0xc4,0x8c,0xff,0xc7,0x02,0x24,0x24,0x28,0xa2,0x00,0x25,0xb0,0x02,0x3c,
-0x04,0x00,0x84,0x34,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,
-0x00,0x00,0x65,0xac,0x6c,0x7e,0xc4,0xac,0xfc,0x4a,0x05,0xae,0x68,0x15,0x63,0x26,
-0x00,0x4b,0x62,0x8c,0x00,0x00,0x00,0x00,0x00,0x08,0x42,0x38,0x00,0x4b,0x62,0xac,
-0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,
-0x00,0x10,0x42,0x30,0x38,0x00,0x40,0x10,0x2a,0xb0,0x02,0x3c,0x08,0x00,0x43,0x34,
-0x00,0x00,0x68,0x8c,0xff,0x00,0x02,0x24,0xff,0x00,0x04,0x31,0x2c,0x00,0x82,0x10,
-0x00,0x80,0x02,0x31,0xca,0x03,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,
-0x24,0x10,0x02,0x01,0x0b,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x10,0x64,0xa2,0x90,
-0x20,0xb0,0x03,0x3c,0x00,0x12,0x02,0x00,0x21,0x10,0x43,0x00,0x0c,0x00,0x48,0x8c,
-0x25,0xb0,0x03,0x3c,0xb0,0x03,0x63,0x34,0x00,0x00,0x68,0xac,0xff,0x00,0x04,0x31,
-0xff,0x00,0x02,0x24,0x1a,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x03,0x31,
-0xd8,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
-0x21,0x30,0x60,0x00,0x6c,0x64,0x03,0xae,0x01,0x00,0x04,0x24,0x10,0x64,0x08,0xa2,
-0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0xfc,0x4a,0x05,0x8e,
-0x02,0x80,0x06,0x3c,0x6c,0x7e,0xc4,0x8c,0xff,0xc7,0x02,0x24,0x24,0x28,0xa2,0x00,
-0x25,0xb0,0x02,0x3c,0x10,0x00,0x84,0x34,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,
-0x00,0x00,0x44,0xac,0x00,0x00,0x65,0xac,0x6c,0x7e,0xc4,0xac,0xfc,0x4a,0x05,0xae,
-0x68,0x15,0x63,0x26,0x00,0x4b,0x62,0x8c,0x00,0x00,0x00,0x00,0x00,0x10,0x42,0x38,
-0x00,0x4b,0x62,0xac,0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x00,0x00,0x00,0x00,
-0x24,0x10,0x52,0x00,0x00,0x20,0x42,0x30,0x37,0x00,0x40,0x10,0x2a,0xb0,0x02,0x3c,
-0x04,0x00,0x43,0x34,0x00,0x00,0x68,0x8c,0xff,0x00,0x02,0x24,0xff,0x00,0x04,0x31,
-0xab,0x03,0x82,0x10,0x00,0x80,0x02,0x31,0x90,0x03,0x40,0x14,0x00,0x80,0x02,0x3c,
-0x00,0xff,0x02,0x3c,0x24,0x10,0x02,0x01,0x0b,0x00,0x40,0x10,0xff,0x00,0x02,0x24,
-0x0c,0x64,0xa2,0x90,0x20,0xb0,0x03,0x3c,0x00,0x12,0x02,0x00,0x21,0x10,0x43,0x00,
-0x0c,0x00,0x48,0x8c,0x25,0xb0,0x03,0x3c,0xb0,0x03,0x63,0x34,0x00,0x00,0x68,0xac,
-0xff,0x00,0x04,0x31,0xff,0x00,0x02,0x24,0x1a,0x00,0x82,0x10,0xff,0x00,0x03,0x31,
-0x68,0x15,0x70,0x26,0xcc,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,
-0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0x60,0x64,0x03,0xae,0x01,0x00,0x04,0x24,
-0x0c,0x64,0x08,0xa2,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
-0xfc,0x4a,0x05,0x8e,0x02,0x80,0x06,0x3c,0x6c,0x7e,0xc4,0x8c,0xff,0xc7,0x02,0x24,
-0x24,0x28,0xa2,0x00,0x25,0xb0,0x02,0x3c,0x20,0x00,0x84,0x34,0x80,0x03,0x42,0x34,
-0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x65,0xac,0x6c,0x7e,0xc4,0xac,
-0xfc,0x4a,0x05,0xae,0x68,0x15,0x63,0x26,0x00,0x4b,0x62,0x8c,0x00,0x00,0x00,0x00,
-0x00,0x20,0x42,0x38,0x00,0x4b,0x62,0xac,0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,
-0x00,0x00,0x00,0x00,0x24,0x10,0x52,0x00,0x00,0x80,0x42,0x30,0x59,0x00,0x40,0x10,
-0x2a,0xb0,0x06,0x3c,0x0c,0x00,0xc3,0x34,0x00,0x00,0x68,0x8c,0xff,0x00,0x07,0x24,
-0xff,0x00,0x04,0x31,0x78,0x03,0x87,0x10,0x00,0x80,0x02,0x31,0x24,0x00,0x40,0x14,
-0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x02,0x01,0x22,0x00,0x40,0x10,
-0xff,0x00,0x02,0x24,0x40,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,
-0xff,0x00,0x44,0x30,0x0f,0x00,0x87,0x10,0x68,0x15,0x62,0x26,0xe8,0x63,0xa4,0xa0,
-0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x09,0x00,0x83,0x10,
-0x68,0x15,0x62,0x26,0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,
-0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0xe8,0x63,0xe3,0xa0,
-0x68,0x15,0x62,0x26,0xe8,0x63,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,
-0x21,0x18,0x62,0x00,0x0c,0x00,0x68,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,
-0xff,0x00,0x04,0x31,0x00,0x00,0x48,0xac,0x16,0x17,0x00,0x08,0xff,0x00,0x02,0x24,
-0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,0x24,0x00,0x82,0x10,0x68,0x15,0x70,0x26,
-0xff,0x00,0x03,0x31,0x90,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,
-0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0xe8,0x63,0x08,0xa2,0x24,0x64,0x03,0xae,
-0x03,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
-0x02,0x80,0x0a,0x3c,0x7c,0x7e,0x47,0x91,0x02,0x80,0x09,0x3c,0x6c,0x7e,0x25,0x8d,
-0xfc,0x4a,0x06,0x8e,0x01,0x00,0x08,0x3c,0x80,0xff,0x02,0x24,0x25,0x38,0xe2,0x00,
-0x00,0x80,0x03,0x35,0x80,0x00,0xa5,0x34,0x27,0x18,0x03,0x00,0x00,0x26,0x07,0x00,
-0x25,0xb0,0x02,0x3c,0x24,0x30,0xc3,0x00,0x25,0x20,0x85,0x00,0x80,0x03,0x42,0x34,
-0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x27,0x88,0x08,0x00,0x00,0x00,0x66,0xac,
-0x6c,0x7e,0x25,0xad,0x7c,0x7e,0x47,0xa1,0xfc,0x4a,0x06,0xae,0x68,0x15,0x63,0x26,
-0x00,0x4b,0x62,0x8c,0x00,0x00,0x00,0x00,0x00,0x80,0x42,0x38,0x00,0x4b,0x62,0xac,
-0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x01,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,
-0x24,0x10,0x51,0x00,0x24,0x10,0x43,0x00,0x56,0x00,0x40,0x10,0x2a,0xb0,0x06,0x3c,
-0x10,0x00,0xc3,0x34,0x00,0x00,0x68,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x04,0x31,
-0x23,0x03,0x87,0x10,0x25,0xb0,0x02,0x3c,0x00,0x80,0x02,0x31,0x23,0x00,0x40,0x14,
-0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x02,0x01,0x21,0x00,0x40,0x10,
-0xff,0x00,0x02,0x24,0x41,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,
-0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,0xec,0x63,0xa4,0xa0,
-0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,
-0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,
-0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0xec,0x63,0xe3,0xa0,0x68,0x15,0x62,0x26,
-0xec,0x63,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
-0x0c,0x00,0x68,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x04,0x31,
-0x00,0x00,0x48,0xac,0x75,0x17,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,
-0xff,0x00,0x02,0x24,0x22,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x03,0x31,
-0x90,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
-0x21,0x30,0x60,0x00,0xec,0x63,0x08,0xa2,0x24,0x64,0x03,0xae,0x03,0x00,0x04,0x24,
-0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x09,0x3c,
-0x7c,0x7e,0x27,0x91,0x02,0x80,0x08,0x3c,0x6c,0x7e,0x05,0x8d,0xfc,0x4a,0x06,0x8e,
-0x01,0x00,0x02,0x3c,0x00,0x80,0x42,0x34,0x40,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,
-0x24,0x30,0xc2,0x00,0x80,0x00,0xa5,0x34,0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,
-0x25,0x20,0x85,0x00,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,
-0x00,0x00,0x66,0xac,0x6c,0x7e,0x05,0xad,0x7c,0x7e,0x27,0xa1,0xfc,0x4a,0x06,0xae,
-0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c,0x01,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,
-0x00,0x4b,0x43,0xac,0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x02,0x00,0x03,0x3c,
-0x24,0x10,0x52,0x00,0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10,0x2a,0xb0,0x06,0x3c,
-0x14,0x00,0xc3,0x34,0x00,0x00,0x68,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x04,0x31,
-0xcc,0x02,0x87,0x10,0x25,0xb0,0x02,0x3c,0x00,0x80,0x02,0x31,0x23,0x00,0x40,0x14,
-0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x02,0x01,0x21,0x00,0x40,0x10,
-0xff,0x00,0x02,0x24,0x42,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,
-0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,0xf0,0x63,0xa4,0xa0,
-0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,
-0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,
-0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0xf0,0x63,0xe3,0xa0,0x68,0x15,0x62,0x26,
-0xf0,0x63,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
-0x0c,0x00,0x68,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x04,0x31,
-0x00,0x00,0x48,0xac,0xd1,0x17,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,
-0xff,0x00,0x02,0x24,0x25,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x03,0x31,
-0x9c,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
-0x21,0x30,0x60,0x00,0xf0,0x63,0x08,0xa2,0x30,0x64,0x03,0xae,0x04,0x00,0x04,0x24,
-0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x0a,0x3c,
-0x7c,0x7e,0x47,0x91,0x02,0x80,0x09,0x3c,0x6c,0x7e,0x25,0x8d,0xfc,0x4a,0x06,0x8e,
-0x06,0x00,0x02,0x3c,0x20,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,
-0x00,0x01,0xa5,0x34,0x25,0xb0,0x03,0x3c,0x04,0x00,0x02,0x3c,0x00,0x26,0x07,0x00,
-0x26,0x88,0x22,0x02,0xb0,0x03,0x68,0x34,0x25,0x20,0x85,0x00,0x80,0x03,0x63,0x34,
-0x41,0xb0,0x02,0x3c,0x00,0x00,0x64,0xac,0x00,0x00,0x46,0xac,0x6c,0x7e,0x25,0xad,
-0x7c,0x7e,0x47,0xa1,0xfc,0x4a,0x06,0xae,0x00,0x00,0x11,0xad,0x68,0x15,0x62,0x26,
-0x00,0x4b,0x43,0x8c,0x02,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,
-0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x04,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,
-0x24,0x10,0x51,0x00,0x24,0x10,0x43,0x00,0x58,0x00,0x40,0x10,0x25,0xb0,0x03,0x3c,
-0xb0,0x03,0x62,0x34,0x2a,0xb0,0x09,0x3c,0x00,0x00,0x51,0xac,0x18,0x00,0x26,0x35,
-0x00,0x00,0xc8,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x04,0x31,0x3a,0x02,0x87,0x10,
-0x04,0x00,0x02,0x24,0x00,0x80,0x02,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,
-0x00,0xff,0x02,0x3c,0x24,0x10,0x02,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,
-0x43,0x00,0x26,0x35,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,
-0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,0xf4,0x63,0xa4,0xa0,0x00,0x00,0xc2,0x90,
-0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00,
-0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,
-0xff,0x00,0x44,0x30,0xf4,0x63,0xe3,0xa0,0x68,0x15,0x62,0x26,0xf4,0x63,0x43,0x90,
-0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x68,0x8c,
-0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x04,0x31,0x00,0x00,0x48,0xac,
-0x34,0x18,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0xc2,0xac,0xff,0x00,0x02,0x24,
-0x21,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x03,0x31,0x9c,0x64,0x05,0x8e,
-0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,
-0xf4,0x63,0x08,0xa2,0x30,0x64,0x03,0xae,0x04,0x00,0x04,0x24,0x20,0x00,0x07,0x24,
-0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x09,0x3c,0x7c,0x7e,0x27,0x91,
-0x02,0x80,0x08,0x3c,0x6c,0x7e,0x05,0x8d,0xfc,0x4a,0x06,0x8e,0x06,0x00,0x02,0x3c,
-0x10,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,0x00,0x01,0xa5,0x34,
-0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,0x25,0x20,0x85,0x00,0x80,0x03,0x42,0x34,
-0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x66,0xac,0x6c,0x7e,0x05,0xad,
-0x7c,0x7e,0x27,0xa1,0xfc,0x4a,0x06,0xae,0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c,
-0x04,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,0x68,0x15,0x65,0x26,
-0xfc,0x4a,0xa2,0x8c,0x08,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,0x24,0x10,0x43,0x00,
-0x5a,0x00,0x40,0x10,0x2a,0xb0,0x06,0x3c,0x1c,0x00,0xc3,0x34,0x00,0x00,0x68,0x8c,
-0xff,0x00,0x07,0x24,0xff,0x00,0x04,0x31,0x13,0x02,0x87,0x10,0x25,0xb0,0x02,0x3c,
-0x00,0x80,0x02,0x31,0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,
-0x24,0x10,0x02,0x01,0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x44,0x00,0xc6,0x34,
-0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,
-0x68,0x15,0x62,0x26,0xf8,0x63,0xa4,0xa0,0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,
-0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,
-0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,
-0xf8,0x63,0xe3,0xa0,0x68,0x15,0x62,0x26,0xf8,0x63,0x43,0x90,0x20,0xb0,0x02,0x3c,
-0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x0c,0x00,0x68,0x8c,0x25,0xb0,0x02,0x3c,
-0xb0,0x03,0x42,0x34,0xff,0x00,0x04,0x31,0x00,0x00,0x48,0xac,0x8f,0x18,0x00,0x08,
-0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,0x25,0x00,0x82,0x10,
-0x68,0x15,0x70,0x26,0xff,0x00,0x03,0x31,0xa8,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,
-0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0xf8,0x63,0x08,0xa2,
-0x3c,0x64,0x03,0xae,0x05,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,
-0x10,0x00,0xa0,0xaf,0x02,0x80,0x0a,0x3c,0x7c,0x7e,0x47,0x91,0x02,0x80,0x09,0x3c,
-0x6c,0x7e,0x25,0x8d,0xfc,0x4a,0x06,0x8e,0x18,0x00,0x02,0x3c,0x08,0x00,0xe7,0x34,
-0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,0x00,0x02,0xa5,0x34,0x25,0xb0,0x03,0x3c,
-0x10,0x00,0x02,0x3c,0x00,0x26,0x07,0x00,0x26,0x88,0x22,0x02,0xb0,0x03,0x68,0x34,
-0x25,0x20,0x85,0x00,0x80,0x03,0x63,0x34,0x41,0xb0,0x02,0x3c,0x00,0x00,0x64,0xac,
-0x00,0x00,0x46,0xac,0x6c,0x7e,0x25,0xad,0x7c,0x7e,0x47,0xa1,0xfc,0x4a,0x06,0xae,
-0x00,0x00,0x11,0xad,0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c,0x08,0x00,0x04,0x3c,
-0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,
-0x10,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,0x24,0x10,0x51,0x00,0x24,0x10,0x43,0x00,
-0x58,0x00,0x40,0x10,0x25,0xb0,0x06,0x3c,0xb0,0x03,0xc2,0x34,0x2a,0xb0,0x09,0x3c,
-0x00,0x00,0x51,0xac,0x20,0x00,0x23,0x35,0x00,0x00,0x68,0x8c,0xff,0x00,0x07,0x24,
-0xff,0x00,0x04,0x31,0x80,0x01,0x87,0x10,0x90,0x03,0xc2,0x34,0x00,0x80,0x02,0x31,
-0x23,0x00,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x02,0x01,
-0x21,0x00,0x40,0x10,0xff,0x00,0x02,0x24,0x45,0x00,0x26,0x35,0x00,0x00,0xc2,0x90,
-0x00,0x00,0x00,0x00,0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,
-0x04,0x64,0xa4,0xa0,0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,
-0x07,0x00,0x83,0x10,0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,
-0x21,0x18,0x80,0x00,0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0x04,0x64,0xe3,0xa0,
-0x68,0x15,0x62,0x26,0x04,0x64,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,
-0x21,0x18,0x62,0x00,0x0c,0x00,0x68,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,
-0xff,0x00,0x04,0x31,0x00,0x00,0x48,0xac,0xf2,0x18,0x00,0x08,0xff,0x00,0x02,0x24,
-0x00,0x00,0x62,0xac,0xff,0x00,0x02,0x24,0x21,0x00,0x82,0x10,0x68,0x15,0x70,0x26,
-0xff,0x00,0x03,0x31,0xa8,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,
-0x21,0x18,0x62,0x00,0x21,0x30,0x60,0x00,0x04,0x64,0x08,0xa2,0x3c,0x64,0x03,0xae,
-0x05,0x00,0x04,0x24,0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,
-0x02,0x80,0x09,0x3c,0x7c,0x7e,0x27,0x91,0x02,0x80,0x08,0x3c,0x6c,0x7e,0x05,0x8d,
-0xfc,0x4a,0x06,0x8e,0x18,0x00,0x02,0x3c,0x01,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,
-0x24,0x30,0xc2,0x00,0x00,0x02,0xa5,0x34,0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,
-0x25,0x20,0x85,0x00,0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,
-0x00,0x00,0x66,0xac,0x6c,0x7e,0x05,0xad,0x7c,0x7e,0x27,0xa1,0xfc,0x4a,0x06,0xae,
-0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c,0x10,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,
-0x00,0x4b,0x43,0xac,0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x20,0x00,0x03,0x3c,
-0x24,0x10,0x52,0x00,0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10,0x2a,0xb0,0x06,0x3c,
-0x24,0x00,0xc3,0x34,0x00,0x00,0x68,0x8c,0xff,0x00,0x07,0x24,0xff,0x00,0x04,0x31,
-0x28,0x01,0x87,0x10,0x25,0xb0,0x02,0x3c,0x00,0x80,0x02,0x31,0x23,0x00,0x40,0x14,
-0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x02,0x01,0x21,0x00,0x40,0x10,
-0xff,0x00,0x02,0x24,0x46,0x00,0xc6,0x34,0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,
-0xff,0x00,0x44,0x30,0x0e,0x00,0x87,0x10,0x68,0x15,0x62,0x26,0xfc,0x63,0xa4,0xa0,
-0x00,0x00,0xc2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,
-0x21,0x38,0xa0,0x00,0x21,0x28,0xc0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,
-0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0xfc,0x63,0xe3,0xa0,0x68,0x15,0x62,0x26,
-0xfc,0x63,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
-0x0c,0x00,0x68,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x04,0x31,
-0x00,0x00,0x48,0xac,0x4d,0x19,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,
-0xff,0x00,0x02,0x24,0x25,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x03,0x31,
-0xb4,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
-0x21,0x30,0x60,0x00,0xfc,0x63,0x08,0xa2,0x48,0x64,0x03,0xae,0x06,0x00,0x04,0x24,
-0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x0a,0x3c,
-0x7c,0x7e,0x47,0x91,0x02,0x80,0x09,0x3c,0x6c,0x7e,0x25,0x8d,0xfc,0x4a,0x06,0x8e,
-0x60,0x00,0x02,0x3c,0x04,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,
-0x00,0x04,0xa5,0x34,0x25,0xb0,0x03,0x3c,0x40,0x00,0x02,0x3c,0x00,0x26,0x07,0x00,
-0x26,0x88,0x22,0x02,0xb0,0x03,0x68,0x34,0x25,0x20,0x85,0x00,0x80,0x03,0x63,0x34,
-0x41,0xb0,0x02,0x3c,0x00,0x00,0x64,0xac,0x00,0x00,0x46,0xac,0x6c,0x7e,0x25,0xad,
-0x7c,0x7e,0x47,0xa1,0xfc,0x4a,0x06,0xae,0x00,0x00,0x11,0xad,0x68,0x15,0x62,0x26,
-0x00,0x4b,0x43,0x8c,0x20,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,
-0x68,0x15,0x65,0x26,0xfc,0x4a,0xa2,0x8c,0x40,0x00,0x03,0x3c,0x24,0x10,0x52,0x00,
-0x24,0x10,0x51,0x00,0x24,0x10,0x43,0x00,0x5a,0x00,0x40,0x10,0x68,0x15,0x70,0x26,
-0x25,0xb0,0x02,0x3c,0x2a,0xb0,0x07,0x3c,0xb0,0x03,0x42,0x34,0x00,0x00,0x51,0xac,
-0x28,0x00,0xe3,0x34,0x00,0x00,0x68,0x8c,0xff,0x00,0x06,0x24,0xff,0x00,0x04,0x31,
-0xc9,0x00,0x86,0x10,0x25,0xbd,0x02,0x3c,0x00,0x80,0x02,0x31,0x23,0x00,0x40,0x14,
-0x00,0x80,0x02,0x3c,0x00,0xff,0x02,0x3c,0x24,0x10,0x02,0x01,0x21,0x00,0x40,0x10,
-0xff,0x00,0x02,0x24,0x47,0x00,0xe7,0x34,0x00,0x00,0xe2,0x90,0x00,0x00,0x00,0x00,
-0xff,0x00,0x44,0x30,0x0e,0x00,0x86,0x10,0x68,0x15,0x62,0x26,0x00,0x64,0xa4,0xa0,
-0x00,0x00,0xe2,0x90,0xff,0x00,0x83,0x30,0xff,0x00,0x44,0x30,0x07,0x00,0x83,0x10,
-0x21,0x30,0xa0,0x00,0x21,0x28,0xe0,0x00,0x00,0x00,0xa2,0x90,0x21,0x18,0x80,0x00,
-0xfd,0xff,0x62,0x14,0xff,0x00,0x44,0x30,0x00,0x64,0xc3,0xa0,0x68,0x15,0x62,0x26,
-0x00,0x64,0x43,0x90,0x20,0xb0,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
-0x0c,0x00,0x68,0x8c,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0xff,0x00,0x04,0x31,
-0x00,0x00,0x48,0xac,0xb1,0x19,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,
-0xff,0x00,0x02,0x24,0x21,0x00,0x82,0x10,0x68,0x15,0x70,0x26,0xff,0x00,0x03,0x31,
-0xb4,0x64,0x05,0x8e,0x20,0x10,0x02,0x3c,0x00,0x1a,0x03,0x00,0x21,0x18,0x62,0x00,
-0x21,0x30,0x60,0x00,0x00,0x64,0x08,0xa2,0x48,0x64,0x03,0xae,0x06,0x00,0x04,0x24,
-0x20,0x00,0x07,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xa0,0xaf,0x02,0x80,0x09,0x3c,
-0x7c,0x7e,0x27,0x91,0x02,0x80,0x08,0x3c,0x6c,0x7e,0x05,0x8d,0xfc,0x4a,0x06,0x8e,
-0x60,0x00,0x02,0x3c,0x02,0x00,0xe7,0x34,0x27,0x10,0x02,0x00,0x24,0x30,0xc2,0x00,
-0x00,0x04,0xa5,0x34,0x00,0x26,0x07,0x00,0x25,0xb0,0x02,0x3c,0x25,0x20,0x85,0x00,
-0x80,0x03,0x42,0x34,0x41,0xb0,0x03,0x3c,0x00,0x00,0x44,0xac,0x00,0x00,0x66,0xac,
-0x6c,0x7e,0x05,0xad,0x7c,0x7e,0x27,0xa1,0xfc,0x4a,0x06,0xae,0x68,0x15,0x62,0x26,
-0x00,0x4b,0x43,0x8c,0x40,0x00,0x04,0x3c,0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,
-0x68,0x15,0x70,0x26,0xfc,0x4a,0x06,0x8e,0x00,0x04,0x11,0x3c,0x24,0x10,0xd2,0x00,
-0x24,0x10,0x51,0x00,0x4c,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x24,0x28,0xd2,0x00,
-0x00,0x08,0x04,0x3c,0x24,0x10,0xa4,0x00,0x08,0x00,0x40,0x10,0x80,0x00,0x07,0x3c,
-0x00,0x4b,0x03,0x8e,0x25,0xb0,0x02,0x3c,0xb0,0x03,0x42,0x34,0x26,0x18,0x64,0x00,
-0x00,0x00,0x44,0xac,0x00,0x4b,0x03,0xae,0x80,0x00,0x07,0x3c,0x24,0x10,0xa7,0x00,
-0x21,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x00,0x4b,0x03,0x8e,0x25,0xb0,0x08,0x3c,
-0xb0,0x03,0x09,0x35,0x2a,0xb0,0x02,0x3c,0x00,0x00,0x23,0xad,0x36,0x00,0x42,0x34,
-0x00,0x00,0x43,0x90,0x23,0xb0,0x04,0x3c,0xff,0x1f,0x02,0x3c,0xc0,0x18,0x03,0x00,
-0xf0,0x07,0x63,0x30,0x5c,0x65,0x05,0x8e,0x21,0x18,0x64,0x00,0xff,0xff,0x42,0x34,
-0x24,0x18,0x62,0x00,0x59,0x00,0x65,0x10,0x60,0x65,0x03,0xae,0x02,0x80,0x05,0x3c,
-0x6c,0x7e,0xa3,0x8c,0x27,0x20,0x07,0x00,0x24,0x20,0xc4,0x00,0x00,0x08,0x63,0x34,
-0x41,0xb0,0x02,0x3c,0x00,0x00,0x23,0xad,0x00,0x00,0x44,0xac,0x6c,0x7e,0xa3,0xac,
-0xfc,0x4a,0x04,0xae,0x68,0x15,0x62,0x26,0x00,0x4b,0x43,0x8c,0x80,0x00,0x04,0x3c,
-0x26,0x18,0x64,0x00,0x00,0x4b,0x43,0xac,0x68,0x15,0x66,0x26,0xfc,0x4a,0xc3,0x8c,
-0x00,0x01,0x04,0x3c,0x24,0x28,0x72,0x00,0x24,0x10,0xa4,0x00,0x06,0x00,0x40,0x10,
-0x25,0xb0,0x02,0x3c,0x00,0x4b,0xc3,0x8c,0xb0,0x03,0x42,0x34,0x26,0x18,0x64,0x00,
-0x00,0x00,0x44,0xac,0x00,0x4b,0xc3,0xac,0x00,0x02,0x04,0x3c,0x24,0x10,0xa4,0x00,
-0x06,0x00,0x40,0x10,0x25,0xb0,0x03,0x3c,0x00,0x4b,0xc2,0x8c,0xb0,0x03,0x63,0x34,
-0x26,0x10,0x44,0x00,0x00,0x4b,0xc2,0xac,0x00,0x00,0x64,0xac,0x28,0x00,0xbf,0x8f,
-0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,0x18,0x00,0xb0,0x8f,
-0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0x5b,0x4e,0x00,0x0c,0x07,0x00,0x04,0x24,
-0x00,0x4b,0x03,0x8e,0xfc,0x4a,0x06,0x8e,0x25,0xb0,0x02,0x3c,0x26,0x18,0x71,0x00,
-0xb0,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0xdf,0x19,0x00,0x08,0x00,0x4b,0x03,0xae,
-0x56,0x01,0x42,0x35,0x00,0x00,0x43,0x94,0x00,0x00,0x00,0x00,0x44,0xfb,0x60,0x10,
-0x00,0x00,0x00,0x00,0x5b,0x4e,0x00,0x0c,0x07,0x00,0x04,0x24,0x7d,0x15,0x00,0x08,
-0x68,0x15,0x66,0x26,0x00,0x00,0xa2,0xac,0x48,0x16,0x00,0x08,0xff,0x00,0x02,0x24,
-0x00,0x00,0x62,0xac,0x85,0x16,0x00,0x08,0xff,0x00,0x02,0x24,0x00,0x00,0x62,0xac,
-0xc2,0x16,0x00,0x08,0xff,0x00,0x02,0x24,0x90,0x03,0x63,0x34,0x00,0x00,0x62,0xac,
-0x57,0x18,0x00,0x08,0x68,0x15,0x62,0x26,0x00,0x00,0x40,0xac,0x15,0x19,0x00,0x08,
-0x68,0x15,0x62,0x26,0x02,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
-0x74,0x19,0x00,0x08,0x68,0x15,0x62,0x26,0x01,0x00,0x03,0x24,0x90,0x03,0x42,0x34,
-0x00,0x00,0x43,0xac,0xd4,0x19,0x00,0x08,0x68,0x15,0x62,0x26,0xd0,0x03,0x03,0x35,
-0x80,0x00,0x02,0x24,0x00,0x00,0x62,0xac,0x0a,0x1a,0x00,0x08,0x68,0x15,0x62,0x26,
-0x25,0xb0,0x02,0x3c,0x07,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
-0x68,0x15,0x63,0x26,0x00,0x4b,0x62,0x8c,0x00,0x00,0x00,0x00,0x00,0x20,0x42,0x38,
-0xe2,0x16,0x00,0x08,0x00,0x4b,0x62,0xac,0x25,0xb0,0x02,0x3c,0x07,0x00,0x03,0x24,
-0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x68,0x15,0x63,0x26,0x00,0x4b,0x62,0x8c,
-0x00,0x00,0x00,0x00,0x00,0x80,0x42,0x38,0x40,0x17,0x00,0x08,0x00,0x4b,0x62,0xac,
-0x06,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,0x99,0x17,0x00,0x08,
-0x68,0x15,0x62,0x26,0x05,0x00,0x03,0x24,0x90,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
-0xf8,0x17,0x00,0x08,0x68,0x15,0x62,0x26,0x03,0x00,0x03,0x24,0x90,0x03,0x42,0x34,
-0x00,0x00,0x43,0xac,0xb6,0x18,0x00,0x08,0x68,0x15,0x62,0x26,0x25,0xb0,0x0d,0x3c,
-0x00,0x80,0x02,0x3c,0x18,0x03,0xa4,0x35,0xfc,0x69,0x42,0x24,0x02,0x80,0x03,0x3c,
-0x41,0xb0,0x08,0x3c,0x00,0x00,0x82,0xac,0x68,0x15,0x6a,0x24,0x0a,0x00,0x02,0x35,
-0x00,0x00,0x44,0x94,0x0a,0x4b,0x43,0x95,0x08,0x4b,0x4b,0x95,0x25,0x18,0x64,0x00,
-0xff,0xff,0x6c,0x30,0x24,0x10,0x8b,0x01,0x02,0x00,0x42,0x30,0x4d,0x00,0x40,0x10,
-0x02,0x00,0x64,0x38,0x02,0x00,0x02,0x24,0xc0,0x03,0xa3,0x35,0x00,0x00,0x62,0xac,
-0x0a,0x4b,0x44,0xa5,0x24,0x38,0x8b,0x01,0x04,0x00,0xe2,0x30,0x0a,0x00,0x40,0x10,
-0x08,0x00,0xe2,0x30,0x0a,0x4b,0x43,0x95,0x0c,0x00,0x04,0x35,0xc0,0x03,0xa5,0x35,
-0x04,0x00,0x63,0x38,0x04,0x00,0x02,0x24,0x00,0x00,0x86,0x8c,0x00,0x00,0xa2,0xac,
-0x0a,0x4b,0x43,0xa5,0x08,0x00,0xe2,0x30,0x08,0x00,0x40,0x10,0x10,0x00,0xe2,0x30,
-0x0a,0x4b,0x42,0x95,0xc0,0x03,0xa4,0x35,0x08,0x00,0x03,0x24,0x08,0x00,0x42,0x38,
-0x00,0x00,0x83,0xac,0x0a,0x4b,0x42,0xa5,0x10,0x00,0xe2,0x30,0x08,0x00,0x40,0x10,
-0x20,0x00,0xe2,0x30,0x0a,0x4b,0x42,0x95,0xc0,0x03,0xa4,0x35,0x10,0x00,0x03,0x24,
-0x10,0x00,0x42,0x38,0x00,0x00,0x83,0xac,0x0a,0x4b,0x42,0xa5,0x20,0x00,0xe2,0x30,
-0x08,0x00,0x40,0x10,0x80,0x00,0xe2,0x30,0x0a,0x4b,0x42,0x95,0xc0,0x03,0xa4,0x35,
-0x20,0x00,0x03,0x24,0x20,0x00,0x42,0x38,0x00,0x00,0x83,0xac,0x0a,0x4b,0x42,0xa5,
-0x80,0x00,0xe2,0x30,0x15,0x00,0x40,0x10,0x24,0x10,0x8b,0x01,0x02,0x80,0x09,0x3c,
-0x0a,0x4b,0x46,0x95,0x6c,0x7e,0x25,0x8d,0x08,0x00,0x02,0x3c,0x7f,0xff,0x04,0x24,
-0x24,0x20,0x64,0x01,0x25,0x28,0xa2,0x00,0x80,0x00,0xc6,0x38,0xb0,0x03,0xa7,0x35,
-0x08,0x00,0x08,0x35,0xc0,0x03,0xa3,0x35,0x80,0x00,0x02,0x24,0x00,0x00,0x62,0xac,
-0x21,0x58,0x80,0x00,0x00,0x00,0xe5,0xac,0x0a,0x4b,0x46,0xa5,0x6c,0x7e,0x25,0xad,
-0x00,0x00,0x04,0xa5,0x08,0x4b,0x44,0xa5,0x24,0x10,0x8b,0x01,0x00,0x30,0x42,0x30,
-0x06,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x0a,0x4b,0x42,0x95,0x00,0x00,0x00,0x00,
-0x00,0x10,0x42,0x38,0x00,0x20,0x42,0x34,0x0a,0x4b,0x42,0xa5,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x95,0x1a,0x00,0x08,0x0a,0x4b,0x43,0xa5,0xf8,0xff,0xbd,0x27,
-0x04,0x00,0xb1,0xaf,0x00,0x00,0xb0,0xaf,0x00,0x40,0x02,0x40,0x00,0x68,0x08,0x40,
-0x00,0x70,0x02,0x40,0x00,0x60,0x09,0x40,0x25,0xb0,0x05,0x3c,0x00,0x80,0x02,0x3c,
-0x18,0x03,0xa3,0x34,0x7c,0x6b,0x42,0x24,0x00,0x00,0x62,0xac,0x80,0x00,0x87,0x8c,
-0x7c,0x02,0xa2,0x34,0x84,0x02,0xa3,0x34,0x88,0x02,0xa6,0x34,0x00,0x00,0x47,0xac,
-0x00,0x00,0x68,0xac,0x00,0x00,0xc9,0xac,0x74,0x00,0x83,0x8c,0x8c,0x02,0xa2,0x34,
-0x90,0x02,0xa7,0x34,0x00,0x00,0x43,0xac,0x08,0x00,0x86,0x8c,0x94,0x02,0xa8,0x34,
-0x98,0x02,0xa9,0x34,0x00,0x00,0xe6,0xac,0x0c,0x00,0x82,0x8c,0x9c,0x02,0xa6,0x34,
-0xa0,0x02,0xa7,0x34,0x00,0x00,0x02,0xad,0x10,0x00,0x83,0x8c,0xa4,0x02,0xa8,0x34,
-0xa8,0x02,0xaa,0x34,0x00,0x00,0x23,0xad,0x14,0x00,0x82,0x8c,0xac,0x02,0xa9,0x34,
-0xb0,0x02,0xab,0x34,0x00,0x00,0xc2,0xac,0x18,0x00,0x83,0x8c,0xb4,0x02,0xa6,0x34,
-0xb8,0x02,0xac,0x34,0x00,0x00,0xe3,0xac,0x1c,0x00,0x82,0x8c,0xbc,0x02,0xa7,0x34,
-0xc0,0x02,0xad,0x34,0x00,0x00,0x02,0xad,0x20,0x00,0x83,0x8c,0xc4,0x02,0xa8,0x34,
-0xc8,0x02,0xae,0x34,0x00,0x00,0x43,0xad,0x24,0x00,0x82,0x8c,0xcc,0x02,0xaa,0x34,
-0xd0,0x02,0xaf,0x34,0x00,0x00,0x22,0xad,0x28,0x00,0x83,0x8c,0xd4,0x02,0xa9,0x34,
-0xd8,0x02,0xb0,0x34,0x00,0x00,0x63,0xad,0x2c,0x00,0x82,0x8c,0x70,0x02,0xab,0x34,
-0x74,0x02,0xb1,0x34,0x00,0x00,0xc2,0xac,0x30,0x00,0x83,0x8c,0x78,0x02,0xa5,0x34,
-0x00,0x00,0x83,0xad,0x34,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xe2,0xac,
-0x38,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xad,0x3c,0x00,0x82,0x8c,
-0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xad,0x40,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,
-0x00,0x00,0xc3,0xad,0x44,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x42,0xad,
-0x48,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xe3,0xad,0x4c,0x00,0x82,0x8c,
-0x00,0x00,0x00,0x00,0x00,0x00,0x22,0xad,0x50,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,
-0x00,0x00,0x03,0xae,0x54,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xad,
-0x58,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xae,0x5c,0x00,0x82,0x8c,
-0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xac,0x42,0x1b,0x00,0x08,0x00,0x00,0x00,0x00,
-0x00,0x80,0x1b,0x3c,0x10,0x6d,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,
-0x00,0x00,0x5b,0xaf,0x21,0xd8,0xa0,0x03,0x82,0xda,0x1b,0x00,0x80,0xda,0x1b,0x00,
-0x08,0x00,0x7b,0x27,0x04,0x00,0x61,0xaf,0x08,0x00,0x62,0xaf,0x0c,0x00,0x63,0xaf,
-0x10,0x00,0x64,0xaf,0x14,0x00,0x65,0xaf,0x18,0x00,0x66,0xaf,0x1c,0x00,0x67,0xaf,
-0x20,0x00,0x68,0xaf,0x24,0x00,0x69,0xaf,0x28,0x00,0x6a,0xaf,0x2c,0x00,0x6b,0xaf,
-0x30,0x00,0x6c,0xaf,0x34,0x00,0x6d,0xaf,0x38,0x00,0x6e,0xaf,0x3c,0x00,0x6f,0xaf,
-0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40,0x40,0x00,0x70,0xaf,
-0x44,0x00,0x71,0xaf,0x48,0x00,0x72,0xaf,0x4c,0x00,0x73,0xaf,0x50,0x00,0x74,0xaf,
-0x54,0x00,0x75,0xaf,0x58,0x00,0x76,0xaf,0x5c,0x00,0x77,0xaf,0x60,0x00,0x78,0xaf,
-0x64,0x00,0x79,0xaf,0x68,0x00,0x7c,0xaf,0x6c,0x00,0x7d,0xaf,0x70,0x00,0x7e,0xaf,
-0x74,0x00,0x7f,0xaf,0x78,0x00,0x68,0xaf,0x7c,0x00,0x69,0xaf,0x80,0x00,0x6a,0xaf,
-0x00,0x68,0x1a,0x40,0x25,0xb0,0x1b,0x3c,0x1c,0x03,0x7b,0x37,0x00,0x00,0x00,0x00,
-0x00,0x00,0x7a,0xaf,0x7f,0x00,0x5b,0x33,0x30,0x00,0x60,0x13,0x00,0x00,0x00,0x00,
-0x25,0xb0,0x1b,0x3c,0x30,0x03,0x7b,0x37,0x00,0x00,0x00,0x00,0x00,0x00,0x7a,0xaf,
-0x00,0x00,0x00,0x00,0x21,0xd8,0xa0,0x03,0x82,0xda,0x1b,0x00,0x80,0xda,0x1b,0x00,
-0x08,0x00,0x7b,0x27,0x04,0x00,0x61,0xaf,0x08,0x00,0x62,0xaf,0x0c,0x00,0x63,0xaf,
-0x10,0x00,0x64,0xaf,0x14,0x00,0x65,0xaf,0x18,0x00,0x66,0xaf,0x1c,0x00,0x67,0xaf,
-0x20,0x00,0x68,0xaf,0x24,0x00,0x69,0xaf,0x28,0x00,0x6a,0xaf,0x2c,0x00,0x6b,0xaf,
-0x30,0x00,0x6c,0xaf,0x34,0x00,0x6d,0xaf,0x38,0x00,0x6e,0xaf,0x3c,0x00,0x6f,0xaf,
-0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x00,0x70,0x0a,0x40,0x40,0x00,0x70,0xaf,
-0x44,0x00,0x71,0xaf,0x48,0x00,0x72,0xaf,0x4c,0x00,0x73,0xaf,0x50,0x00,0x74,0xaf,
-0x54,0x00,0x75,0xaf,0x58,0x00,0x76,0xaf,0x5c,0x00,0x77,0xaf,0x60,0x00,0x78,0xaf,
-0x64,0x00,0x79,0xaf,0x68,0x00,0x7c,0xaf,0x6c,0x00,0x7d,0xaf,0x70,0x00,0x7e,0xaf,
-0x74,0x00,0x7f,0xaf,0x78,0x00,0x68,0xaf,0x7c,0x00,0x69,0xaf,0x80,0x00,0x6a,0xaf,
-0xdf,0x1a,0x00,0x08,0x21,0x20,0x60,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x08,0x3c,
-0x20,0x03,0x08,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x1a,0xad,0x00,0x04,0x5b,0x33,
-0x0a,0x00,0x60,0x13,0x00,0x00,0x00,0x00,0x00,0x80,0x08,0x3c,0x74,0x55,0x08,0x25,
-0x00,0x00,0x00,0x00,0x25,0xb0,0x1b,0x3c,0x24,0x03,0x7b,0x37,0x00,0x00,0x00,0x00,
-0x00,0x00,0x68,0xaf,0x09,0xf8,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x08,0x5b,0x33,
-0x25,0xb0,0x08,0x3c,0x28,0x03,0x08,0x35,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xad,
-0x06,0x00,0x60,0x13,0x00,0x00,0x00,0x00,0x00,0x80,0x08,0x3c,0xfc,0x69,0x08,0x25,
-0x00,0x00,0x00,0x00,0x09,0xf8,0x00,0x01,0x00,0x00,0x00,0x00,0x02,0x80,0x1a,0x3c,
-0x6c,0x7e,0x5a,0x27,0x04,0x00,0x5b,0x97,0x25,0xb0,0x08,0x3c,0x30,0x03,0x08,0x35,
-0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0xad,0x18,0x00,0x60,0x13,0x00,0x00,0x00,0x00,
-0x08,0xec,0x9b,0x27,0x00,0x00,0x00,0x00,0x04,0x00,0x61,0x8f,0xfc,0x03,0x70,0x7b,
-0x7c,0x00,0x62,0x7b,0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b,0x3c,0x01,0x68,0x7b,
-0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b,0xbc,0x01,0x6c,0x7b,
-0xfc,0x01,0x6e,0x7b,0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b,0xbc,0x02,0x74,0x7b,
-0xfc,0x02,0x76,0x7b,0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b,0xbc,0x03,0x7e,0x7b,
-0x80,0x00,0x7b,0x8f,0x2f,0x1c,0x00,0x08,0x00,0x00,0x00,0x00,0x21,0xd8,0xa0,0x03,
-0x82,0xda,0x1b,0x00,0x80,0xda,0x1b,0x00,0x08,0x00,0x7b,0x27,0x08,0x00,0x5b,0xaf,
-0xfc,0xef,0x9d,0x27,0x00,0x00,0x4a,0x8f,0x00,0x00,0x00,0x00,0x21,0x00,0x40,0x11,
-0x00,0x00,0x00,0x00,0x02,0x80,0x08,0x3c,0xcc,0x7d,0x08,0x25,0x21,0x48,0x00,0x00,
-0x21,0x58,0x00,0x00,0x01,0x00,0x6b,0x25,0x1a,0x00,0x40,0x11,0x24,0x70,0x4b,0x01,
-0x14,0x00,0xc0,0x11,0x01,0x00,0x04,0x24,0x00,0x00,0x00,0x00,0x04,0x00,0x44,0xa3,
-0x26,0x50,0x4b,0x01,0x00,0x00,0x4a,0xaf,0x80,0x80,0x09,0x00,0x21,0x80,0x08,0x02,
-0x00,0x00,0x10,0x8e,0x00,0x00,0x00,0x00,0x09,0xf8,0x00,0x02,0x00,0x00,0x00,0x00,
-0x00,0x80,0x1b,0x3c,0xe8,0x6f,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,
-0x00,0x00,0x5b,0xaf,0x02,0x80,0x1a,0x3c,0x6c,0x7e,0x5a,0x27,0xe1,0xff,0x00,0x10,
-0x00,0x00,0x00,0x00,0x01,0x00,0x29,0x25,0x40,0x58,0x0b,0x00,0xf2,0x1b,0x00,0x08,
-0x00,0x00,0x00,0x00,0x02,0x80,0x1b,0x3c,0x6c,0x7e,0x7b,0x27,0x21,0x60,0x00,0x00,
-0x04,0x00,0x6c,0xa7,0x08,0x00,0x7a,0x8f,0x00,0x00,0x00,0x00,0xf8,0xff,0x5a,0x27,
-0x00,0x00,0x5a,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0x5a,0x27,0x84,0x00,0x44,0x8f,
-0x00,0x00,0x00,0x00,0xf9,0xff,0x80,0x10,0x00,0x00,0x00,0x00,0x04,0x00,0x41,0x8f,
-0xfc,0x03,0x50,0x7b,0x7c,0x00,0x42,0x7b,0xbc,0x00,0x44,0x7b,0xfc,0x00,0x46,0x7b,
-0x3c,0x01,0x48,0x7b,0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x4a,0x7b,
-0xbc,0x01,0x4c,0x7b,0xfc,0x01,0x4e,0x7b,0x3c,0x02,0x50,0x7b,0x7c,0x02,0x52,0x7b,
-0xbc,0x02,0x54,0x7b,0xfc,0x02,0x56,0x7b,0x3c,0x03,0x58,0x7b,0x7c,0x03,0x5c,0x7b,
-0xbc,0x03,0x5e,0x7b,0x80,0x00,0x5b,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0x60,0x03,
-0x10,0x00,0x00,0x42,0x00,0x60,0x05,0x40,0x42,0x28,0x05,0x00,0x40,0x28,0x05,0x00,
-0x00,0x60,0x85,0x40,0x04,0x00,0x81,0xac,0x08,0x00,0x82,0xac,0x0c,0x00,0x83,0xac,
-0x20,0x00,0x88,0xac,0x24,0x00,0x89,0xac,0x28,0x00,0x8a,0xac,0x2c,0x00,0x8b,0xac,
-0x30,0x00,0x8c,0xac,0x34,0x00,0x8d,0xac,0x38,0x00,0x8e,0xac,0x3c,0x00,0x8f,0xac,
-0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,0x40,0x00,0x90,0xac,0x44,0x00,0x91,0xac,
-0x48,0x00,0x92,0xac,0x4c,0x00,0x93,0xac,0x50,0x00,0x94,0xac,0x54,0x00,0x95,0xac,
-0x58,0x00,0x96,0xac,0x5c,0x00,0x97,0xac,0x60,0x00,0x98,0xac,0x64,0x00,0x99,0xac,
-0x68,0x00,0x9c,0xac,0x6c,0x00,0x9d,0xac,0x70,0x00,0x9e,0xac,0x74,0x00,0x9f,0xac,
-0x78,0x00,0x88,0xac,0x7c,0x00,0x89,0xac,0x80,0x00,0x9f,0xac,0xf8,0xff,0x84,0x24,
-0x00,0x00,0x84,0x8c,0x00,0x00,0x00,0x00,0x08,0x00,0x84,0x24,0x84,0x00,0x86,0x8c,
-0x00,0x00,0x00,0x00,0xf9,0xff,0xc0,0x10,0x00,0x00,0x00,0x00,0x21,0xd8,0x80,0x00,
-0x01,0x00,0xba,0x24,0x04,0x00,0x61,0x8f,0xfc,0x03,0x70,0x7b,0x7c,0x00,0x62,0x7b,
-0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b,0x3c,0x01,0x68,0x7b,0x13,0x00,0x00,0x02,
-0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b,0xbc,0x01,0x6c,0x7b,0xfc,0x01,0x6e,0x7b,
-0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b,0xbc,0x02,0x74,0x7b,0xfc,0x02,0x76,0x7b,
-0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b,0xbc,0x03,0x7e,0x7b,0x80,0x00,0x7b,0x8f,
-0x00,0x00,0x00,0x00,0x08,0x00,0x60,0x03,0x00,0x60,0x9a,0x40,0x00,0x60,0x05,0x40,
-0x42,0x28,0x05,0x00,0x40,0x28,0x05,0x00,0x00,0x60,0x85,0x40,0x04,0x00,0x81,0xac,
-0x08,0x00,0x82,0xac,0x0c,0x00,0x83,0xac,0x20,0x00,0x88,0xac,0x24,0x00,0x89,0xac,
-0x28,0x00,0x8a,0xac,0x2c,0x00,0x8b,0xac,0x30,0x00,0x8c,0xac,0x34,0x00,0x8d,0xac,
-0x38,0x00,0x8e,0xac,0x3c,0x00,0x8f,0xac,0x12,0x40,0x00,0x00,0x10,0x48,0x00,0x00,
-0x40,0x00,0x90,0xac,0x44,0x00,0x91,0xac,0x48,0x00,0x92,0xac,0x4c,0x00,0x93,0xac,
-0x50,0x00,0x94,0xac,0x54,0x00,0x94,0xac,0x58,0x00,0x96,0xac,0x5c,0x00,0x96,0xac,
-0x60,0x00,0x98,0xac,0x64,0x00,0x99,0xac,0x68,0x00,0x9c,0xac,0x6c,0x00,0x9d,0xac,
-0x70,0x00,0x9e,0xac,0x78,0x00,0x88,0xac,0x7c,0x00,0x89,0xac,0x80,0x00,0x9f,0xac,
-0x84,0x00,0x80,0xac,0xf8,0xff,0x84,0x24,0x00,0x00,0x84,0x8c,0x00,0x00,0x00,0x00,
-0x08,0x00,0x84,0x24,0x84,0x00,0x86,0x8c,0xfa,0xff,0xc0,0x10,0x00,0x00,0x00,0x00,
-0x21,0xd8,0x80,0x00,0x01,0x00,0xba,0x24,0x04,0x00,0x61,0x8f,0xfc,0x03,0x70,0x7b,
-0x7c,0x00,0x62,0x7b,0xbc,0x00,0x64,0x7b,0xfc,0x00,0x66,0x7b,0x3c,0x01,0x68,0x7b,
-0x13,0x00,0x00,0x02,0x11,0x00,0x20,0x02,0x7c,0x01,0x6a,0x7b,0xbc,0x01,0x6c,0x7b,
-0xfc,0x01,0x6e,0x7b,0x3c,0x02,0x70,0x7b,0x7c,0x02,0x72,0x7b,0xbc,0x02,0x74,0x7b,
-0xfc,0x02,0x76,0x7b,0x3c,0x03,0x78,0x7b,0x7c,0x03,0x7c,0x7b,0xbc,0x03,0x7e,0x7b,
-0x80,0x00,0x7b,0x8f,0x08,0x00,0x60,0x03,0x00,0x60,0x9a,0x40,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0xc6,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x1b,0x3c,0x00,0x00,0x7b,0x27,
-0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,0x00,0x00,0x05,0x24,
-0x03,0x00,0xa4,0x24,0x00,0xa0,0x80,0x40,0x00,0xa0,0x84,0x40,0x01,0x80,0x04,0x3c,
-0x98,0x03,0x84,0x24,0x08,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x01,0x80,0x1b,0x3c,0x98,0x03,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,
-0x00,0x00,0x5b,0xaf,0x02,0x80,0x1a,0x3c,0x00,0x00,0x5a,0x27,0xfc,0x03,0x5d,0x27,
-0x02,0x80,0x1c,0x3c,0x00,0x14,0x9c,0x27,0x00,0xf0,0x08,0x3c,0x00,0x0c,0x08,0x35,
-0x00,0x60,0x88,0x40,0x02,0x80,0x04,0x3c,0x00,0x00,0x84,0x24,0xff,0x7f,0x05,0x3c,
-0xff,0xff,0xa5,0x34,0x24,0x20,0x85,0x00,0x00,0x20,0x84,0x4c,0xff,0xff,0x05,0x34,
-0x21,0x28,0xa4,0x00,0x00,0x28,0x85,0x4c,0x00,0x80,0x04,0x3c,0x00,0x00,0x84,0x24,
-0xff,0x7f,0x05,0x3c,0xff,0xff,0xa5,0x34,0x24,0x20,0x85,0x00,0x00,0x00,0x84,0x4c,
-0xff,0x7f,0x06,0x24,0x21,0x30,0xc4,0x00,0x24,0x30,0xc5,0x00,0x00,0x08,0x86,0x4c,
-0x00,0xa0,0x04,0x40,0x10,0x00,0x84,0x34,0x00,0xa0,0x84,0x40,0x01,0x80,0x1b,0x3c,
-0x24,0x04,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,
-0x00,0x00,0x00,0x00,0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x85,0x84,
-0x20,0x00,0x06,0x24,0x25,0x28,0xa6,0x00,0x00,0x00,0x85,0xa4,0x01,0x80,0x1b,0x3c,
-0x54,0x04,0x7b,0x27,0x25,0xb0,0x1a,0x3c,0x18,0x03,0x5a,0x27,0x00,0x00,0x5b,0xaf,
-0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x85,0x8c,0x00,0x00,0x00,0x00,
-0x10,0x00,0xa5,0x30,0xfc,0xff,0xa0,0x10,0x00,0x00,0x00,0x00,0xff,0x1f,0x07,0x3c,
-0xff,0xff,0xe7,0x34,0x02,0x80,0x05,0x3c,0x88,0x7d,0xa5,0x24,0xff,0xff,0xa5,0x30,
-0x40,0xb0,0x04,0x3c,0x25,0x28,0xa4,0x00,0x24,0x28,0xa7,0x00,0x21,0x30,0x00,0x00,
-0x43,0xb0,0x02,0x3c,0x00,0x80,0x04,0x3c,0x40,0x00,0x84,0x34,0x00,0x00,0x45,0xac,
-0x04,0x00,0x46,0xac,0x08,0x00,0x44,0xac,0x4e,0x58,0x00,0x08,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x09,0x00,0x02,0x24,0xff,0xff,0x42,0x24,
-0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0x08,0x00,0xe0,0x03,0x01,0x00,0x42,0x24,
-0x00,0x60,0x02,0x40,0x01,0x00,0x41,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x82,0xac,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
-0x21,0x18,0x40,0x00,0x00,0x60,0x83,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x82,0xac,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
-0x00,0x60,0x81,0x40,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,
-0x25,0xb0,0x02,0x3c,0x44,0x05,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
-0x04,0x00,0x85,0x8c,0x00,0x80,0x03,0x3c,0x01,0x00,0x02,0x24,0x25,0x28,0xa3,0x00,
-0x00,0x00,0xa4,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,
-0x25,0xb0,0x02,0x3c,0x74,0x05,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
-0x04,0x00,0x82,0x8c,0x02,0x00,0x83,0x94,0x00,0x80,0x07,0x3c,0x25,0x28,0x47,0x00,
-0x00,0x00,0xa2,0x8c,0x10,0x00,0x02,0x24,0x13,0x00,0x62,0x10,0x11,0x00,0x66,0x28,
-0x06,0x00,0xc0,0x10,0x20,0x00,0x02,0x24,0x08,0x00,0x02,0x24,0x17,0x00,0x62,0x10,
-0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0xfd,0xff,0x62,0x14,
-0x00,0x00,0x00,0x00,0x08,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xa3,0xac,
-0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x25,0x10,0x47,0x00,0x00,0x00,0x42,0x8c,
-0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,
-0x00,0x00,0xa2,0xa4,0x04,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,0x25,0x18,0x67,0x00,
-0x00,0x00,0x62,0x94,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0x82,0x8c,
-0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0xa0,0x04,0x00,0x83,0x8c,0x00,0x00,0x00,0x00,
-0x25,0x18,0x67,0x00,0x00,0x00,0x62,0x90,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
-0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c,0x1c,0x00,0xbf,0xaf,
-0x18,0x00,0xb2,0xaf,0x10,0x00,0xb0,0xaf,0x68,0x15,0x31,0x26,0xe4,0x64,0x30,0x96,
-0x02,0x80,0x02,0x3c,0x01,0x80,0x03,0x3c,0x25,0x80,0x02,0x02,0x25,0xb0,0x02,0x3c,
-0x38,0x06,0x63,0x24,0x18,0x03,0x42,0x34,0x60,0x00,0x04,0x26,0x80,0x00,0x05,0x26,
-0x00,0x00,0x43,0xac,0xab,0x45,0x00,0x0c,0x03,0x00,0x06,0x24,0x21,0x20,0x00,0x02,
-0x21,0x28,0x00,0x00,0x97,0x45,0x00,0x0c,0x08,0x00,0x06,0x24,0xe4,0x64,0x22,0x8e,
-0x0c,0x00,0x03,0x24,0x0c,0x00,0x43,0xae,0x08,0x00,0x42,0xae,0x12,0x00,0x02,0x24,
-0x14,0x00,0x42,0xae,0x21,0x20,0x40,0x02,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x8b,0x07,0x00,0x08,0x20,0x00,0xbd,0x27,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
-0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,0x02,0x80,0x02,0x3c,0x21,0x48,0x80,0x00,
-0x68,0x15,0x48,0x24,0x21,0x38,0x00,0x00,0x21,0x28,0x27,0x01,0x00,0x00,0xa2,0x90,
-0x21,0x20,0xe8,0x00,0x01,0x00,0xe7,0x24,0x38,0x4c,0x82,0xa0,0x1e,0x00,0xa3,0x90,
-0x1e,0x00,0xe6,0x28,0x56,0x4c,0x83,0xa0,0x3c,0x00,0xa2,0x90,0x00,0x00,0x00,0x00,
-0x74,0x4c,0x82,0xa0,0x5a,0x00,0xa3,0x90,0xf3,0xff,0xc0,0x14,0x92,0x4c,0x83,0xa0,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
-0x20,0xbd,0x03,0x3c,0x58,0x00,0x63,0x34,0x00,0x00,0x62,0x90,0x0f,0x27,0x07,0x24,
-0x20,0x00,0x42,0x34,0x00,0x00,0x62,0xa0,0xff,0xff,0xe7,0x24,0xff,0xff,0xe1,0x04,
-0xff,0xff,0xe7,0x24,0x62,0xbd,0x04,0x3c,0x24,0x10,0x82,0x34,0x00,0x00,0x40,0xa0,
-0x28,0x10,0x83,0x34,0x0c,0x11,0x86,0x34,0x0e,0x00,0x02,0x24,0x00,0x00,0x60,0xa0,
-0x00,0x11,0x85,0x34,0x00,0x00,0xc2,0xa0,0x00,0x00,0xa7,0x8c,0xdf,0xff,0x02,0x24,
-0x10,0x00,0x86,0x34,0x24,0x38,0xe2,0x00,0x49,0x0c,0x03,0x24,0xcf,0xff,0x02,0x24,
-0x00,0x00,0xc3,0xac,0x04,0x00,0x84,0x34,0x00,0x00,0xa7,0xac,0x24,0x38,0xe2,0x00,
-0x41,0x0c,0x02,0x24,0x00,0x00,0xa7,0xac,0x00,0x00,0x80,0xac,0x00,0x00,0xc2,0xac,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0xd0,0xff,0xbd,0x27,0x25,0xb0,0x03,0x3c,
-0x01,0x80,0x02,0x3c,0xb0,0x03,0x68,0x34,0x1c,0x00,0xb1,0xaf,0x18,0x03,0x63,0x34,
-0xd8,0xff,0x91,0x24,0xa0,0x08,0x42,0x24,0x00,0x00,0x62,0xac,0x28,0x00,0xbf,0xaf,
-0x00,0x00,0x11,0xad,0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x18,0x00,0xb0,0xaf,
-0x02,0x80,0x13,0x3c,0x00,0x00,0x23,0x96,0x68,0x15,0x73,0x26,0xff,0xff,0x32,0x32,
-0x40,0x10,0x02,0x3c,0x78,0x64,0x65,0x8e,0x25,0x90,0x42,0x02,0x02,0x80,0x10,0x3c,
-0x8c,0x96,0x10,0x26,0x20,0x00,0x42,0x26,0x00,0x00,0x03,0xad,0x20,0x00,0x06,0x24,
-0x00,0x00,0x02,0xad,0x21,0x38,0x00,0x02,0x0c,0x00,0x03,0xae,0x0a,0x00,0x04,0x24,
-0x64,0x01,0x00,0x0c,0x08,0x00,0x02,0xae,0x04,0x00,0x23,0x8e,0xff,0xe0,0x02,0x24,
-0x28,0x00,0x04,0x24,0x24,0x18,0x62,0x00,0x00,0x10,0x63,0x34,0x02,0x00,0x24,0xa2,
-0x04,0x00,0x23,0xae,0x0c,0x00,0x02,0x8e,0x0a,0x00,0x04,0x24,0xf8,0xff,0x42,0x24,
-0x4d,0x01,0x00,0x0c,0x00,0x00,0x22,0xa6,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x0c,0x00,0x07,0x8e,0x20,0x10,0x06,0x3c,
-0x21,0x28,0x40,0x02,0x20,0x00,0xe7,0x24,0x00,0xfe,0xc6,0x34,0xff,0xff,0xe7,0x30,
-0x01,0x00,0x11,0x24,0x0a,0x00,0x04,0x24,0x10,0x01,0x00,0x0c,0x10,0x00,0xb1,0xaf,
-0xd5,0x4a,0x63,0x92,0x2a,0xb0,0x10,0x3c,0x32,0x00,0x02,0x36,0x01,0x00,0x63,0x24,
-0x00,0x00,0x43,0xa0,0x4d,0x01,0x00,0x0c,0x0a,0x00,0x04,0x24,0xc9,0x64,0x62,0x92,
-0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x24,0xc9,0x64,0x62,0xa2,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x01,0x00,0x10,0x36,0x00,0x00,0x11,0xa2,
-0x28,0x00,0xbf,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,
-0x18,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,
-0x25,0xb0,0x05,0x3c,0x01,0x80,0x03,0x3c,0x21,0x38,0x80,0x00,0x18,0x03,0xa2,0x34,
-0xe8,0x09,0x63,0x24,0x01,0x00,0x04,0x24,0x00,0x00,0x43,0xac,0x35,0x00,0xe4,0x10,
-0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x10,0x20,0x08,0xa2,0x34,0x02,0x00,0x02,0x24,
-0x83,0x00,0xe2,0x10,0x03,0x00,0x02,0x24,0x5a,0x00,0xe2,0x10,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x00,0x00,0x44,0x8c,
-0x68,0x15,0x66,0x24,0x70,0x08,0x02,0x24,0xe0,0x08,0x03,0x24,0x74,0x4b,0xc2,0xac,
-0x40,0x08,0x02,0x24,0x78,0x4b,0xc3,0xac,0x84,0x4b,0xc2,0xac,0x78,0x08,0x03,0x24,
-0x0c,0x08,0x02,0x24,0x88,0x4b,0xc3,0xac,0x8c,0x4b,0xc2,0xac,0x10,0x08,0x03,0x24,
-0x20,0x08,0x02,0x24,0x90,0x4b,0xc3,0xac,0x94,0x4b,0xc2,0xac,0x24,0x08,0x03,0x24,
-0x58,0x08,0x02,0x24,0x98,0x4b,0xc3,0xac,0x9c,0x4b,0xc2,0xac,0x50,0x0c,0x03,0x24,
-0x54,0x0c,0x02,0x24,0xa0,0x4b,0xc3,0xac,0xa4,0x4b,0xc2,0xac,0x14,0x0c,0x03,0x24,
-0x10,0x0c,0x02,0x24,0x60,0x08,0x05,0x24,0xa8,0x4b,0xc3,0xac,0xac,0x4b,0xc2,0xac,
-0x80,0x0c,0x03,0x24,0x84,0x0c,0x02,0x24,0x00,0x01,0x84,0x30,0xb4,0x4b,0xc2,0xac,
-0x80,0x4b,0xc5,0xac,0xb0,0x4b,0xc3,0xac,0x71,0x4b,0xc0,0xa0,0x7c,0x4b,0xc5,0xac,
-0x02,0x00,0x80,0x10,0xa0,0x08,0x02,0x24,0xb8,0x08,0x02,0x24,0x08,0x00,0xe0,0x03,
-0xb8,0x4b,0xc2,0xac,0x28,0x08,0xa2,0x34,0x02,0x80,0x03,0x3c,0x00,0x00,0x44,0x8c,
-0x68,0x15,0x66,0x24,0x70,0x08,0x02,0x24,0xe0,0x08,0x03,0x24,0x74,0x4b,0xc2,0xac,
-0x44,0x08,0x02,0x24,0x78,0x4b,0xc3,0xac,0x84,0x4b,0xc2,0xac,0x78,0x08,0x03,0x24,
-0x0c,0x08,0x02,0x24,0x88,0x4b,0xc3,0xac,0x8c,0x4b,0xc2,0xac,0x14,0x08,0x03,0x24,
-0x28,0x08,0x02,0x24,0x90,0x4b,0xc3,0xac,0x94,0x4b,0xc2,0xac,0x2c,0x08,0x03,0x24,
-0x58,0x08,0x02,0x24,0x98,0x4b,0xc3,0xac,0x9c,0x4b,0xc2,0xac,0x58,0x0c,0x03,0x24,
-0x5c,0x0c,0x02,0x24,0xa0,0x4b,0xc3,0xac,0xa4,0x4b,0xc2,0xac,0x1c,0x0c,0x03,0x24,
-0x18,0x0c,0x02,0x24,0x64,0x08,0x05,0x24,0xa8,0x4b,0xc3,0xac,0xac,0x4b,0xc2,0xac,
-0x88,0x0c,0x03,0x24,0x8c,0x0c,0x02,0x24,0x00,0x01,0x84,0x30,0xb4,0x4b,0xc2,0xac,
-0x71,0x4b,0xc7,0xa0,0x80,0x4b,0xc5,0xac,0xb0,0x4b,0xc3,0xac,0x7c,0x4b,0xc5,0xac,
-0xd6,0xff,0x80,0x10,0xa4,0x08,0x02,0x24,0xbc,0x08,0x02,0x24,0x08,0x00,0xe0,0x03,
-0xb8,0x4b,0xc2,0xac,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0xac,0x08,0x03,0x24,
-0xb8,0x4b,0x43,0xac,0x74,0x08,0x03,0x24,0xe4,0x08,0x04,0x24,0x74,0x4b,0x43,0xac,
-0x4c,0x08,0x03,0x24,0x78,0x4b,0x44,0xac,0x84,0x4b,0x43,0xac,0x7c,0x08,0x04,0x24,
-0x0c,0x08,0x03,0x24,0x88,0x4b,0x44,0xac,0x8c,0x4b,0x43,0xac,0x1c,0x08,0x04,0x24,
-0x38,0x08,0x03,0x24,0x90,0x4b,0x44,0xac,0x94,0x4b,0x43,0xac,0x3c,0x08,0x04,0x24,
-0x5c,0x08,0x03,0x24,0x98,0x4b,0x44,0xac,0x9c,0x4b,0x43,0xac,0x68,0x0c,0x04,0x24,
-0x6c,0x0c,0x03,0x24,0xa0,0x4b,0x44,0xac,0xa4,0x4b,0x43,0xac,0x2c,0x0c,0x04,0x24,
-0x28,0x0c,0x03,0x24,0x6c,0x08,0x05,0x24,0xa8,0x4b,0x44,0xac,0xac,0x4b,0x43,0xac,
-0x98,0x0c,0x04,0x24,0x9c,0x0c,0x03,0x24,0x71,0x4b,0x47,0xa0,0x80,0x4b,0x45,0xac,
-0xb0,0x4b,0x44,0xac,0xb4,0x4b,0x43,0xac,0x08,0x00,0xe0,0x03,0x7c,0x4b,0x45,0xac,
-0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0xa8,0x08,0x03,0x24,0xb8,0x4b,0x43,0xac,
-0x74,0x08,0x03,0x24,0xe4,0x08,0x04,0x24,0x74,0x4b,0x43,0xac,0x48,0x08,0x03,0x24,
-0x78,0x4b,0x44,0xac,0x84,0x4b,0x43,0xac,0x7c,0x08,0x04,0x24,0x0c,0x08,0x03,0x24,
-0x88,0x4b,0x44,0xac,0x8c,0x4b,0x43,0xac,0x18,0x08,0x04,0x24,0x30,0x08,0x03,0x24,
-0x90,0x4b,0x44,0xac,0x94,0x4b,0x43,0xac,0x34,0x08,0x04,0x24,0x5c,0x08,0x03,0x24,
-0x98,0x4b,0x44,0xac,0x9c,0x4b,0x43,0xac,0x60,0x0c,0x04,0x24,0x64,0x0c,0x03,0x24,
-0xa0,0x4b,0x44,0xac,0xa4,0x4b,0x43,0xac,0x24,0x0c,0x04,0x24,0x20,0x0c,0x03,0x24,
-0x68,0x08,0x05,0x24,0xa8,0x4b,0x44,0xac,0xac,0x4b,0x43,0xac,0x90,0x0c,0x04,0x24,
-0x94,0x0c,0x03,0x24,0x71,0x4b,0x47,0xa0,0x80,0x4b,0x45,0xac,0xb0,0x4b,0x44,0xac,
-0xb4,0x4b,0x43,0xac,0x08,0x00,0xe0,0x03,0x7c,0x4b,0x45,0xac,0x36,0x43,0x00,0x08,
-0x21,0x18,0x00,0x00,0x20,0x00,0x62,0x2c,0x06,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
-0x06,0x10,0x64,0x00,0x01,0x00,0x42,0x30,0xfa,0xff,0x40,0x10,0x01,0x00,0x63,0x24,
-0xff,0xff,0x63,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,0xd8,0xff,0xbd,0x27,
-0x25,0xb0,0x02,0x3c,0x18,0x00,0xb2,0xaf,0x21,0x90,0x82,0x00,0xff,0xff,0x02,0x24,
-0x1c,0x00,0xb3,0xaf,0x14,0x00,0xb1,0xaf,0x20,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,
-0x21,0x88,0xa0,0x00,0x21,0x20,0xa0,0x00,0x21,0x18,0x40,0x02,0x10,0x00,0xa2,0x10,
-0x21,0x98,0xc0,0x00,0x00,0x00,0x50,0x8e,0x31,0x43,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x04,0x10,0x53,0x00,0x27,0x18,0x11,0x00,0x25,0x18,0x62,0x00,0x24,0x18,0x70,0x00,
-0x00,0x00,0x43,0xae,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,
-0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x28,0x00,0xbd,0x27,0x00,0x00,0x66,0xac,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x21,0x30,0x80,0x00,0xec,0x60,0x44,0x8c,
-0x3d,0x43,0x00,0x08,0xff,0xff,0x05,0x24,0xe0,0xff,0xbd,0x27,0x25,0xb0,0x02,0x3c,
-0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x21,0x20,0x82,0x00,
-0x00,0x00,0x90,0x8c,0x21,0x88,0xa0,0x00,0x31,0x43,0x00,0x0c,0x21,0x20,0xa0,0x00,
-0x24,0x80,0x11,0x02,0x06,0x10,0x50,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xd0,0xff,0xbd,0x27,
-0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c,0x28,0x00,0xbf,0xaf,0x20,0x00,0xb4,0xaf,
-0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x24,0x00,0xb5,0xaf,0x10,0x00,0xb0,0xaf,
-0x68,0x15,0x31,0x26,0x98,0x4b,0x22,0x8e,0x25,0xb0,0x12,0x3c,0x24,0x08,0x53,0x36,
-0x21,0x10,0x52,0x00,0x00,0x00,0x70,0x8e,0x00,0x00,0x55,0x8c,0x7f,0x80,0x03,0x3c,
-0xff,0x7f,0x02,0x3c,0xff,0xff,0x63,0x34,0xff,0xff,0x42,0x34,0x24,0x10,0x02,0x02,
-0x24,0x18,0xa3,0x02,0xc0,0x25,0x04,0x00,0x25,0x18,0x64,0x00,0x00,0x80,0x14,0x3c,
-0x00,0x00,0x62,0xae,0x01,0x00,0x04,0x24,0x84,0x0a,0x00,0x0c,0x25,0xa8,0x74,0x00,
-0x98,0x4b,0x22,0x8e,0x25,0x80,0x14,0x02,0x01,0x00,0x04,0x24,0x21,0x10,0x52,0x00,
-0x00,0x00,0x55,0xac,0x84,0x0a,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xae,
-0x84,0x0a,0x00,0x0c,0x01,0x00,0x04,0x24,0xb8,0x4b,0x24,0x8e,0x0f,0x00,0x05,0x3c,
-0x28,0x00,0xbf,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,
-0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0xff,0xff,0xa5,0x34,
-0x68,0x43,0x00,0x08,0x30,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,
-0x02,0x80,0x11,0x3c,0x10,0x00,0xb0,0xaf,0x18,0x00,0xbf,0xaf,0x68,0x15,0x27,0x26,
-0x73,0x4b,0xe5,0x90,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,0xb0,0x0e,0x63,0x24,
-0x18,0x03,0x42,0x34,0x02,0x00,0x06,0x24,0x00,0x00,0x43,0xac,0x34,0x00,0xa6,0x10,
-0x21,0x80,0x80,0x00,0x03,0x00,0x03,0x24,0x3a,0x00,0xa3,0x10,0x2e,0x00,0x02,0x2e,
-0x10,0x00,0x02,0x2e,0x07,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0xff,0x00,0x04,0x32,
-0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x79,0x43,0x00,0x08,
-0x20,0x00,0xbd,0x27,0xfa,0xff,0xa6,0x14,0xff,0x00,0x04,0x32,0x71,0x4b,0xe4,0x90,
-0x01,0x00,0x02,0x24,0x33,0x00,0x82,0x10,0x02,0x00,0x82,0x28,0x38,0x00,0x40,0x14,
-0x00,0x00,0x00,0x00,0x38,0x00,0x85,0x10,0x68,0x15,0x22,0x26,0x2e,0x00,0x83,0x10,
-0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x24,0x68,0x43,0x00,0x0c,0xff,0xff,0x05,0x24,
-0xff,0xfc,0x06,0x3c,0xff,0xff,0xc6,0x34,0x24,0x30,0x46,0x00,0x00,0x08,0x04,0x24,
-0x3d,0x43,0x00,0x0c,0xff,0xff,0x05,0x24,0x68,0x15,0x22,0x26,0x71,0x4b,0x44,0x90,
-0x01,0x00,0x03,0x24,0x07,0x00,0x83,0x10,0x02,0x00,0x82,0x28,0x2c,0x00,0x40,0x14,
-0x02,0x00,0x02,0x24,0x2c,0x00,0x82,0x10,0x03,0x00,0x02,0x24,0xdb,0xff,0x82,0x14,
-0x00,0x00,0x00,0x00,0x68,0x15,0x22,0x26,0x74,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x3c,
-0x3d,0x43,0x00,0x0c,0x21,0x30,0x00,0x00,0xc2,0x43,0x00,0x08,0xff,0x00,0x04,0x32,
-0x25,0x00,0x82,0x2c,0xcc,0xff,0x40,0x14,0x03,0x00,0x03,0x24,0x18,0x00,0xbf,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x20,0x00,0xbd,0x27,0xc7,0xff,0x40,0x14,0x10,0x00,0x02,0x2e,0x18,0x00,0xbf,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x20,0x00,0xbd,0x27,0x68,0x15,0x22,0x26,0x74,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x3c,
-0x3d,0x43,0x00,0x0c,0x0f,0x00,0x06,0x24,0xd4,0x43,0x00,0x08,0x00,0x08,0x04,0x24,
-0xcc,0xff,0x80,0x14,0x68,0x15,0x22,0x26,0x74,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x24,
-0x3d,0x43,0x00,0x0c,0x0f,0x00,0x06,0x24,0xd4,0x43,0x00,0x08,0x00,0x08,0x04,0x24,
-0xb2,0xff,0x80,0x14,0x00,0x00,0x00,0x00,0x68,0x15,0x22,0x26,0x74,0x4b,0x44,0x8c,
-0x0f,0x00,0x05,0x24,0x3d,0x43,0x00,0x0c,0x21,0x30,0x00,0x00,0xc2,0x43,0x00,0x08,
-0xff,0x00,0x04,0x32,0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x02,0x80,0x11,0x3c,
-0x68,0x15,0x28,0x26,0x73,0x4b,0x06,0x91,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
-0x5c,0x10,0x63,0x24,0x18,0x03,0x42,0x34,0x02,0x00,0x07,0x24,0x18,0x00,0xb2,0xaf,
-0x10,0x00,0xb0,0xaf,0x1c,0x00,0xbf,0xaf,0x00,0x00,0x43,0xac,0x21,0x90,0xa0,0x00,
-0x39,0x00,0xc7,0x10,0xff,0x00,0x90,0x30,0x03,0x00,0x03,0x24,0x3f,0x00,0xc3,0x10,
-0x2e,0x00,0x02,0x2e,0x10,0x00,0x02,0x2e,0x0c,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
-0x0f,0x00,0x04,0x3c,0xff,0xff,0x84,0x34,0x24,0x20,0x44,0x02,0x00,0x15,0x10,0x00,
-0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
-0x25,0x20,0x44,0x00,0x63,0x43,0x00,0x08,0x20,0x00,0xbd,0x27,0xf5,0xff,0xc7,0x14,
-0x0f,0x00,0x04,0x3c,0x71,0x4b,0x04,0x91,0x01,0x00,0x02,0x24,0x33,0x00,0x82,0x10,
-0x02,0x00,0x82,0x28,0x38,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x38,0x00,0x86,0x10,
-0x68,0x15,0x22,0x26,0x2e,0x00,0x83,0x10,0x00,0x00,0x00,0x00,0x00,0x08,0x04,0x24,
-0x68,0x43,0x00,0x0c,0xff,0xff,0x05,0x24,0xff,0xfc,0x06,0x3c,0xff,0xff,0xc6,0x34,
-0x24,0x30,0x46,0x00,0x00,0x08,0x04,0x24,0x3d,0x43,0x00,0x0c,0xff,0xff,0x05,0x24,
-0x68,0x15,0x22,0x26,0x71,0x4b,0x44,0x90,0x01,0x00,0x03,0x24,0x07,0x00,0x83,0x10,
-0x02,0x00,0x82,0x28,0x2c,0x00,0x40,0x14,0x02,0x00,0x02,0x24,0x2c,0x00,0x82,0x10,
-0x03,0x00,0x02,0x24,0xd6,0xff,0x82,0x14,0x00,0x00,0x00,0x00,0x68,0x15,0x22,0x26,
-0x74,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x3c,0x3d,0x43,0x00,0x0c,0x21,0x30,0x00,0x00,
-0x2f,0x44,0x00,0x08,0x0f,0x00,0x04,0x3c,0x25,0x00,0x02,0x2e,0xc7,0xff,0x40,0x14,
-0x03,0x00,0x03,0x24,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xc1,0xff,0x40,0x14,
-0x00,0x00,0x00,0x00,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x68,0x15,0x22,0x26,
-0x74,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x3c,0x3d,0x43,0x00,0x0c,0x0f,0x00,0x06,0x24,
-0x46,0x44,0x00,0x08,0x00,0x08,0x04,0x24,0xcc,0xff,0x80,0x14,0x68,0x15,0x22,0x26,
-0x74,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x24,0x3d,0x43,0x00,0x0c,0x0f,0x00,0x06,0x24,
-0x46,0x44,0x00,0x08,0x00,0x08,0x04,0x24,0xad,0xff,0x80,0x14,0x00,0x00,0x00,0x00,
-0x68,0x15,0x22,0x26,0x74,0x4b,0x44,0x8c,0x0f,0x00,0x05,0x24,0x3d,0x43,0x00,0x0c,
-0x21,0x30,0x00,0x00,0x2f,0x44,0x00,0x08,0x0f,0x00,0x04,0x3c,0xe8,0xff,0xbd,0x27,
-0x10,0x00,0xb0,0xaf,0x21,0x80,0x80,0x00,0x14,0x00,0xbf,0xaf,0x79,0x43,0x00,0x0c,
-0x21,0x20,0x00,0x00,0x40,0x01,0x44,0x34,0x21,0x18,0x40,0x00,0x1f,0x00,0x02,0x2e,
-0x00,0x23,0x04,0x00,0x10,0x00,0x40,0x10,0x10,0x00,0x05,0x2e,0x00,0x01,0x64,0x34,
-0x06,0x00,0xa0,0x10,0x00,0x23,0x04,0x00,0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,
-0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x63,0x43,0x00,0x0c,
-0xf1,0xff,0x10,0x26,0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,
-0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x63,0x43,0x00,0x0c,0xe2,0xff,0x10,0x26,
-0x21,0x10,0x00,0x02,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
-0x18,0x00,0xbd,0x27,0x25,0xb0,0x02,0x3c,0x27,0x38,0x05,0x00,0x21,0x40,0x82,0x00,
-0xff,0xff,0x02,0x24,0x07,0x00,0xa2,0x10,0x25,0x38,0xe6,0x00,0x00,0x00,0x02,0x8d,
-0x00,0x00,0x00,0x00,0x24,0x10,0xe2,0x00,0x00,0x00,0x02,0xad,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x00,0x00,0x06,0xad,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c,0xe8,0x12,0x42,0x24,0x18,0x03,0x63,0x34,
-0xd8,0xff,0xbd,0x27,0x00,0x00,0x62,0xac,0x0f,0x00,0x02,0x3c,0x14,0x00,0xb1,0xaf,
-0xff,0xff,0x42,0x34,0x21,0x88,0xa0,0x00,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,
-0x20,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x21,0x90,0xc0,0x00,0x21,0x28,0xc0,0x00,
-0x0a,0x00,0x22,0x12,0x21,0x98,0x80,0x00,0xac,0x43,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x21,0x20,0x20,0x02,0x31,0x43,0x00,0x0c,0x21,0x80,0x40,0x00,0x04,0x10,0x52,0x00,
-0x27,0x28,0x11,0x00,0x25,0x28,0xa2,0x00,0x24,0x28,0xb0,0x00,0xff,0x00,0x64,0x32,
-0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x17,0x44,0x00,0x08,0x28,0x00,0xbd,0x27,0x01,0x80,0x03,0x3c,
-0x25,0xb0,0x02,0x3c,0x74,0x13,0x63,0x24,0x18,0x03,0x42,0x34,0xe0,0xff,0xbd,0x27,
-0x00,0x00,0x43,0xac,0x18,0x00,0xbf,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,
-0xac,0x43,0x00,0x0c,0x21,0x88,0xa0,0x00,0x21,0x80,0x40,0x00,0x31,0x43,0x00,0x0c,
-0x21,0x20,0x20,0x02,0x24,0x80,0x11,0x02,0x06,0x10,0x50,0x00,0x18,0x00,0xbf,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x01,0x00,0x02,0x24,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0xc8,0xff,0xbd,0x27,0x2c,0x00,0xb1,0xaf,0xff,0xff,0x05,0x24,0x21,0x88,0x80,0x00,
-0x02,0x00,0x06,0x24,0x10,0x00,0xa4,0x27,0x34,0x00,0xbf,0xaf,0x30,0x00,0xb2,0xaf,
-0x97,0x45,0x00,0x0c,0x28,0x00,0xb0,0xaf,0x08,0x00,0x30,0x96,0x02,0x80,0x02,0x3c,
-0x21,0x28,0x00,0x00,0x25,0x80,0x02,0x02,0x21,0x20,0x00,0x02,0x97,0x45,0x00,0x0c,
-0x10,0x00,0x06,0x24,0x20,0x00,0x02,0x96,0x24,0x00,0x04,0x26,0x10,0x00,0xa5,0x27,
-0x03,0xff,0x42,0x30,0xc8,0x00,0x42,0x34,0x20,0x00,0x02,0xa6,0x9f,0x45,0x00,0x0c,
-0x06,0x00,0x06,0x24,0x25,0xb0,0x03,0x3c,0x50,0x00,0x62,0x34,0x00,0x00,0x44,0x8c,
-0x54,0x00,0x65,0x34,0x58,0x00,0x66,0x34,0x18,0x00,0xa4,0xaf,0x00,0x00,0xa2,0x8c,
-0x5c,0x00,0x63,0x34,0x2a,0x00,0x04,0x26,0x1c,0x00,0xa2,0xaf,0x00,0x00,0xc7,0x8c,
-0x18,0x00,0xa5,0x27,0x06,0x00,0x06,0x24,0x20,0x00,0xa7,0xaf,0x00,0x00,0x62,0x8c,
-0x1a,0x00,0x12,0x24,0x9f,0x45,0x00,0x0c,0x24,0x00,0xa2,0xaf,0x30,0x00,0x04,0x26,
-0x20,0x00,0xa5,0x27,0x9f,0x45,0x00,0x0c,0x06,0x00,0x06,0x24,0x13,0x00,0x03,0x24,
-0x14,0x00,0x23,0xae,0x0c,0x00,0x32,0xae,0x08,0x00,0x05,0x8e,0x04,0x00,0x04,0x8e,
-0xff,0xdf,0x02,0x3c,0x14,0x00,0x06,0x8e,0xff,0xff,0x42,0x34,0x10,0x00,0x07,0x8e,
-0xff,0xe0,0x03,0x24,0x24,0x28,0xa2,0x00,0x00,0x40,0x02,0x3c,0x24,0x20,0x83,0x00,
-0x25,0x28,0xa2,0x00,0xff,0x81,0x03,0x24,0xfe,0xff,0x02,0x3c,0x24,0x30,0xc3,0x00,
-0xff,0xff,0x42,0x34,0x00,0x12,0x84,0x34,0x00,0x80,0x03,0x3c,0x24,0x20,0x82,0x00,
-0x25,0x38,0xe3,0x00,0x00,0x26,0xc6,0x34,0x80,0x00,0xa5,0x34,0x20,0x00,0x02,0x24,
-0x00,0x00,0x12,0xa6,0x10,0x00,0x07,0xae,0x02,0x00,0x02,0xa2,0x14,0x00,0x06,0xae,
-0x04,0x00,0x04,0xae,0x08,0x00,0x05,0xae,0x34,0x00,0xbf,0x8f,0x30,0x00,0xb2,0x8f,
-0x2c,0x00,0xb1,0x8f,0x28,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,
-0x93,0x45,0x00,0x08,0xff,0x00,0xa5,0x30,0x00,0x00,0x85,0xa0,0xff,0xff,0xc6,0x24,
-0x01,0x00,0x84,0x24,0xfc,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x05,0x00,0xc0,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,
-0xff,0xff,0xc6,0x24,0xfd,0xff,0xc0,0x14,0x04,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x21,0x38,0x80,0x00,0x08,0x00,0xc0,0x10,0xff,0xff,0xc3,0x24,
-0xff,0xff,0x06,0x24,0x00,0x00,0xa2,0x90,0xff,0xff,0x63,0x24,0x01,0x00,0xa5,0x24,
-0x00,0x00,0xe2,0xa0,0xfb,0xff,0x66,0x14,0x01,0x00,0xe7,0x24,0x08,0x00,0xe0,0x03,
-0x21,0x10,0x80,0x00,0x21,0x38,0x80,0x00,0x08,0x00,0xc0,0x10,0xff,0xff,0xc3,0x24,
-0xff,0xff,0x06,0x24,0x00,0x00,0xa2,0x8c,0xff,0xff,0x63,0x24,0x04,0x00,0xa5,0x24,
-0x00,0x00,0xe2,0xac,0xfb,0xff,0x66,0x14,0x04,0x00,0xe7,0x24,0x08,0x00,0xe0,0x03,
-0x21,0x10,0x80,0x00,0x2b,0x10,0xa4,0x00,0x0d,0x00,0x40,0x14,0xff,0xff,0x02,0x24,
-0xff,0xff,0xc6,0x24,0x08,0x00,0xc2,0x10,0x21,0x18,0x80,0x00,0xff,0xff,0x07,0x24,
-0x00,0x00,0xa2,0x90,0xff,0xff,0xc6,0x24,0x01,0x00,0xa5,0x24,0x00,0x00,0x62,0xa0,
-0xfb,0xff,0xc7,0x14,0x01,0x00,0x63,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,
-0x21,0x28,0xa6,0x00,0x21,0x18,0x86,0x00,0xff,0xff,0xc6,0x24,0xfa,0xff,0xc2,0x10,
-0x00,0x00,0x00,0x00,0xff,0xff,0x07,0x24,0xff,0xff,0xa5,0x24,0x00,0x00,0xa2,0x90,
-0xff,0xff,0x63,0x24,0xff,0xff,0xc6,0x24,0xfb,0xff,0xc7,0x14,0x00,0x00,0x62,0xa0,
-0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0x0c,0x00,0xc0,0x10,0x00,0x00,0x00,0x00,
-0x00,0x00,0x82,0x90,0x00,0x00,0xa3,0x90,0x01,0x00,0x84,0x24,0x23,0x10,0x43,0x00,
-0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0x04,0x00,0x40,0x14,0x01,0x00,0xa5,0x24,
-0xff,0xff,0xc6,0x24,0xf6,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x21,0x10,0xc0,0x00,0xea,0x45,0x00,0x08,0x21,0x18,0x86,0x00,0x00,0x00,0x82,0x90,
-0x00,0x00,0x00,0x00,0x04,0x00,0x45,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x84,0x24,
-0xfa,0xff,0x83,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,
-0x09,0x00,0xc0,0x10,0xff,0xff,0xc3,0x24,0xff,0x00,0xa5,0x30,0xff,0xff,0x06,0x24,
-0x00,0x00,0x82,0x90,0xff,0xff,0x63,0x24,0x05,0x00,0x45,0x10,0x01,0x00,0x84,0x24,
-0xfb,0xff,0x66,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0xff,0xff,0x82,0x24,0x21,0x38,0x00,0x00,0x1f,0x00,0xc0,0x10,
-0x21,0x18,0x00,0x00,0x02,0x80,0x02,0x3c,0x80,0x95,0x4b,0x24,0x00,0x00,0x87,0x90,
-0x00,0x00,0xa3,0x90,0xff,0xff,0xc6,0x24,0x01,0x00,0x84,0x24,0x21,0x10,0xeb,0x00,
-0x16,0x00,0xe0,0x10,0x01,0x00,0xa5,0x24,0x14,0x00,0x60,0x10,0x21,0x48,0x6b,0x00,
-0x10,0x00,0xe3,0x10,0x20,0x00,0xe8,0x24,0x00,0x00,0x42,0x90,0x00,0x00,0x00,0x00,
-0x01,0x00,0x42,0x30,0x02,0x00,0x40,0x10,0x20,0x00,0x6a,0x24,0xff,0x00,0x07,0x31,
-0x00,0x00,0x22,0x91,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0x02,0x00,0x40,0x10,
-0xff,0x00,0xe7,0x30,0xff,0x00,0x43,0x31,0xff,0x00,0x63,0x30,0x03,0x00,0xe3,0x14,
-0x00,0x00,0x00,0x00,0xe5,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x23,0x10,0xe3,0x00,0x21,0x18,0x80,0x00,0x00,0x00,0xa2,0x90,0x01,0x00,0xa5,0x24,
-0x00,0x00,0x82,0xa0,0xfc,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,
-0x21,0x10,0x60,0x00,0x21,0x38,0x80,0x00,0xff,0xff,0x03,0x24,0xff,0xff,0xc6,0x24,
-0x06,0x00,0xc3,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,0x01,0x00,0xa5,0x24,
-0x00,0x00,0x82,0xa0,0xf9,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,
-0x21,0x10,0xe0,0x00,0x00,0x00,0x82,0x80,0x39,0x46,0x00,0x08,0x21,0x18,0x80,0x00,
-0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x80,0x00,0x00,0x00,0x00,0xfc,0xff,0x40,0x14,
-0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,0x01,0x00,0xa5,0x24,0x00,0x00,0x82,0xa0,
-0xfc,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
-0x12,0x00,0xc0,0x10,0x21,0x18,0x80,0x00,0x00,0x00,0x82,0x80,0x4a,0x46,0x00,0x08,
-0x00,0x00,0x00,0x00,0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x80,0x00,0x00,0x00,0x00,
-0xfc,0xff,0x40,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0xa2,0x90,0x01,0x00,0xa5,0x24,
-0x00,0x00,0x82,0xa0,0x05,0x00,0x40,0x10,0x01,0x00,0x84,0x24,0xff,0xff,0xc6,0x24,
-0xf9,0xff,0xc0,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xa0,0x08,0x00,0xe0,0x03,
-0x21,0x10,0x60,0x00,0x00,0x00,0x83,0x90,0x00,0x00,0xa2,0x90,0x01,0x00,0x84,0x24,
-0x23,0x10,0x62,0x00,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0x03,0x00,0x40,0x14,
-0x01,0x00,0xa5,0x24,0xf7,0xff,0x60,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x21,0x10,0x00,0x00,0x0b,0x00,0xc0,0x10,0x00,0x00,0x00,0x00,
-0x00,0x00,0xa2,0x90,0x00,0x00,0x83,0x90,0xff,0xff,0xc6,0x24,0x23,0x10,0x62,0x00,
-0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0x03,0x00,0x40,0x14,0x01,0x00,0xa5,0x24,
-0xf5,0xff,0x60,0x14,0x01,0x00,0x84,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x00,0x00,0x83,0x80,0x00,0x2e,0x05,0x00,0x21,0x10,0x80,0x00,0x7b,0x46,0x00,0x08,
-0x03,0x2e,0x05,0x00,0x07,0x00,0x60,0x10,0x01,0x00,0x42,0x24,0x00,0x00,0x43,0x80,
-0x00,0x00,0x00,0x00,0xfb,0xff,0x65,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x00,0x00,0x00,0x82,0x80,
-0x87,0x46,0x00,0x08,0x21,0x18,0x80,0x00,0x01,0x00,0x63,0x24,0x00,0x00,0x62,0x80,
-0x00,0x00,0x00,0x00,0xfc,0xff,0x40,0x14,0x23,0x10,0x64,0x00,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x21,0x80,0xa0,0x00,
-0x14,0x00,0xb1,0xaf,0x18,0x00,0xbf,0xaf,0x21,0x88,0x80,0x00,0x81,0x46,0x00,0x0c,
-0x00,0x86,0x10,0x00,0x21,0x18,0x51,0x00,0x03,0x86,0x10,0x00,0x00,0x00,0x62,0x80,
-0x00,0x00,0x00,0x00,0x0a,0x00,0x50,0x10,0x21,0x10,0x60,0x00,0xff,0xff,0x63,0x24,
-0x2b,0x10,0x71,0x00,0xf9,0xff,0x40,0x10,0x21,0x10,0x00,0x00,0x18,0x00,0xbf,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
-0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,
-0x20,0x00,0xbd,0x27,0x21,0x30,0x80,0x00,0x0d,0x00,0xa0,0x10,0xff,0xff,0xa3,0x24,
-0x00,0x00,0x82,0x80,0x00,0x00,0x00,0x00,0x09,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
-0xff,0xff,0x05,0x24,0xff,0xff,0x63,0x24,0x05,0x00,0x65,0x10,0x01,0x00,0xc6,0x24,
-0x00,0x00,0xc2,0x80,0x00,0x00,0x00,0x00,0xfa,0xff,0x40,0x14,0x00,0x00,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x23,0x10,0xc4,0x00,0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,
-0x19,0x00,0x40,0x10,0x21,0x40,0x00,0x00,0x00,0x00,0xa9,0x80,0x00,0x00,0x00,0x00,
-0x17,0x00,0x20,0x11,0x21,0x30,0xa0,0x00,0x00,0x3e,0x02,0x00,0x03,0x3e,0x07,0x00,
-0x21,0x18,0x20,0x01,0x15,0x00,0xe3,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0xc6,0x24,
-0x00,0x00,0xc2,0x90,0x00,0x00,0x00,0x00,0x00,0x1e,0x02,0x00,0x03,0x1e,0x03,0x00,
-0xf8,0xff,0x60,0x14,0x00,0x16,0x02,0x00,0x03,0x16,0x02,0x00,0x06,0x00,0x40,0x10,
-0x00,0x00,0x00,0x00,0x01,0x00,0x84,0x24,0x00,0x00,0x82,0x90,0x00,0x00,0x00,0x00,
-0xeb,0xff,0x40,0x14,0x01,0x00,0x08,0x25,0x08,0x00,0xe0,0x03,0x21,0x10,0x00,0x01,
-0x00,0x00,0xa2,0x90,0xcc,0x46,0x00,0x08,0x00,0x16,0x02,0x00,0x00,0x00,0xc2,0x90,
-0xcc,0x46,0x00,0x08,0x00,0x16,0x02,0x00,0x00,0x00,0x87,0x90,0x00,0x00,0x00,0x00,
-0x14,0x00,0xe0,0x10,0x21,0x10,0x80,0x00,0x00,0x00,0xa4,0x90,0x00,0x00,0x00,0x00,
-0x00,0x1e,0x04,0x00,0x03,0x1e,0x03,0x00,0x09,0x00,0x60,0x10,0x21,0x30,0xa0,0x00,
-0x00,0x3e,0x07,0x00,0x03,0x3e,0x07,0x00,0x0b,0x00,0xe3,0x10,0x01,0x00,0xc6,0x24,
-0x00,0x00,0xc3,0x80,0x00,0x00,0x00,0x00,0xfb,0xff,0x60,0x14,0x00,0x00,0x00,0x00,
-0x01,0x00,0x42,0x24,0x00,0x00,0x47,0x90,0x00,0x00,0x00,0x00,0xf0,0xff,0xe0,0x14,
-0x00,0x00,0x00,0x00,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x18,0x00,0xbf,0xaf,
-0x21,0x80,0x80,0x00,0x1d,0x00,0x80,0x10,0x21,0x88,0xa0,0x00,0xb8,0x46,0x00,0x0c,
-0x21,0x20,0x00,0x02,0x21,0x80,0x02,0x02,0x00,0x00,0x02,0x82,0x21,0x28,0x20,0x02,
-0x21,0x20,0x00,0x02,0x22,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0xdc,0x46,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x05,0x00,0x40,0x10,0x21,0x18,0x40,0x00,0x00,0x00,0x42,0x80,
-0x00,0x00,0x00,0x00,0x0a,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,
-0xa8,0x96,0x43,0xac,0x21,0x18,0x00,0x02,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x21,0x10,0x60,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
-0x00,0x00,0x60,0xa0,0x0d,0x47,0x00,0x08,0x01,0x00,0x63,0x24,0x02,0x80,0x02,0x3c,
-0xa8,0x96,0x50,0x8c,0x00,0x00,0x00,0x00,0xf3,0xff,0x00,0x12,0x21,0x18,0x00,0x00,
-0xb8,0x46,0x00,0x0c,0x21,0x20,0x00,0x02,0x21,0x80,0x02,0x02,0x00,0x00,0x02,0x82,
-0x21,0x28,0x20,0x02,0x21,0x20,0x00,0x02,0xe0,0xff,0x40,0x14,0x21,0x18,0x00,0x00,
-0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x02,0x80,0x02,0x3c,
-0xa8,0x96,0x40,0xac,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
-0xe0,0xff,0xbd,0x27,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x1c,0x00,0xbf,0xaf,
-0x10,0x00,0xb0,0xaf,0x00,0x00,0x90,0x8c,0x21,0x90,0x80,0x00,0x21,0x88,0xa0,0x00,
-0x21,0x18,0x00,0x00,0x0f,0x00,0x00,0x12,0x21,0x20,0x00,0x02,0xb8,0x46,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x21,0x80,0x02,0x02,0x00,0x00,0x02,0x82,0x21,0x28,0x20,0x02,
-0x21,0x20,0x00,0x02,0x07,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0xdc,0x46,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x21,0x18,0x40,0x00,0x09,0x00,0x40,0x14,0x00,0x00,0x42,0xae,
-0x21,0x18,0x00,0x02,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x21,0x10,0x60,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
-0x00,0x00,0x42,0x80,0x00,0x00,0x00,0x00,0xf5,0xff,0x40,0x10,0x01,0x00,0x64,0x24,
-0x00,0x00,0x60,0xa0,0x46,0x47,0x00,0x08,0x00,0x00,0x44,0xae,0xd8,0xff,0xbd,0x27,
-0x14,0x00,0xb1,0xaf,0x21,0x88,0x80,0x00,0x21,0x20,0xa0,0x00,0x1c,0x00,0xb3,0xaf,
-0x18,0x00,0xb2,0xaf,0x20,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x81,0x46,0x00,0x0c,
-0x21,0x98,0xa0,0x00,0x21,0x90,0x40,0x00,0x08,0x00,0x40,0x16,0x21,0x10,0x20,0x02,
-0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x81,0x46,0x00,0x0c,
-0x21,0x20,0x20,0x02,0x21,0x80,0x40,0x00,0x2a,0x10,0x52,0x00,0x0a,0x00,0x40,0x14,
-0x00,0x00,0x00,0x00,0x21,0x20,0x20,0x02,0x21,0x28,0x60,0x02,0x21,0x30,0x40,0x02,
-0xd4,0x45,0x00,0x0c,0xff,0xff,0x10,0x26,0x0b,0x00,0x40,0x10,0x2a,0x18,0x12,0x02,
-0xf8,0xff,0x60,0x10,0x01,0x00,0x31,0x26,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,
-0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,
-0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0x62,0x47,0x00,0x08,0x21,0x10,0x20,0x02,
-0x01,0x80,0x02,0x3c,0xc0,0xff,0xbd,0x27,0x08,0x1e,0x44,0x24,0x25,0xb0,0x02,0x3c,
-0x28,0x00,0xb4,0xaf,0x02,0x80,0x03,0x3c,0x25,0xb0,0x14,0x3c,0x18,0x03,0x42,0x34,
-0x38,0x00,0xbe,0xaf,0x34,0x00,0xb7,0xaf,0x30,0x00,0xb6,0xaf,0x2c,0x00,0xb5,0xaf,
-0x24,0x00,0xb3,0xaf,0x3c,0x00,0xbf,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,
-0x18,0x00,0xb0,0xaf,0x68,0x15,0x73,0x24,0x00,0x00,0x44,0xac,0x02,0x80,0x16,0x3c,
-0x02,0x80,0x15,0x3c,0xc4,0x02,0x9e,0x36,0x64,0x03,0x97,0x36,0x01,0x80,0x04,0x3c,
-0x08,0x1e,0x82,0x24,0x18,0x03,0x83,0x36,0x00,0x00,0x62,0xac,0xa0,0x02,0x87,0x36,
-0x00,0x00,0xe4,0x8c,0xd8,0x63,0x63,0x8e,0xff,0x0f,0x02,0x3c,0xff,0xff,0x46,0x34,
-0x24,0x80,0x86,0x00,0x01,0x00,0x05,0x3c,0x01,0x00,0x63,0x24,0x2b,0x10,0xb0,0x00,
-0x07,0x00,0x40,0x10,0xd8,0x63,0x63,0xae,0xa4,0x02,0x82,0x36,0x00,0x00,0x51,0x8c,
-0x00,0xb0,0x03,0x3c,0x25,0x80,0x03,0x02,0x00,0x00,0x11,0xae,0x00,0x00,0xe0,0xac,
-0xb0,0x02,0x84,0x36,0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x24,0x80,0x46,0x00,
-0x2b,0x18,0xb0,0x00,0x08,0x00,0x60,0x10,0xc0,0x02,0x82,0x36,0x00,0xb0,0x02,0x3c,
-0x25,0x80,0x02,0x02,0x00,0x00,0x11,0x8e,0xb4,0x02,0x82,0x36,0x00,0x00,0x51,0xac,
-0x00,0x00,0x80,0xac,0xc0,0x02,0x82,0x36,0x00,0x00,0x50,0x8c,0xff,0x00,0x08,0x3c,
-0xff,0xff,0x02,0x35,0x2b,0x10,0x50,0x00,0x47,0x00,0x40,0x10,0x00,0x00,0x00,0x00,
-0x00,0x00,0x82,0x8e,0x00,0xff,0x06,0x3c,0xac,0x02,0x84,0x36,0x01,0x00,0x45,0x24,
-0xbc,0x02,0x83,0x36,0xff,0x00,0xc2,0x34,0x00,0xfd,0x07,0x3c,0x00,0x00,0x85,0xac,
-0x00,0x00,0x70,0xac,0x24,0x18,0x02,0x02,0x07,0x00,0xe2,0x34,0x00,0x00,0x85,0x8c,
-0x52,0x03,0x62,0x10,0x25,0xb0,0x12,0x3c,0x2b,0x10,0x43,0x00,0xa2,0x00,0x40,0x14,
-0xa4,0x00,0xe2,0x34,0x00,0xf8,0x04,0x3c,0x15,0x00,0x82,0x34,0x57,0x03,0x62,0x10,
-0x2b,0x10,0x43,0x00,0xc8,0x00,0x40,0x14,0x00,0xf9,0x05,0x3c,0x00,0xf0,0x05,0x3c,
-0x20,0x00,0xa2,0x34,0x67,0x03,0x62,0x10,0x2b,0x10,0x43,0x00,0x20,0x01,0x40,0x14,
-0x10,0x00,0x82,0x34,0x70,0x03,0x65,0x10,0x2b,0x10,0xa3,0x00,0xc8,0x01,0x40,0x14,
-0x02,0x00,0xa2,0x34,0x00,0xd0,0x02,0x3c,0x2a,0x02,0x62,0x10,0x2b,0x10,0x43,0x00,
-0xaf,0x02,0x40,0x14,0x00,0xe0,0x02,0x3c,0x00,0xc0,0x02,0x3c,0xbb,0x03,0x62,0x10,
-0xff,0x00,0x03,0x3c,0x00,0xf0,0x02,0x3c,0x24,0x30,0x02,0x02,0x18,0x00,0xc2,0x10,
-0x02,0x1d,0x10,0x00,0x00,0x70,0x05,0x3c,0x24,0x10,0x05,0x02,0x02,0x4f,0x02,0x00,
-0x0f,0x00,0x02,0x3c,0xff,0xff,0x42,0x34,0x00,0x50,0x07,0x3c,0xff,0x00,0x68,0x30,
-0xff,0x00,0x04,0x32,0x96,0x01,0xc7,0x10,0x24,0x18,0x02,0x02,0x2b,0x10,0xe6,0x00,
-0x8a,0x01,0x40,0x14,0x00,0x80,0x02,0x3c,0x00,0x20,0x02,0x3c,0x1a,0x03,0xc2,0x10,
-0x2b,0x10,0x46,0x00,0x82,0x02,0x40,0x14,0x00,0x30,0x02,0x3c,0x17,0x03,0xc0,0x10,
-0x80,0x10,0x08,0x00,0x00,0x10,0x02,0x3c,0x14,0x03,0xc2,0x10,0x80,0x10,0x08,0x00,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x00,0x00,0xe2,0x92,0x25,0xb0,0x07,0x3c,
-0xc8,0x7d,0xc2,0xa2,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0xc8,0x7d,0xc2,0x92,0x00,0x00,0x00,0x00,0x01,0x00,0x42,0x30,0x4e,0x00,0x40,0x10,
-0x02,0x80,0x03,0x3c,0x00,0x40,0x62,0x8e,0xf0,0xff,0x03,0x24,0xd7,0x42,0x60,0xa2,
-0x24,0x10,0x43,0x00,0x01,0x00,0x42,0x34,0x00,0x40,0x62,0xae,0xc8,0x7d,0xc2,0x92,
-0x00,0x00,0x00,0x00,0x02,0x00,0x42,0x30,0x3d,0x00,0x40,0x10,0x0f,0xff,0x03,0x24,
-0x00,0x40,0x62,0x8e,0x00,0x00,0x00,0x00,0x24,0x10,0x43,0x00,0x10,0x00,0x42,0x34,
-0x00,0x40,0x62,0xae,0xc8,0x7d,0xc2,0x92,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x30,
-0x30,0x00,0x40,0x10,0xff,0xf0,0x03,0x24,0x00,0x40,0x62,0x8e,0x00,0x00,0x00,0x00,
-0x24,0x10,0x43,0x00,0x00,0x01,0x42,0x34,0x25,0xb0,0x05,0x3c,0x00,0x40,0x62,0xae,
-0x4c,0x00,0xa3,0x34,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x03,0x00,0x42,0x30,
-0x05,0x00,0x40,0x14,0xff,0xff,0x02,0x3c,0x00,0x40,0x63,0x8e,0xff,0x0f,0x42,0x34,
-0x24,0x18,0x62,0x00,0x00,0x40,0x63,0xae,0x00,0x7b,0xa4,0x8e,0x01,0x80,0x06,0x3c,
-0x08,0x1f,0xc2,0x24,0x18,0x03,0xa3,0x34,0x00,0x7b,0xa6,0x26,0x00,0x00,0x62,0xac,
-0x10,0x00,0x86,0x10,0x02,0x80,0x02,0x3c,0xbf,0x00,0xb2,0x34,0x68,0x15,0x51,0x24,
-0x21,0x80,0xc0,0x00,0x00,0x00,0x42,0x92,0x00,0x00,0x00,0x00,0x04,0x00,0x42,0x2c,
-0x09,0x00,0x40,0x10,0x02,0x80,0x07,0x3c,0x98,0x65,0x24,0x8e,0x8b,0x07,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x00,0x7b,0xa2,0x8e,0x00,0x00,0x00,0x00,0xf5,0xff,0x50,0x14,
-0x00,0x00,0x00,0x00,0x02,0x80,0x07,0x3c,0x08,0x08,0xe4,0x24,0x21,0x28,0x00,0x00,
-0x21,0x30,0x00,0x00,0x31,0x1c,0x00,0x0c,0x21,0x38,0x00,0x00,0x9a,0x47,0x00,0x08,
-0x01,0x80,0x04,0x3c,0x00,0x40,0x62,0x8e,0x30,0x48,0x00,0x08,0x24,0x10,0x43,0x00,
-0x00,0x40,0x62,0x8e,0x04,0x43,0x64,0x92,0x24,0x10,0x43,0x00,0x00,0x40,0x62,0xae,
-0x27,0x48,0x00,0x08,0x04,0x43,0x64,0xae,0x68,0x15,0x66,0x24,0x00,0x40,0xc2,0x8c,
-0xd7,0x42,0xc4,0x90,0xf0,0xff,0x03,0x24,0x24,0x10,0x43,0x00,0xb3,0xff,0x80,0x14,
-0x00,0x40,0xc2,0xac,0x1c,0x00,0x04,0x24,0x58,0x0c,0xe5,0x34,0x50,0x0c,0xe3,0x34,
-0x01,0x00,0x02,0x24,0xd7,0x42,0xc2,0xa0,0x00,0x00,0x64,0xa0,0x00,0x00,0xa4,0xa0,
-0x1d,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xb2,0x02,0x62,0x10,0x2b,0x10,0x43,0x00,
-0x3f,0x00,0x40,0x14,0xaf,0x00,0xe2,0x34,0x20,0x00,0xe2,0x34,0xc0,0x02,0x62,0x10,
-0x2b,0x10,0x43,0x00,0xe3,0x00,0x40,0x14,0x29,0x00,0xe2,0x34,0x15,0x00,0xe2,0x34,
-0x0c,0x03,0x62,0x10,0x2b,0x10,0x43,0x00,0x9d,0x01,0x40,0x14,0x17,0x00,0xe2,0x34,
-0x09,0x00,0xe2,0x34,0xd8,0x03,0x62,0x10,0x2b,0x10,0x62,0x00,0x81,0x02,0x40,0x14,
-0x14,0x00,0xe2,0x34,0x64,0xff,0x62,0x14,0x00,0xf0,0x02,0x3c,0xff,0x00,0x07,0x3c,
-0x00,0xff,0xe7,0x34,0x24,0x10,0x07,0x02,0x7a,0xff,0x40,0x10,0xc0,0x02,0x82,0x36,
-0x04,0x43,0x64,0x92,0xff,0x00,0x02,0x3c,0x24,0x10,0x02,0x02,0x00,0xff,0x03,0x32,
-0x02,0x14,0x02,0x00,0x02,0x1a,0x03,0x00,0xfb,0xff,0x45,0x24,0x1c,0x43,0x62,0xa2,
-0x00,0x01,0x84,0x34,0xfb,0xff,0x66,0x24,0xc0,0x02,0x82,0x36,0x04,0x43,0x64,0xae,
-0x1d,0x43,0x65,0xa2,0x1f,0x43,0x66,0xa2,0x1e,0x43,0x63,0xa2,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x05,0x00,0xa2,0x34,0x91,0x02,0x62,0x10,
-0x2b,0x10,0x43,0x00,0x8e,0x00,0x40,0x14,0x00,0x00,0x00,0x00,0xde,0x02,0x65,0x10,
-0x2b,0x10,0xa3,0x00,0x32,0x01,0x40,0x14,0x02,0x00,0xa2,0x34,0x17,0x00,0x82,0x34,
-0x61,0x04,0x62,0x10,0x2b,0x10,0x62,0x00,0xa9,0x03,0x40,0x14,0x18,0x00,0x82,0x34,
-0x3d,0xff,0x62,0x14,0x00,0xf0,0x02,0x3c,0x74,0x0b,0x00,0x0c,0x00,0x00,0x00,0x00,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0xa8,0x02,0x62,0x10,0x2b,0x10,0x43,0x00,0x95,0x00,0x40,0x14,0x0c,0x00,0xc2,0x34,
-0xaa,0x00,0xe2,0x34,0xdc,0x02,0x62,0x10,0x2b,0x10,0x43,0x00,0xd9,0x00,0x40,0x14,
-0xac,0x00,0xe2,0x34,0xa6,0x00,0xe2,0x34,0x1c,0x04,0x62,0x10,0x2b,0x10,0x62,0x00,
-0x69,0x03,0x40,0x14,0xa7,0x00,0xe2,0x34,0x27,0xff,0x62,0x14,0x00,0xf0,0x02,0x3c,
-0x00,0xff,0x02,0x32,0xff,0x00,0x04,0x3c,0x02,0x8a,0x02,0x00,0x24,0x18,0x04,0x02,
-0x01,0x00,0x02,0x24,0xa6,0x04,0x22,0x12,0x02,0x1c,0x03,0x00,0x02,0x00,0x02,0x24,
-0xc9,0x04,0x22,0x12,0x03,0x00,0x02,0x24,0xdf,0x04,0x22,0x12,0x04,0x00,0x02,0x24,
-0xd1,0x04,0x22,0x12,0x08,0x00,0x02,0x24,0x2e,0x05,0x22,0x12,0x09,0x00,0x02,0x24,
-0x1e,0x05,0x22,0x12,0x0a,0x00,0x02,0x24,0x0e,0x05,0x22,0x12,0x0b,0x00,0x02,0x24,
-0xfe,0x04,0x22,0x12,0x0c,0x00,0x02,0x24,0x5e,0x05,0x22,0x12,0x0d,0x00,0x02,0x24,
-0x4e,0x05,0x22,0x12,0x0e,0x00,0x02,0x24,0x3e,0x05,0x22,0x12,0x0f,0x00,0x02,0x24,
-0x2e,0x05,0x22,0x12,0x10,0x00,0x02,0x24,0x22,0xff,0x22,0x16,0xc0,0x02,0x82,0x36,
-0xc0,0x10,0x03,0x00,0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,
-0x80,0x10,0x02,0x00,0x21,0x10,0x53,0x00,0x4c,0x51,0x43,0x94,0x48,0x51,0x44,0x94,
-0x25,0xb0,0x06,0x3c,0x00,0x1c,0x03,0x00,0x21,0x20,0x83,0x00,0x00,0x00,0xc4,0xaf,
-0x58,0x51,0x45,0x8c,0x54,0x51,0x43,0x8c,0x50,0x51,0x44,0x94,0xc8,0x02,0xc6,0x34,
-0x21,0x18,0x65,0x00,0x00,0x1c,0x03,0x00,0x21,0x20,0x83,0x00,0xc0,0x02,0x82,0x36,
-0x00,0x00,0xc4,0xac,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x66,0x02,0x62,0x10,0x2b,0x10,0x43,0x00,0xbf,0x00,0x40,0x14,0x12,0x00,0x82,0x34,
-0x00,0xf1,0x04,0x3c,0x01,0x00,0x82,0x34,0xc1,0x02,0x62,0x10,0x2b,0x10,0x43,0x00,
-0xb7,0x01,0x40,0x14,0x02,0x00,0x82,0x34,0xe3,0xfe,0x64,0x14,0x00,0xf0,0x02,0x3c,
-0xff,0x00,0x04,0x3c,0x00,0xff,0x84,0x34,0x24,0x10,0x04,0x02,0x02,0x8a,0x02,0x00,
-0x80,0x1a,0x11,0x00,0x00,0xf4,0x63,0x24,0x94,0x00,0x82,0x36,0x00,0x00,0x51,0xa4,
-0x26,0xb0,0x04,0x3c,0x42,0x89,0x03,0x00,0x98,0x00,0x86,0x36,0xff,0x01,0x02,0x24,
-0x10,0x00,0x03,0x24,0x9a,0x00,0x85,0x36,0x00,0x00,0xa2,0xa4,0x7c,0x00,0x89,0x34,
-0x00,0x00,0xc3,0xa4,0x01,0x00,0x02,0x24,0x04,0x00,0x03,0x24,0x96,0x00,0x87,0x36,
-0x7a,0x00,0x84,0x34,0xb0,0x03,0x88,0x36,0x25,0xb0,0x06,0x3c,0x00,0x00,0xe2,0xa4,
-0x44,0x00,0xc6,0x34,0x00,0x00,0x83,0xa0,0x00,0x00,0x11,0xad,0x00,0x00,0x31,0xa5,
-0x00,0x00,0xc3,0x94,0xff,0xfd,0x02,0x24,0x24,0x18,0x62,0x00,0x00,0x00,0xc3,0xa4,
-0x00,0x00,0xc2,0x94,0x00,0x00,0x00,0x00,0x00,0x02,0x42,0x34,0x00,0x00,0xc2,0xa4,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x65,0x01,0x67,0x10,0x2b,0x10,0xe3,0x00,0xc5,0x00,0x40,0x14,0x02,0x00,0xe2,0x34,
-0x07,0x00,0xa2,0x34,0xfc,0x02,0x62,0x10,0x2b,0x10,0x62,0x00,0xa9,0x01,0x40,0x14,
-0x20,0x00,0xa2,0x34,0xb0,0xfe,0x62,0x14,0x00,0xf0,0x02,0x3c,0xff,0x00,0x03,0x3c,
-0x00,0xff,0x63,0x34,0x24,0x10,0x03,0x02,0x02,0x3a,0x02,0x00,0x80,0x04,0xe0,0x10,
-0x02,0x80,0x04,0x3c,0x05,0x00,0x02,0x24,0xc2,0xfe,0xe2,0x14,0xc0,0x02,0x82,0x36,
-0x02,0x80,0x06,0x3c,0x8f,0x7d,0xc2,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xaf,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x2e,0x02,0x62,0x10,0x2b,0x10,0x43,0x00,0x98,0x00,0x40,0x14,0x0e,0x00,0xc2,0x34,
-0x01,0x00,0xc2,0x34,0xab,0x03,0x62,0x10,0x2b,0x10,0x43,0x00,0x48,0x01,0x40,0x14,
-0x00,0xff,0x02,0x3c,0x94,0xfe,0x66,0x14,0x00,0xf0,0x02,0x3c,0x5b,0x4e,0x00,0x0c,
-0x21,0x20,0x00,0x00,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x4c,0x02,0x62,0x10,0x2b,0x10,0x43,0x00,0xa6,0x00,0x40,0x14,
-0xa1,0x00,0xe2,0x34,0x22,0x00,0xe2,0x34,0xbd,0x02,0x62,0x10,0x2b,0x10,0x62,0x00,
-0x88,0x01,0x40,0x14,0x00,0x20,0x02,0x3c,0x28,0x00,0xe2,0x34,0x82,0xfe,0x62,0x14,
-0x00,0xf0,0x02,0x3c,0x0f,0x00,0x04,0x3c,0xff,0xff,0x85,0x34,0x60,0x00,0x06,0x24,
-0xba,0x44,0x00,0x0c,0x24,0x00,0x04,0x24,0x84,0x0a,0x00,0x0c,0xe8,0x03,0x04,0x24,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x0f,0x00,0x06,0x3c,0x24,0x00,0x04,0x24,0xdd,0x44,0x00,0x0c,0xff,0xff,0xc5,0x34,
-0x1f,0x00,0x51,0x30,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0xc0,0x02,0x82,0x36,0x00,0x00,0xd1,0xa3,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x18,0x02,0xc2,0x10,
-0x2b,0x10,0x46,0x00,0x01,0x01,0x40,0x14,0x00,0xa0,0x02,0x3c,0x00,0x60,0x02,0x3c,
-0x04,0x00,0xc2,0x10,0x80,0x10,0x08,0x00,0x7a,0xfe,0xc5,0x14,0xc0,0x02,0x82,0x36,
-0x80,0x10,0x08,0x00,0x21,0x10,0x48,0x00,0x21,0x10,0x53,0x00,0x21,0x10,0x49,0x00,
-0xc1,0x43,0x44,0xa0,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x3f,0x03,0x62,0x10,0x2b,0x10,0x62,0x00,0xb6,0x02,0x40,0x14,
-0xad,0x00,0xe2,0x34,0xc7,0x03,0x62,0x10,0xae,0x00,0xe2,0x34,0x4e,0xfe,0x62,0x14,
-0x00,0xf0,0x02,0x3c,0xff,0x00,0x02,0x3c,0x24,0x20,0x02,0x02,0x00,0xff,0x05,0x32,
-0x02,0x24,0x04,0x00,0x69,0x4f,0x00,0x0c,0x02,0x2a,0x05,0x00,0x00,0x00,0xc2,0xa3,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x4b,0x02,0x62,0x10,0x2b,0x10,0x62,0x00,0x17,0x01,0x40,0x14,0x03,0x00,0xa2,0x34,
-0x82,0x03,0x62,0x10,0x08,0x00,0xa2,0x34,0x3b,0xfe,0x62,0x14,0x00,0xf0,0x02,0x3c,
-0x00,0xff,0x02,0x32,0x02,0x82,0x02,0x00,0xcc,0x02,0x83,0x36,0x00,0x00,0x70,0xac,
-0x12,0x04,0x00,0x12,0x01,0x00,0x02,0x24,0x9c,0x04,0x02,0x12,0x00,0x00,0x00,0x00,
-0x7a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x4e,0x02,0x62,0x10,0x2b,0x10,0x62,0x00,
-0xe4,0x00,0x40,0x14,0x00,0xff,0x02,0x32,0x13,0x00,0x82,0x34,0x4c,0x03,0x62,0x10,
-0x14,0x00,0x82,0x34,0x24,0xfe,0x62,0x14,0x00,0xf0,0x02,0x3c,0xd3,0x0a,0x00,0x0c,
-0xfd,0x00,0x04,0x24,0x10,0x10,0x03,0x3c,0xa0,0x00,0x82,0x36,0x10,0x10,0x63,0x34,
-0x00,0xc0,0x07,0x3c,0x25,0xb0,0x06,0x3c,0x00,0x00,0x43,0xac,0xa4,0x00,0x84,0x36,
-0x00,0xa1,0xe7,0x34,0xa8,0x00,0xc6,0x34,0xc0,0x02,0x82,0x36,0x00,0x00,0x80,0xac,
-0x00,0x00,0xc7,0xac,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x60,0x02,0x62,0x10,0x2b,0x10,0x62,0x00,0xf6,0x00,0x40,0x14,0x03,0x00,0xa2,0x34,
-0x4b,0x03,0x62,0x10,0x04,0x00,0xa2,0x34,0x0b,0xfe,0x62,0x14,0x00,0xf0,0x02,0x3c,
-0xf4,0x63,0x62,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xaf,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x61,0x02,0x62,0x10,
-0x2b,0x10,0x62,0x00,0xfe,0x00,0x40,0x14,0x01,0x00,0x02,0x24,0x0f,0x00,0xc2,0x34,
-0x63,0x03,0x62,0x10,0x10,0x00,0xc2,0x34,0xfb,0xfd,0x62,0x14,0x00,0xf0,0x02,0x3c,
-0x00,0xff,0x03,0x32,0x00,0xff,0x02,0x34,0x9d,0x03,0x62,0x10,0xc0,0x02,0x82,0x36,
-0x8c,0x65,0x60,0xae,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x47,0x02,0x62,0x10,0x2b,0x10,0x62,0x00,0x02,0x01,0x40,0x14,0x03,0x00,0xe2,0x34,
-0x8d,0x03,0x62,0x10,0x04,0x00,0xe2,0x34,0xeb,0xfd,0x62,0x14,0x00,0xf0,0x02,0x3c,
-0x1e,0x57,0x00,0x0c,0x00,0x00,0x00,0x00,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x9b,0x01,0x62,0x10,0x2b,0x10,0x43,0x00,
-0xcf,0x00,0x40,0x14,0xa2,0x00,0xe2,0x34,0xa0,0x00,0xe2,0x34,0xde,0xfd,0x62,0x14,
-0x00,0xf0,0x02,0x3c,0x00,0x0f,0x02,0x32,0x02,0x22,0x02,0x00,0x01,0x00,0x03,0x24,
-0x3c,0x04,0x83,0x10,0x02,0x00,0x02,0x24,0x34,0x04,0x82,0x10,0x03,0x00,0x02,0x24,
-0x46,0x03,0x82,0x10,0x00,0x00,0x00,0x00,0xde,0x4f,0x00,0x0c,0x21,0x20,0x00,0x00,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x46,0x02,0x62,0x10,0x2b,0x10,0x62,0x00,0xe6,0xfd,0x40,0x14,0xc0,0x02,0x82,0x36,
-0x18,0x00,0xe2,0x34,0x45,0x03,0x62,0x10,0x19,0x00,0xe2,0x34,0xc6,0xfd,0x62,0x14,
-0x00,0xf0,0x02,0x3c,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x94,0x0e,0x83,0x36,
-0x9c,0x0e,0x82,0x36,0xa4,0x0e,0x84,0x36,0xac,0x0e,0x87,0x36,0x00,0x00,0x65,0x8c,
-0x00,0x00,0x48,0x8c,0x00,0x00,0x8a,0x8c,0x00,0x00,0xe6,0x8c,0x02,0x80,0x07,0x3c,
-0x68,0x15,0xed,0x24,0xb4,0x0e,0x82,0x36,0x00,0x00,0x47,0x8c,0x0c,0x40,0xa3,0x8d,
-0xff,0x03,0x02,0x3c,0x10,0x40,0xa4,0x8d,0x24,0x28,0xa2,0x00,0x24,0x30,0xc2,0x00,
-0xbc,0x0e,0x82,0x36,0x00,0x00,0x4b,0x8c,0x00,0xfc,0x02,0x24,0x02,0x2c,0x05,0x00,
-0x24,0x18,0x62,0x00,0x02,0x34,0x06,0x00,0x24,0x20,0x82,0x00,0xc4,0x0e,0x82,0x36,
-0x25,0x18,0x65,0x00,0x25,0x20,0x86,0x00,0x00,0x00,0x45,0x8c,0xff,0x03,0x06,0x3c,
-0xf0,0xff,0x02,0x3c,0xff,0x03,0x42,0x34,0x24,0x38,0xe6,0x00,0x82,0x39,0x07,0x00,
-0x24,0x20,0x82,0x00,0x24,0x40,0x06,0x01,0x08,0x40,0xa9,0x8d,0x25,0x20,0x87,0x00,
-0xcc,0x0e,0x8c,0x36,0xff,0x03,0x07,0x3c,0x00,0x00,0x86,0x8d,0x24,0x18,0x62,0x00,
-0x24,0x50,0x47,0x01,0x24,0x58,0x67,0x01,0x82,0x41,0x08,0x00,0xff,0x9f,0x02,0x3c,
-0x0f,0xc0,0x07,0x3c,0xff,0xff,0xe7,0x34,0xff,0xff,0x42,0x34,0x25,0x18,0x68,0x00,
-0x24,0x48,0x22,0x01,0x24,0x18,0x67,0x00,0xff,0x03,0x02,0x3c,0x24,0x20,0x87,0x00,
-0xff,0x00,0x07,0x3c,0x24,0x28,0xa2,0x00,0x24,0x30,0xc2,0x00,0x00,0x51,0x0a,0x00,
-0x00,0x20,0x02,0x3c,0x00,0x59,0x0b,0x00,0x00,0xff,0xe7,0x34,0x25,0x48,0x22,0x01,
-0x25,0x18,0x6a,0x00,0x25,0x20,0x8b,0x00,0x02,0x2c,0x05,0x00,0x02,0x34,0x06,0x00,
-0x24,0x10,0x07,0x02,0x08,0x40,0xa9,0xad,0x0c,0x40,0xa3,0xad,0x10,0x40,0xa4,0xad,
-0x14,0x40,0xa5,0xa5,0x4e,0x03,0x40,0x10,0x16,0x40,0xa6,0xa5,0xff,0x00,0x02,0x3c,
-0x24,0x10,0x02,0x02,0x02,0x14,0x02,0x00,0x02,0x1a,0x10,0x00,0xc7,0x42,0xa2,0xa1,
-0xc3,0x42,0xa3,0xa1,0xc3,0x42,0x62,0x92,0x25,0xb0,0x03,0x3c,0x61,0x0c,0x63,0x34,
-0x10,0x00,0xa4,0x27,0x00,0x00,0x62,0xa0,0x7a,0x54,0x00,0x0c,0x00,0x00,0x00,0x00,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x95,0x00,0xc2,0x10,0x00,0x40,0x02,0x3c,0x09,0xff,0xc2,0x10,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x7b,0x02,0xc2,0x10,
-0x2b,0x10,0x46,0x00,0x83,0x00,0x40,0x14,0x00,0xb0,0x02,0x3c,0x00,0x90,0x02,0x3c,
-0x78,0xfd,0xc2,0x14,0xc0,0x02,0x82,0x36,0x21,0x10,0x13,0x01,0x73,0x44,0x44,0xa0,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x55,0xfd,0x62,0x14,0x00,0xf0,0x02,0x3c,0x6a,0x56,0x00,0x0c,0x21,0x20,0x00,0x02,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x07,0x00,0x42,0x34,0x4c,0xfd,0x62,0x14,0x00,0xf0,0x02,0x3c,0x5b,0x4e,0x00,0x0c,
-0x07,0x00,0x04,0x24,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x02,0x1a,0x02,0x00,0x21,0x88,0x00,0x00,0xaf,0x4a,0x00,0x08,
-0x27,0xb0,0x06,0x3c,0x01,0x00,0x31,0x26,0x00,0x01,0x22,0x2e,0x08,0x00,0x40,0x10,
-0xff,0x00,0x22,0x2e,0x00,0x00,0xc2,0x94,0x00,0x00,0x00,0x00,0xff,0x00,0x42,0x30,
-0xf8,0xff,0x43,0x14,0x08,0x00,0xc6,0x24,0x00,0x00,0xd1,0xa7,0xff,0x00,0x22,0x2e,
-0x50,0xfd,0x40,0x14,0xc0,0x02,0x82,0x36,0x12,0x87,0x02,0x3c,0x00,0x00,0xc2,0xaf,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x2d,0xfd,0x62,0x14,0x00,0xf0,0x02,0x3c,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xff,0x00,0x03,0x3c,0x00,0xff,0x63,0x34,
-0x24,0x10,0x03,0x02,0x02,0x82,0x02,0x00,0xcc,0x02,0x83,0x36,0x00,0x00,0x70,0xac,
-0x00,0x00,0xd1,0x8f,0x21,0x10,0x14,0x02,0x00,0x00,0x51,0xac,0x00,0x00,0x51,0x8c,
-0xc0,0x02,0x82,0x36,0x00,0x00,0xd1,0xaf,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x00,0x64,0x62,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xaf,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0xf4,0x02,0x62,0x10,0xa3,0x00,0xe2,0x34,0x0f,0xfd,0x62,0x14,0x00,0xf0,0x02,0x3c,
-0xc0,0x02,0x82,0x36,0x8c,0x65,0x60,0xae,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xec,0x63,0x62,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xaf,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0xe6,0x63,0x62,0xa6,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x08,0x40,0x63,0x8e,0xff,0x9f,0x07,0x3c,0xff,0xff,0xe7,0x34,
-0x02,0x2c,0x10,0x00,0x00,0x1f,0x04,0x32,0x24,0x18,0x67,0x00,0x25,0x18,0x62,0x00,
-0x02,0x8a,0x04,0x00,0x3f,0x00,0xa5,0x30,0xc0,0x02,0x82,0x36,0x08,0x40,0x63,0xae,
-0xbc,0x42,0x71,0xa2,0xc1,0x42,0x65,0xa2,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x00,0x00,0xe2,0x92,0x00,0x00,0x00,0x00,0xfa,0x00,0x42,0x30,
-0x00,0x00,0xe2,0xa2,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x00,0x00,0xe2,0x92,0x00,0x00,0x00,0x00,0xfd,0x00,0x42,0x30,
-0x00,0x00,0xe2,0xa2,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xf7,0xfc,0xc2,0x14,0xc0,0x02,0x82,0x36,0x80,0x10,0x08,0x00,
-0x21,0x10,0x53,0x00,0x60,0x45,0x43,0xac,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x80,0x10,0x08,0x00,0x21,0x10,0x48,0x00,
-0x21,0x10,0x53,0x00,0x21,0x10,0x49,0x00,0x34,0x43,0x44,0xa0,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x77,0x56,0x00,0x0c,
-0x21,0x20,0x00,0x02,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xff,0xff,0x02,0x34,0x8c,0x65,0x62,0xae,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x07,0x0b,0x00,0x0c,
-0x00,0x00,0x00,0x00,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xf0,0x63,0x62,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xaf,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x08,0x40,0x62,0x8e,0xff,0x9f,0x03,0x3c,0xff,0xff,0x63,0x34,0x24,0x10,0x43,0x00,
-0x08,0x40,0x62,0xae,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
-0x00,0x60,0x81,0x40,0x22,0x51,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xff,0x00,0x07,0x3c,0x00,0xff,0xe7,0x34,
-0x24,0x10,0x07,0x02,0x02,0x82,0x02,0x00,0xcc,0x02,0x43,0x36,0x00,0x00,0x70,0xac,
-0x21,0x10,0x12,0x02,0x00,0x00,0x51,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0xd1,0xaf,
-0x00,0x00,0x51,0x8c,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xb7,0x4f,0x00,0x0c,0x00,0x00,0x00,0x00,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x21,0x88,0x00,0x00,
-0x6c,0x4b,0x00,0x08,0x27,0xb0,0x04,0x3c,0x01,0x00,0x31,0x26,0x00,0x01,0x22,0x2e,
-0x0a,0x00,0x40,0x10,0xff,0x00,0x22,0x2e,0x00,0x00,0x83,0x94,0x00,0x00,0x00,0x00,
-0xff,0xff,0x67,0x30,0xff,0x00,0xe2,0x30,0xf0,0x00,0x42,0x28,0xf6,0xff,0x40,0x14,
-0x08,0x00,0x84,0x24,0x00,0x00,0xc7,0xa7,0xff,0x00,0x22,0x2e,0x91,0xfc,0x40,0x14,
-0xc0,0x02,0x82,0x36,0x12,0x87,0x02,0x3c,0x00,0x00,0xc2,0xaf,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xe4,0x63,0x62,0x96,
-0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xa7,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x04,0x64,0x62,0x92,0x00,0x00,0x00,0x00,
-0x00,0x00,0xc2,0xaf,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x00,0xff,0x02,0x32,0x02,0x12,0x02,0x00,0x03,0x00,0x43,0x2c,
-0x02,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x02,0x40,0x62,0xa2,0x02,0x40,0x63,0x92,
-0x90,0x0c,0x42,0x36,0x00,0x00,0x43,0xa0,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xd7,0x56,0x00,0x0c,0x00,0x00,0x00,0x00,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x21,0x10,0x13,0x01,0x56,0x44,0x44,0xa0,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xff,0x00,0x03,0x3c,0x24,0x20,0x03,0x02,
-0x73,0x0e,0x00,0x0c,0x02,0x24,0x04,0x00,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x1c,0x10,0x00,0x00,0x1f,0x02,0x32,
-0x02,0x8a,0x02,0x00,0x3f,0x00,0x65,0x30,0xc1,0x42,0x65,0xa2,0xbc,0x42,0x71,0xa2,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x1f,0x12,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xaf,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0x03,0x40,0x62,0x92,0x0e,0x0c,0x44,0x36,
-0x01,0x00,0x42,0x24,0xff,0x00,0x43,0x30,0x00,0x00,0x83,0xa0,0x03,0x40,0x62,0xa2,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x00,0xff,0x02,0x32,0x02,0x3a,0x02,0x00,0x1a,0x01,0xe0,0x10,0x4f,0x00,0x82,0x36,
-0x94,0x00,0x42,0x36,0x00,0x00,0x43,0x94,0xff,0xff,0xe2,0x24,0xb0,0x03,0x45,0x36,
-0xff,0xff,0x71,0x30,0x1b,0x00,0x27,0x02,0x02,0x00,0xe0,0x14,0x00,0x00,0x00,0x00,
-0x0d,0x00,0x07,0x00,0xff,0xff,0x47,0x30,0x00,0x00,0xb1,0xac,0x80,0xff,0x02,0x24,
-0x00,0x19,0x07,0x00,0x25,0x18,0x62,0x00,0x4f,0x00,0x44,0x36,0x9e,0x00,0x46,0x36,
-0x00,0x00,0xa7,0xac,0x00,0x00,0x83,0xa0,0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,
-0x12,0x88,0x00,0x00,0x80,0x12,0x11,0x00,0x00,0xfc,0x42,0x24,0x00,0x00,0xb1,0xac,
-0x00,0x00,0xd1,0xa4,0x42,0x89,0x02,0x00,0x26,0xb0,0x02,0x3c,0x7c,0x00,0x42,0x34,
-0x00,0x00,0xb1,0xac,0x00,0x00,0x51,0xa4,0x25,0xb0,0x02,0x3c,0x44,0x00,0x42,0x34,
-0x00,0x00,0x43,0x94,0xff,0xfd,0x02,0x24,0x24,0x18,0x62,0x00,0x00,0x00,0x83,0xa4,
-0x00,0x00,0x82,0x94,0x00,0x00,0x00,0x00,0x00,0x02,0x42,0x34,0x00,0x00,0x82,0xa4,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x24,0x10,0x08,0x02,0xcc,0x02,0x43,0x36,0x00,0xff,0x04,0x32,0x02,0x3c,0x02,0x00,
-0x00,0x00,0x70,0xac,0x04,0x00,0xe0,0x10,0x02,0x82,0x04,0x00,0x01,0x00,0x02,0x24,
-0x02,0x00,0xe2,0x10,0x01,0x00,0x04,0x24,0x21,0x20,0x00,0x00,0x7a,0x42,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x0f,0x00,0x06,0x3c,0x21,0x20,0x00,0x02,0xdd,0x44,0x00,0x0c,
-0xff,0xff,0xc5,0x34,0x0f,0x00,0x07,0x3c,0xff,0xff,0xe7,0x34,0x24,0x88,0x47,0x00,
-0xc0,0x02,0x82,0x36,0x00,0x00,0xd1,0xaf,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x28,0xb0,0x02,0x3c,0x00,0x00,0x43,0x90,0xff,0x00,0x02,0x24,
-0xff,0x00,0x70,0x30,0xf3,0xfb,0x02,0x12,0xc0,0x02,0x82,0x36,0x28,0xb0,0x05,0x3c,
-0xff,0x00,0x04,0x24,0xc0,0x10,0x10,0x00,0x21,0x10,0x45,0x00,0x00,0x00,0x43,0x90,
-0x00,0x00,0x00,0x00,0xff,0x00,0x70,0x30,0xfb,0xff,0x04,0x16,0xc0,0x10,0x10,0x00,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x00,0x1f,0x02,0x32,0x02,0x1c,0x10,0x00,0x02,0x8a,0x02,0x00,0x3f,0x00,0x65,0x30,
-0xc0,0x02,0x82,0x36,0xbc,0x42,0x71,0xa2,0xc1,0x42,0x65,0xa2,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xff,0x00,0x07,0x3c,0x24,0x20,0x07,0x02,
-0x15,0x51,0x00,0x0c,0x02,0x24,0x04,0x00,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xe8,0x63,0x62,0x92,0x00,0x00,0x00,0x00,
-0x00,0x00,0xc2,0xaf,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xfc,0x63,0x62,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xaf,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x00,0x00,0xe2,0x92,0x00,0x00,0x00,0x00,0xff,0x00,0x51,0x30,0x05,0x00,0x23,0x36,
-0xc0,0x02,0x82,0x36,0x00,0x00,0xe3,0xa2,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xc0,0x02,0x82,0x36,0xe6,0x63,0x60,0xa6,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xbd,0x56,0x00,0x0c,0x21,0x20,0x00,0x02,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x41,0x0b,0x00,0x0c,0x00,0x00,0x00,0x00,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xe2,0x92,0x00,0x00,0x00,0x00,
-0xff,0x00,0x51,0x30,0x02,0x00,0x23,0x36,0xc0,0x02,0x82,0x36,0x00,0x00,0xe3,0xa2,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,
-0xec,0x91,0x42,0x24,0x00,0x00,0x47,0x8c,0xc0,0x02,0x43,0x36,0x25,0xb0,0x0c,0x3c,
-0x08,0x40,0xe4,0x8c,0x00,0x00,0x60,0xac,0x42,0x17,0x04,0x00,0x03,0x00,0x42,0x30,
-0x60,0x00,0x40,0x14,0x03,0x0d,0x42,0x36,0x00,0x00,0x45,0x90,0x10,0x40,0xe6,0x8c,
-0xff,0x9f,0x03,0x3c,0xff,0xff,0x63,0x34,0xff,0x3f,0x02,0x3c,0x24,0x20,0x83,0x00,
-0xff,0xff,0x42,0x34,0x00,0x20,0x03,0x3c,0x24,0x58,0xc2,0x00,0x25,0x20,0x83,0x00,
-0x00,0x40,0x02,0x3c,0x70,0x00,0xa5,0x30,0x25,0x58,0x62,0x01,0x08,0x01,0xa0,0x10,
-0x08,0x40,0xe4,0xac,0x94,0x0e,0x82,0x35,0x9c,0x0e,0x83,0x35,0xa4,0x0e,0x86,0x35,
-0x00,0x00,0x45,0x8c,0xac,0x0e,0x87,0x35,0x00,0x00,0x68,0x8c,0x00,0x00,0xca,0x8c,
-0x02,0x80,0x06,0x3c,0x00,0x00,0xe4,0x8c,0x68,0x15,0xc6,0x24,0x0c,0x40,0xc3,0x8c,
-0xb4,0x0e,0x82,0x35,0x00,0x00,0x47,0x8c,0xff,0x03,0x02,0x3c,0x00,0xfc,0x06,0x24,
-0x24,0x28,0xa2,0x00,0x24,0x20,0x82,0x00,0xbc,0x0e,0x82,0x35,0x00,0x00,0x49,0x8c,
-0x02,0x2c,0x05,0x00,0x24,0x10,0x66,0x01,0x24,0x18,0x66,0x00,0x02,0x24,0x04,0x00,
-0xc4,0x0e,0x86,0x35,0x25,0x18,0x65,0x00,0x25,0x10,0x44,0x00,0x00,0x00,0xc5,0x8c,
-0xff,0x03,0x04,0x3c,0xf0,0xff,0x06,0x3c,0xff,0x03,0xc6,0x34,0x24,0x38,0xe4,0x00,
-0xcc,0x0e,0x8b,0x35,0x24,0x40,0x04,0x01,0x82,0x39,0x07,0x00,0x00,0x00,0x64,0x8d,
-0x24,0x10,0x46,0x00,0x24,0x18,0x66,0x00,0x25,0x10,0x47,0x00,0x82,0x41,0x08,0x00,
-0xff,0x03,0x07,0x3c,0x0f,0xc0,0x06,0x3c,0x24,0x50,0x47,0x01,0x24,0x48,0x27,0x01,
-0xff,0xff,0xc6,0x34,0x25,0x18,0x68,0x00,0x24,0x28,0xa7,0x00,0x24,0x20,0x87,0x00,
-0x00,0x51,0x0a,0x00,0x24,0x18,0x66,0x00,0x00,0x49,0x09,0x00,0x24,0x10,0x46,0x00,
-0x02,0x80,0x07,0x3c,0x68,0x15,0xe7,0x24,0x25,0x18,0x6a,0x00,0x25,0x10,0x49,0x00,
-0x02,0x2c,0x05,0x00,0x02,0x24,0x04,0x00,0x0c,0x40,0xe3,0xac,0x10,0x40,0xe2,0xac,
-0x14,0x40,0xe5,0xa4,0x16,0x40,0xe4,0xa4,0x02,0x80,0x02,0x3c,0x68,0x15,0x43,0x24,
-0x0c,0x40,0x62,0x8c,0x00,0x00,0x00,0x00,0xbd,0x00,0x40,0x04,0x00,0x00,0x00,0x00,
-0x00,0xff,0x02,0x32,0xc6,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,
-0xc3,0x42,0x62,0xa0,0x7a,0x54,0x00,0x0c,0x10,0x00,0xa4,0x27,0xc2,0x53,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x0c,0x40,0x62,0x8e,0x00,0x80,0x03,0x3c,0x25,0x10,0x43,0x00,
-0x0c,0x40,0x62,0xae,0xc3,0x42,0x62,0x92,0x25,0xb0,0x03,0x3c,0x61,0x0c,0x63,0x34,
-0x00,0x00,0x62,0xa0,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xcf,0x4e,0x00,0x0c,0x21,0x20,0x00,0x02,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x17,0x51,0x00,0x0c,
-0x00,0x00,0x00,0x00,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x9e,0x00,0x83,0x36,0x00,0x00,0x40,0xa0,0x00,0x00,0x60,0xa4,
-0x94,0x00,0x82,0x36,0x00,0x00,0x43,0x94,0x25,0xb0,0x06,0x3c,0x44,0x00,0xc6,0x34,
-0xff,0xff,0x71,0x30,0x80,0x12,0x11,0x00,0x00,0xf8,0x42,0x24,0x42,0x89,0x02,0x00,
-0x26,0xb0,0x02,0x3c,0xb0,0x03,0x83,0x36,0x7c,0x00,0x42,0x34,0x00,0x00,0x71,0xac,
-0x00,0x00,0x51,0xa4,0x00,0x00,0xc3,0x94,0xff,0xfd,0x02,0x24,0x24,0x18,0x62,0x00,
-0x00,0x00,0xc3,0xa4,0x00,0x00,0xc2,0x94,0x00,0x00,0x00,0x00,0x00,0x02,0x42,0x34,
-0x00,0x00,0xc2,0xa4,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x5b,0x4e,0x00,0x0c,0x01,0x00,0x04,0x24,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x80,0x10,0x08,0x00,
-0x21,0x10,0x53,0x00,0xec,0x44,0x43,0xac,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xa7,0x0b,0x00,0x0c,0x00,0x00,0x00,0x00,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x28,0xb0,0x11,0x3c,0x00,0x00,0x22,0x96,0xff,0x00,0x04,0x3c,0x24,0x18,0x04,0x02,
-0x02,0x24,0x03,0x00,0xff,0x00,0x42,0x30,0x0a,0x00,0x82,0x10,0xff,0x7f,0x02,0x3c,
-0x08,0x00,0x31,0x26,0x00,0x00,0x22,0x96,0xff,0xff,0x23,0x32,0xff,0x00,0x42,0x30,
-0x03,0x00,0x82,0x10,0x00,0x08,0x63,0x2c,0xf9,0xff,0x60,0x14,0x00,0x00,0x00,0x00,
-0xff,0x7f,0x02,0x3c,0xff,0xff,0x42,0x34,0x24,0x10,0x22,0x02,0x00,0x00,0xc2,0xaf,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0xf8,0x63,0x62,0x92,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xaf,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xff,0x00,0x03,0x3c,
-0x24,0x10,0x03,0x02,0x00,0xff,0x04,0x32,0xcc,0x02,0x83,0x36,0x02,0x3c,0x02,0x00,
-0x00,0x00,0x70,0xac,0x04,0x00,0xe0,0x10,0x02,0x82,0x04,0x00,0x01,0x00,0x02,0x24,
-0x02,0x00,0xe2,0x10,0x01,0x00,0x04,0x24,0x21,0x20,0x00,0x00,0x7a,0x42,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x00,0x00,0xd1,0x8f,0x0f,0x00,0x06,0x3c,0xff,0xff,0xc5,0x34,
-0x21,0x20,0x00,0x02,0xba,0x44,0x00,0x0c,0x21,0x30,0x20,0x02,0x0f,0x00,0x07,0x3c,
-0x21,0x20,0x00,0x02,0xdd,0x44,0x00,0x0c,0xff,0xff,0xe5,0x34,0x00,0x00,0xc2,0xaf,
-0x21,0x88,0x40,0x00,0x25,0xb0,0x02,0x3c,0xc8,0x02,0x42,0x34,0x00,0x00,0x51,0xac,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x25,0xb0,0x06,0x3c,0xff,0x00,0x02,0x24,0x56,0x01,0xc6,0x34,0x00,0x00,0xc2,0xa4,
-0x01,0x00,0x03,0x24,0x02,0x80,0x07,0x3c,0xc0,0x02,0x82,0x36,0xb8,0x7d,0xe3,0xa0,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xde,0x4f,0x00,0x0c,
-0x03,0x00,0x04,0x24,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xde,0x4e,0x00,0x0c,0x21,0x20,0x00,0x02,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x08,0x40,0x62,0x8e,
-0xff,0x9f,0x04,0x3c,0xff,0xff,0x84,0x34,0x24,0x10,0x44,0x00,0x08,0x40,0x62,0xae,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0xc0,0x10,0x03,0x00,0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,
-0x80,0x10,0x02,0x00,0x21,0x10,0x53,0x00,0x70,0x51,0x43,0x8c,0xc0,0x02,0x82,0x36,
-0x00,0x00,0xc3,0xaf,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x7a,0x54,0x00,0x0c,0x10,0x00,0xa4,0x27,0xc3,0x42,0x62,0x92,0x25,0xb0,0x03,0x3c,
-0x61,0x0c,0x63,0x34,0x00,0x00,0x62,0xa0,0xd4,0x4c,0x00,0x08,0xc0,0x02,0x82,0x36,
-0x22,0x51,0x00,0x0c,0x10,0x40,0xeb,0xac,0xbd,0x4c,0x00,0x08,0x02,0x80,0x02,0x3c,
-0xc6,0x4c,0x00,0x08,0x12,0x00,0x02,0x24,0x1a,0x57,0x00,0x0c,0x00,0x00,0x00,0x00,
-0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0xff,0xff,0x02,0x34,0x8c,0x65,0x62,0xae,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,0x21,0x10,0x43,0x00,
-0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x53,0x00,
-0x74,0x51,0x43,0x8c,0xc0,0x02,0x82,0x36,0x00,0x00,0xc3,0xaf,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,0x21,0x10,0x43,0x00,
-0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x53,0x00,
-0xd4,0x51,0x43,0x8c,0xc0,0x02,0x82,0x36,0x00,0x00,0xc3,0xaf,0x00,0x00,0x40,0xac,
-0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,0x21,0x10,0x43,0x00,
-0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x02,0x80,0x06,0x3c,0x80,0x10,0x02,0x00,
-0xe0,0x66,0xc3,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0xc0,0x02,0x82,0x36,
-0x00,0x00,0xc4,0xaf,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,
-0x12,0x00,0x02,0x24,0xc7,0x42,0xa2,0xa1,0x77,0x4a,0x00,0x08,0xc3,0x42,0xa2,0xa1,
-0x88,0x7d,0x82,0x94,0x00,0x00,0x00,0x00,0x00,0x00,0xc2,0xaf,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x7a,0x42,0x00,0x0c,
-0x21,0x20,0x00,0x00,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xff,0x00,0x06,0x3c,0x00,0xff,0xc6,0x34,0x00,0x00,0xc5,0x8f,
-0x24,0x20,0x06,0x02,0xe1,0x50,0x00,0x0c,0x02,0x22,0x04,0x00,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,
-0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x02,0x80,0x07,0x3c,
-0x80,0x10,0x02,0x00,0xf0,0x66,0xe3,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,
-0xc0,0x02,0x82,0x36,0x00,0x00,0xc4,0xaf,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,
-0x21,0x10,0x43,0x00,0x02,0x80,0x06,0x3c,0x80,0x10,0x02,0x00,0xec,0x66,0xc3,0x24,
-0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0xc0,0x02,0x82,0x36,0x00,0x00,0xc4,0xaf,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,
-0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x02,0x80,0x04,0x3c,
-0xe8,0x66,0x83,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,
-0xc0,0x02,0x82,0x36,0x00,0x00,0xc4,0xaf,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,
-0x21,0x10,0x43,0x00,0x02,0x80,0x07,0x3c,0x80,0x10,0x02,0x00,0xe4,0x66,0xe3,0x24,
-0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0xc0,0x02,0x82,0x36,0x00,0x00,0xc4,0xaf,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,
-0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x02,0x80,0x04,0x3c,
-0x00,0x67,0x83,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,
-0xc0,0x02,0x82,0x36,0x00,0x00,0xc4,0xaf,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,
-0x21,0x10,0x43,0x00,0x02,0x80,0x07,0x3c,0x80,0x10,0x02,0x00,0xfc,0x66,0xe3,0x24,
-0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0xc0,0x02,0x82,0x36,0x00,0x00,0xc4,0xaf,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,
-0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,0x02,0x80,0x06,0x3c,
-0x80,0x10,0x02,0x00,0xf8,0x66,0xc3,0x24,0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,
-0xc0,0x02,0x82,0x36,0x00,0x00,0xc4,0xaf,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xc0,0x10,0x03,0x00,0x21,0x10,0x43,0x00,0x80,0x10,0x02,0x00,
-0x21,0x10,0x43,0x00,0x02,0x80,0x04,0x3c,0xf4,0x66,0x83,0x24,0x80,0x10,0x02,0x00,
-0x21,0x10,0x43,0x00,0x00,0x00,0x44,0x8c,0xc0,0x02,0x82,0x36,0x00,0x00,0xc4,0xaf,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0xde,0x4f,0x00,0x0c,
-0x02,0x00,0x04,0x24,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0xde,0x4f,0x00,0x0c,0x01,0x00,0x04,0x24,0xc0,0x02,0x82,0x36,
-0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,0x00,0x00,0x00,0x00,0x7a,0x42,0x00,0x0c,
-0x01,0x00,0x04,0x24,0xc0,0x02,0x82,0x36,0x00,0x00,0x40,0xac,0x08,0x48,0x00,0x08,
-0x00,0x00,0x00,0x00,0x25,0xb0,0x05,0x3c,0x01,0x00,0x06,0x24,0x01,0x80,0x02,0x3c,
-0x04,0x30,0x86,0x00,0xf1,0x02,0xa7,0x34,0xed,0x02,0xa4,0x34,0x6c,0x39,0x42,0x24,
-0x18,0x03,0xa5,0x34,0x08,0x00,0x03,0x24,0x00,0x00,0xa2,0xac,0x00,0x00,0xe3,0xa0,
-0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,
-0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,0x00,0x00,0x80,0xa0,0x00,0x00,0x86,0xa0,
-0x00,0x00,0x80,0xa0,0x00,0x00,0xe0,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x01,0x80,0x02,0x3c,0x25,0xb0,0x03,0x3c,0xc8,0x39,0x42,0x24,0x18,0x03,0x63,0x34,
-0x00,0x00,0x62,0xac,0x00,0x00,0x83,0x90,0x30,0x00,0x02,0x24,0x05,0x00,0x62,0x10,
-0x21,0x20,0x00,0x00,0x31,0x00,0x02,0x24,0x02,0x00,0x62,0x10,0x01,0x00,0x04,0x24,
-0x07,0x00,0x04,0x24,0x5b,0x4e,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x3c,
-0x25,0xb0,0x03,0x3c,0x04,0x3a,0x42,0x24,0x18,0x03,0x63,0x34,0x02,0x80,0x04,0x3c,
-0x00,0x00,0x62,0xac,0x08,0x00,0xe0,0x03,0xc4,0x7d,0x80,0xac,0x02,0x80,0x02,0x3c,
-0x08,0x7b,0x42,0x24,0xc0,0x20,0x04,0x00,0x21,0x20,0x82,0x00,0x21,0x28,0x00,0x00,
-0x00,0x60,0x06,0x40,0x01,0x00,0xc1,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,
-0x00,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x09,0x00,0x44,0x10,0x00,0x00,0x00,0x00,
-0x04,0x00,0x43,0x8c,0x21,0x28,0x40,0x00,0x00,0x00,0x42,0x8c,0x00,0x00,0x00,0x00,
-0x00,0x00,0x62,0xac,0x04,0x00,0x43,0xac,0x00,0x00,0xa5,0xac,0x04,0x00,0xa5,0xac,
-0x00,0x60,0x86,0x40,0x08,0x00,0xe0,0x03,0x21,0x10,0xa0,0x00,0x21,0x18,0x80,0x00,
-0xe8,0xff,0xbd,0x27,0x01,0x01,0x62,0x2c,0x10,0x00,0xbf,0xaf,0x01,0x00,0x04,0x24,
-0x01,0x02,0x65,0x2c,0x0a,0x00,0x40,0x14,0x21,0x30,0x00,0x00,0x02,0x00,0x04,0x24,
-0x07,0x00,0xa0,0x14,0x01,0x08,0x62,0x2c,0x05,0x00,0x40,0x14,0x03,0x00,0x04,0x24,
-0x10,0x00,0xbf,0x8f,0x21,0x10,0xc0,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,
-0x89,0x4e,0x00,0x0c,0x00,0x00,0x00,0x00,0x10,0x00,0xbf,0x8f,0x21,0x30,0x40,0x00,
-0x21,0x10,0xc0,0x00,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x02,0x80,0x03,0x3c,
-0x20,0x7b,0x62,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x00,0x60,0x06,0x40,
-0x01,0x00,0xc1,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x10,0x00,0x83,0x8c,
-0x02,0x80,0x02,0x3c,0x08,0x7b,0x42,0x24,0xc0,0x18,0x03,0x00,0x21,0x18,0x62,0x00,
-0x00,0x00,0x65,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0xac,0x04,0x00,0xa4,0xac,
-0x00,0x00,0x64,0xac,0x04,0x00,0x83,0xac,0x00,0x60,0x86,0x40,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x02,0x24,0x04,0x00,0xff,0x00,0x84,0x30,0xc0,0x18,0x04,0x00,
-0x21,0x18,0x64,0x00,0x80,0x18,0x03,0x00,0x21,0x18,0x64,0x00,0x02,0x80,0x02,0x3c,
-0x68,0x15,0x42,0x24,0x80,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x78,0x51,0x64,0x8c,
-0xff,0xf1,0x02,0x24,0x24,0x20,0x82,0x00,0x08,0x00,0xe0,0x03,0x78,0x51,0x64,0xac,
-0x02,0x24,0x04,0x00,0xff,0x00,0x84,0x30,0xc0,0x18,0x04,0x00,0x21,0x18,0x64,0x00,
-0x80,0x18,0x03,0x00,0x21,0x18,0x64,0x00,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,
-0x80,0x18,0x03,0x00,0x21,0x18,0x62,0x00,0x78,0x51,0x64,0x8c,0xff,0xf1,0x02,0x24,
-0x24,0x20,0x82,0x00,0x00,0x02,0x84,0x34,0x08,0x00,0xe0,0x03,0x78,0x51,0x64,0xac,
-0xe0,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0xc0,0x80,0x04,0x00,0x21,0x80,0x04,0x02,
-0x80,0x80,0x10,0x00,0x21,0x80,0x04,0x02,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,
-0x80,0x80,0x10,0x00,0x21,0x80,0x02,0x02,0x1c,0x00,0xbf,0xaf,0x18,0x00,0xb2,0xaf,
-0x14,0x00,0xb1,0xaf,0x78,0x51,0x05,0x8e,0xff,0x1f,0x02,0x3c,0x25,0xb0,0x12,0x3c,
-0xff,0xff,0x42,0x34,0x70,0x51,0x02,0xae,0x84,0x01,0x43,0x36,0xf8,0xff,0x02,0x24,
-0x00,0x00,0x66,0x8c,0x24,0x28,0xa2,0x00,0xff,0xfe,0x02,0x24,0x24,0x28,0xa2,0x00,
-0xff,0xef,0x03,0x24,0x24,0x28,0xa3,0x00,0x74,0x51,0x06,0xae,0x78,0x51,0x05,0xae,
-0xce,0x0d,0x00,0x0c,0x21,0x88,0x80,0x00,0x7a,0x51,0x02,0x92,0x21,0x88,0x32,0x02,
-0x1c,0x00,0xbf,0x8f,0x60,0x01,0x22,0xa2,0x18,0x00,0xb2,0x8f,0x64,0x51,0x00,0xae,
-0x48,0x51,0x00,0xae,0x4c,0x51,0x00,0xae,0x50,0x51,0x00,0xae,0x54,0x51,0x00,0xae,
-0x58,0x51,0x00,0xae,0x5c,0x51,0x00,0xae,0x60,0x51,0x00,0xae,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xff,0x00,0xa5,0x30,
-0xc0,0x10,0x05,0x00,0x21,0x10,0x45,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x45,0x00,
-0x02,0x80,0x03,0x3c,0x68,0x15,0x63,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,
-0x78,0x51,0x43,0x8c,0x25,0xb0,0x05,0x3c,0xff,0x00,0xc6,0x30,0x21,0x30,0xc5,0x00,
-0xaf,0x01,0xc2,0x90,0x07,0x00,0x63,0x30,0x80,0x18,0x03,0x00,0x21,0x18,0x65,0x00,
-0xff,0x00,0x88,0x30,0xff,0x00,0x49,0x30,0x84,0x01,0x66,0x8c,0x21,0x50,0x00,0x00,
-0x21,0x58,0x00,0x00,0x2b,0x00,0x20,0x11,0x21,0x20,0x00,0x01,0x2b,0x00,0xc0,0x10,
-0x2b,0x10,0x09,0x01,0x21,0x28,0x00,0x00,0x3e,0x4f,0x00,0x08,0x01,0x00,0x07,0x24,
-0xff,0x00,0x65,0x30,0x1d,0x00,0xa2,0x2c,0x07,0x00,0x40,0x10,0xff,0xff,0x02,0x25,
-0x04,0x10,0xa7,0x00,0x24,0x10,0x46,0x00,0xf9,0xff,0x40,0x10,0x01,0x00,0xa3,0x24,
-0x21,0x58,0xa0,0x00,0xff,0xff,0x02,0x25,0xff,0x00,0x45,0x30,0x2b,0x18,0xab,0x00,
-0x0f,0x00,0x60,0x14,0x2b,0x10,0x49,0x01,0x01,0x00,0x04,0x24,0x04,0x10,0xa4,0x00,
-0x24,0x10,0x46,0x00,0xff,0xff,0xa7,0x24,0x04,0x00,0x40,0x10,0x01,0x00,0x43,0x25,
-0x17,0x00,0x49,0x11,0xff,0x00,0x6a,0x30,0x21,0x40,0xa0,0x00,0xff,0x00,0xe5,0x30,
-0x2b,0x10,0xab,0x00,0xf6,0xff,0x40,0x10,0x04,0x10,0xa4,0x00,0x2b,0x10,0x49,0x01,
-0x08,0x00,0x40,0x10,0x21,0x20,0x00,0x01,0x23,0x10,0x2a,0x01,0x2a,0x10,0x62,0x01,
-0x04,0x00,0x40,0x14,0x21,0x20,0x00,0x00,0x23,0x10,0x69,0x01,0x21,0x10,0x4a,0x00,
-0xff,0x00,0x44,0x30,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0xfd,0xff,0x40,0x14,
-0x21,0x20,0x00,0x00,0x23,0x10,0x09,0x01,0x5f,0x4f,0x00,0x08,0xff,0x00,0x44,0x30,
-0x21,0x20,0x00,0x01,0x08,0x00,0xe0,0x03,0x21,0x10,0x80,0x00,0xff,0x00,0x84,0x30,
-0xc0,0x10,0x04,0x00,0x21,0x10,0x44,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,
-0x02,0x80,0x03,0x3c,0x68,0x15,0x63,0x24,0x80,0x10,0x02,0x00,0x21,0x10,0x43,0x00,
-0x25,0xb0,0x06,0x3c,0x78,0x51,0x43,0x8c,0xff,0x00,0xa5,0x30,0x21,0x20,0x86,0x00,
-0x21,0x28,0xa6,0x00,0x60,0x01,0x82,0x90,0xaf,0x01,0xa4,0x90,0x07,0x00,0x63,0x30,
-0x80,0x18,0x03,0x00,0x21,0x18,0x66,0x00,0xff,0x00,0x48,0x30,0xff,0x00,0x89,0x30,
-0x84,0x01,0x66,0x8c,0x21,0x50,0x00,0x00,0x21,0x58,0x00,0x00,0x2b,0x00,0x20,0x11,
-0x21,0x20,0x00,0x01,0x2b,0x00,0xc0,0x10,0x2b,0x10,0x09,0x01,0x21,0x28,0x00,0x00,
-0x8c,0x4f,0x00,0x08,0x01,0x00,0x07,0x24,0xff,0x00,0x65,0x30,0x1d,0x00,0xa2,0x2c,
-0x07,0x00,0x40,0x10,0xff,0xff,0x02,0x25,0x04,0x10,0xa7,0x00,0x24,0x10,0x46,0x00,
-0xf9,0xff,0x40,0x10,0x01,0x00,0xa3,0x24,0x21,0x58,0xa0,0x00,0xff,0xff,0x02,0x25,
-0xff,0x00,0x45,0x30,0x2b,0x18,0xab,0x00,0x0f,0x00,0x60,0x14,0x2b,0x10,0x49,0x01,
-0x01,0x00,0x04,0x24,0x04,0x10,0xa4,0x00,0x24,0x10,0x46,0x00,0xff,0xff,0xa7,0x24,
-0x04,0x00,0x40,0x10,0x01,0x00,0x43,0x25,0x17,0x00,0x49,0x11,0xff,0x00,0x6a,0x30,
-0x21,0x40,0xa0,0x00,0xff,0x00,0xe5,0x30,0x2b,0x10,0xab,0x00,0xf6,0xff,0x40,0x10,
-0x04,0x10,0xa4,0x00,0x2b,0x10,0x49,0x01,0x08,0x00,0x40,0x10,0x21,0x20,0x00,0x01,
-0x23,0x10,0x2a,0x01,0x2a,0x10,0x62,0x01,0x04,0x00,0x40,0x14,0x21,0x20,0x00,0x00,
-0x23,0x10,0x69,0x01,0x21,0x10,0x4a,0x00,0xff,0x00,0x44,0x30,0x08,0x00,0xe0,0x03,
-0x21,0x10,0x80,0x00,0xfd,0xff,0x40,0x14,0x21,0x20,0x00,0x00,0x23,0x10,0x09,0x01,
-0xad,0x4f,0x00,0x08,0xff,0x00,0x44,0x30,0x21,0x20,0x00,0x01,0x08,0x00,0xe0,0x03,
-0x21,0x10,0x80,0x00,0xe0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x10,0x00,0xb0,0xaf,
-0x68,0x15,0x50,0x24,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x1c,0x00,0xbf,0xaf,
-0x21,0x88,0x00,0x00,0x21,0x90,0x00,0x02,0xee,0x4e,0x00,0x0c,0x21,0x20,0x20,0x02,
-0x7a,0x51,0x02,0x92,0x21,0x28,0x00,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x52,0x00,
-0xec,0x44,0x44,0x8c,0x60,0x45,0x43,0x8c,0x00,0x00,0x00,0x00,0x21,0x18,0x64,0x00,
-0x42,0x18,0x03,0x00,0x44,0x51,0x03,0xae,0x21,0x10,0x05,0x02,0x01,0x00,0xa5,0x24,
-0x1d,0x00,0xa3,0x28,0xb6,0x51,0x40,0xa0,0x7c,0x51,0x40,0xa0,0xfa,0xff,0x60,0x14,
-0x99,0x51,0x40,0xa0,0x01,0x00,0x31,0x26,0x20,0x00,0x22,0x2a,0xd4,0x51,0x00,0xae,
-0xe9,0xff,0x40,0x14,0x94,0x00,0x10,0x26,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,
-0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
-0xc8,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x30,0x00,0xbe,0xaf,0x28,0x00,0xb6,0xaf,
-0x68,0x15,0x46,0x24,0x34,0x00,0xbf,0xaf,0x2c,0x00,0xb7,0xaf,0x24,0x00,0xb5,0xaf,
-0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,
-0x10,0x00,0xb0,0xaf,0x8c,0x65,0xc2,0x8c,0xff,0x00,0x8d,0x30,0xff,0x00,0x03,0x24,
-0xff,0xff,0x42,0x38,0x21,0xf0,0x00,0x00,0xff,0xff,0x04,0x34,0x0a,0xf0,0x62,0x00,
-0x8c,0x65,0xc4,0xac,0xb0,0x00,0xa0,0x11,0x08,0x00,0x16,0x24,0x02,0x80,0x02,0x3c,
-0xb8,0x90,0x45,0x24,0x90,0x44,0xc4,0x24,0xff,0x4f,0x00,0x08,0x21,0x88,0x00,0x00,
-0x01,0x00,0x31,0x26,0x00,0x00,0x82,0xa0,0x1d,0x00,0x22,0x2a,0x0b,0x00,0x40,0x10,
-0x01,0x00,0x84,0x24,0x21,0x10,0x25,0x02,0x00,0x00,0x42,0x90,0x00,0x00,0x00,0x00,
-0xf7,0xff,0x40,0x10,0xfd,0xff,0x43,0x24,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,
-0x00,0x00,0x83,0xa0,0xf7,0xff,0x40,0x14,0x01,0x00,0x84,0x24,0x02,0x80,0x02,0x3c,
-0x68,0x15,0x4a,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x50,0x8e,0x6c,0x24,
-0xd8,0x8d,0x4b,0x24,0x21,0x88,0x00,0x00,0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00,
-0x21,0x40,0x2a,0x01,0x21,0x38,0x2c,0x01,0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90,
-0x00,0x00,0x45,0x90,0x21,0x18,0x06,0x01,0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28,
-0xc5,0x43,0x64,0xa0,0xf8,0xff,0x40,0x14,0x34,0x43,0x65,0xa0,0x21,0x10,0x2b,0x02,
-0x1d,0x00,0x44,0x90,0x00,0x00,0x45,0x90,0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26,
-0x1d,0x00,0x22,0x2a,0x73,0x44,0x64,0xa0,0x56,0x44,0x65,0xa0,0xeb,0xff,0x40,0x14,
-0x05,0x00,0x29,0x25,0xa6,0x00,0xa0,0x11,0x02,0x80,0x02,0x3c,0x68,0x15,0x48,0x24,
-0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x4c,0x91,0x69,0x24,0xd8,0x90,0x47,0x24,
-0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00,0x21,0x10,0x69,0x00,0x21,0x20,0x67,0x00,
-0x00,0x00,0x46,0x8c,0x00,0x00,0x85,0x8c,0x01,0x00,0x31,0x26,0x21,0x18,0x68,0x00,
-0x04,0x00,0x22,0x2a,0xec,0x44,0x65,0xac,0xf6,0xff,0x40,0x14,0x60,0x45,0x66,0xac,
-0x02,0x80,0x02,0x3c,0x68,0x15,0x49,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,
-0x4c,0x91,0x68,0x24,0xd8,0x90,0x47,0x24,0x04,0x00,0x11,0x24,0x80,0x20,0x11,0x00,
-0x21,0x10,0x88,0x00,0x21,0x30,0x87,0x00,0x00,0x00,0x45,0x8c,0x00,0x00,0xc3,0x8c,
-0x01,0x00,0x31,0x26,0x21,0x20,0x89,0x00,0x82,0x28,0x05,0x00,0x82,0x18,0x03,0x00,
-0x1d,0x00,0x22,0x2a,0xec,0x44,0x83,0xac,0xf4,0xff,0x40,0x14,0x60,0x45,0x85,0xac,
-0x02,0x80,0x02,0x3c,0x68,0x15,0x55,0x24,0x21,0x88,0x00,0x00,0x21,0xb8,0xa0,0x02,
-0x21,0xa0,0x00,0x00,0x5a,0x50,0x00,0x08,0x21,0x90,0xa0,0x02,0x01,0x00,0x31,0x26,
-0x20,0x00,0x22,0x2a,0x94,0x00,0x52,0x26,0x38,0x00,0x40,0x10,0x94,0x00,0x94,0x26,
-0x78,0x51,0x44,0x8e,0x01,0x00,0x03,0x24,0x02,0x13,0x04,0x00,0x01,0x00,0x53,0x30,
-0xf6,0xff,0x63,0x16,0x07,0x00,0x82,0x30,0x25,0xb0,0x03,0x3c,0x80,0x10,0x02,0x00,
-0x21,0x10,0x43,0x00,0x84,0x01,0x45,0x8c,0x70,0x51,0x43,0x8e,0x21,0x20,0x20,0x02,
-0x24,0x28,0xa3,0x00,0xce,0x0d,0x00,0x0c,0x74,0x51,0x45,0xae,0x7a,0x51,0x44,0x92,
-0x5c,0x0d,0x00,0x0c,0xff,0x00,0x25,0x32,0x7a,0x51,0x50,0x92,0x00,0x00,0x00,0x00,
-0x21,0x20,0x00,0x02,0x63,0x0d,0x00,0x0c,0x80,0x80,0x10,0x00,0x21,0x80,0x17,0x02,
-0x48,0x51,0x40,0xae,0x4c,0x51,0x40,0xae,0x50,0x51,0x40,0xae,0x54,0x51,0x40,0xae,
-0x58,0x51,0x40,0xae,0x5c,0x51,0x40,0xae,0x60,0x51,0x40,0xae,0x64,0x51,0x40,0xae,
-0xec,0x44,0x04,0x8e,0x60,0x45,0x03,0x8e,0x26,0x10,0x53,0x00,0x21,0x30,0x00,0x00,
-0x21,0x18,0x64,0x00,0x42,0x18,0x03,0x00,0x04,0x00,0x04,0x24,0x0a,0xb0,0x82,0x00,
-0x44,0x51,0x43,0xae,0x21,0x20,0x95,0x02,0x21,0x10,0x86,0x00,0x01,0x00,0xc6,0x24,
-0x1d,0x00,0xc3,0x28,0xb6,0x51,0x40,0xa0,0x7c,0x51,0x40,0xa0,0xfa,0xff,0x60,0x14,
-0x99,0x51,0x40,0xa0,0x01,0x00,0x31,0x26,0x20,0x00,0x22,0x2a,0xd4,0x51,0x80,0xac,
-0x94,0x00,0x52,0x26,0xca,0xff,0x40,0x14,0x94,0x00,0x94,0x26,0x25,0xb0,0x02,0x3c,
-0x80,0x01,0x42,0x34,0x00,0x00,0x56,0xa0,0x03,0x00,0xc0,0x17,0x02,0x80,0x03,0x3c,
-0x68,0x15,0x62,0x24,0x8c,0x65,0x40,0xac,0x34,0x00,0xbf,0x8f,0x30,0x00,0xbe,0x8f,
-0x2c,0x00,0xb7,0x8f,0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,
-0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
-0x08,0x00,0xe0,0x03,0x38,0x00,0xbd,0x27,0x02,0x80,0x02,0x3c,0xb8,0x90,0x45,0x24,
-0x90,0x44,0xc4,0x24,0x21,0x88,0x00,0x00,0x21,0x10,0x25,0x02,0x00,0x00,0x43,0x90,
-0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x00,0x00,0x83,0xa0,0xfa,0xff,0x40,0x14,
-0x01,0x00,0x84,0x24,0x02,0x80,0x02,0x3c,0x68,0x15,0x4a,0x24,0x02,0x80,0x03,0x3c,
-0x02,0x80,0x02,0x3c,0x74,0x8f,0x6c,0x24,0x14,0x8e,0x4b,0x24,0x21,0x88,0x00,0x00,
-0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00,0x21,0x40,0x2a,0x01,0x21,0x38,0x2c,0x01,
-0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90,0x00,0x00,0x45,0x90,0x21,0x18,0x06,0x01,
-0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28,0xc5,0x43,0x64,0xa0,0xf8,0xff,0x40,0x14,
-0x34,0x43,0x65,0xa0,0x21,0x10,0x2b,0x02,0x1d,0x00,0x44,0x90,0x00,0x00,0x45,0x90,
-0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26,0x1d,0x00,0x22,0x2a,0x73,0x44,0x64,0xa0,
-0x56,0x44,0x65,0xa0,0xeb,0xff,0x40,0x14,0x05,0x00,0x29,0x25,0x02,0x80,0x02,0x3c,
-0x68,0x15,0x49,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x4c,0x91,0x68,0x24,
-0xd8,0x90,0x47,0x24,0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00,0x21,0x10,0x68,0x00,
-0x21,0x20,0x67,0x00,0x00,0x00,0x46,0x8c,0x00,0x00,0x85,0x8c,0x01,0x00,0x31,0x26,
-0x21,0x18,0x69,0x00,0x1d,0x00,0x22,0x2a,0xec,0x44,0x65,0xac,0xf6,0xff,0x40,0x14,
-0x60,0x45,0x66,0xac,0x4f,0x50,0x00,0x08,0x02,0x80,0x02,0x3c,0xd8,0xff,0xbd,0x27,
-0xff,0xff,0x84,0x30,0x18,0x00,0xb2,0xaf,0xf0,0x01,0x92,0x30,0x02,0x91,0x12,0x00,
-0x14,0x00,0xb1,0xaf,0xc0,0x88,0x12,0x00,0x21,0x88,0x32,0x02,0x80,0x88,0x11,0x00,
-0x21,0x88,0x32,0x02,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0x80,0x88,0x11,0x00,
-0x21,0x88,0x22,0x02,0x20,0x00,0xbf,0xaf,0x1c,0x00,0xb3,0xaf,0x10,0x00,0xb0,0xaf,
-0x78,0x51,0x30,0x8e,0x00,0x02,0x82,0x30,0xff,0xfe,0x03,0x24,0x2b,0x10,0x02,0x00,
-0x00,0x10,0x10,0x36,0x24,0x80,0x03,0x02,0x00,0x12,0x02,0x00,0x25,0x80,0x02,0x02,
-0x70,0x51,0x25,0xae,0x78,0x51,0x30,0xae,0xa0,0x0e,0x00,0x0c,0x21,0x98,0xa0,0x00,
-0xf8,0xff,0x03,0x24,0x24,0x80,0x03,0x02,0x07,0x00,0x42,0x30,0x25,0x80,0x02,0x02,
-0x07,0x00,0x03,0x32,0x25,0xb0,0x02,0x3c,0x80,0x18,0x03,0x00,0x78,0x51,0x30,0xae,
-0x21,0x18,0x62,0x00,0x84,0x01,0x62,0x8c,0x21,0x20,0x40,0x02,0x24,0x10,0x53,0x00,
-0xce,0x0d,0x00,0x0c,0x74,0x51,0x22,0xae,0x7a,0x51,0x24,0x92,0x21,0x28,0x40,0x02,
-0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x5c,0x0d,0x00,0x08,0x28,0x00,0xbd,0x27,0xee,0x4e,0x00,0x08,
-0xff,0x00,0x84,0x30,0x02,0x80,0x02,0x3c,0x68,0x15,0x43,0x24,0x1f,0x00,0x04,0x24,
-0x78,0x51,0x62,0x8c,0xff,0xff,0x84,0x24,0x00,0x10,0x42,0x34,0x78,0x51,0x62,0xac,
-0xfb,0xff,0x81,0x04,0x94,0x00,0x63,0x24,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x78,0xff,0xbd,0x27,0x60,0x00,0xb0,0xaf,0x25,0xb0,0x10,0x3c,0x70,0x00,0xb4,0xaf,
-0xc4,0x02,0x14,0x36,0x00,0x00,0x80,0xae,0x74,0x00,0xb5,0xaf,0x6c,0x00,0xb3,0xaf,
-0x68,0x00,0xb2,0xaf,0x64,0x00,0xb1,0xaf,0x84,0x00,0xbf,0xaf,0x80,0x00,0xbe,0xaf,
-0x7c,0x00,0xb7,0xaf,0x78,0x00,0xb6,0xaf,0x04,0x00,0x02,0x36,0x04,0x0c,0x13,0x36,
-0x00,0x00,0x43,0x8c,0x00,0x00,0x62,0x8e,0x0f,0x00,0x11,0x3c,0x24,0x18,0x71,0x00,
-0x08,0x0c,0x12,0x36,0x4c,0x00,0xa2,0xaf,0x02,0xac,0x03,0x00,0x00,0x00,0x43,0x8e,
-0x00,0x00,0x00,0x00,0x50,0x00,0xa3,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x21,0x20,0x00,0x00,0xdd,0x44,0x00,0x0c,
-0xff,0xff,0x25,0x36,0x10,0x00,0xa2,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x00,0x60,0x81,0x40,0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0x7a,0x42,0x00,0x0c,
-0x01,0x00,0x04,0x24,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
-0x00,0x60,0x81,0x40,0x21,0x20,0x00,0x00,0xdd,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,
-0x14,0x00,0xa2,0xaf,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0x7a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,
-0xe0,0x0e,0x05,0x36,0x00,0x00,0xad,0x8c,0xdc,0x0e,0x06,0x36,0x70,0x0e,0x07,0x36,
-0x18,0x00,0xad,0xaf,0x00,0x00,0xc2,0x8c,0x74,0x0e,0x08,0x36,0x78,0x0e,0x09,0x36,
-0x1c,0x00,0xa2,0xaf,0x00,0x00,0xe3,0x8c,0x7c,0x0e,0x0a,0x36,0x80,0x0e,0x0b,0x36,
-0x20,0x00,0xa3,0xaf,0x00,0x00,0x0d,0x8d,0x84,0x0e,0x0c,0x36,0x88,0x0e,0x17,0x36,
-0x24,0x00,0xad,0xaf,0x00,0x00,0x22,0x8d,0x8c,0x0e,0x0e,0x36,0xd0,0x0e,0x18,0x36,
-0x28,0x00,0xa2,0xaf,0x00,0x00,0x43,0x8d,0xd8,0x0e,0x11,0x36,0xd4,0x0e,0x10,0x36,
-0x2c,0x00,0xa3,0xaf,0x00,0x00,0x6d,0x8d,0xed,0x3f,0x04,0x3c,0xfb,0x92,0x84,0x34,
-0x30,0x00,0xad,0xaf,0x00,0x00,0x82,0x8d,0x25,0xb0,0x1e,0x3c,0x21,0xb0,0x00,0x00,
-0x34,0x00,0xa2,0xaf,0x00,0x00,0xe3,0x8e,0xff,0x03,0x0f,0x3c,0x38,0x00,0xa3,0xaf,
-0x00,0x00,0xcd,0x8d,0x00,0x00,0x00,0x00,0x3c,0x00,0xad,0xaf,0x00,0x00,0x02,0x8f,
-0x00,0x00,0x00,0x00,0x40,0x00,0xa2,0xaf,0x00,0x00,0x03,0x8e,0x00,0x00,0x00,0x00,
-0x44,0x00,0xa3,0xaf,0x00,0x00,0x2d,0x8e,0x00,0x00,0x00,0x00,0x48,0x00,0xad,0xaf,
-0x00,0x00,0xa4,0xac,0x00,0x00,0xc4,0xac,0x00,0x00,0xe4,0xac,0x00,0x00,0x04,0xad,
-0x00,0x00,0x24,0xad,0x00,0x00,0x44,0xad,0x00,0x00,0x64,0xad,0x00,0x00,0x84,0xad,
-0x00,0x00,0xe4,0xae,0x00,0x00,0xc4,0xad,0x00,0x00,0x04,0xaf,0x00,0x00,0x04,0xae,
-0x00,0x00,0x24,0xae,0xd0,0x51,0x00,0x08,0x00,0x00,0x00,0x00,0x7a,0x00,0xa2,0x12,
-0x00,0x10,0x03,0x3c,0xac,0x0e,0xc2,0x37,0x94,0x0e,0xc3,0x37,0x25,0xb0,0x09,0x3c,
-0x00,0x00,0x4a,0x8c,0xbc,0x0e,0x29,0x35,0x00,0x00,0x64,0x8c,0xb4,0x0e,0xc2,0x37,
-0x9c,0x0e,0xc3,0x37,0x00,0x00,0x45,0x8c,0x00,0x00,0x66,0x8c,0x00,0x00,0x27,0x8d,
-0x24,0x20,0x8f,0x00,0x00,0xd8,0x02,0x3c,0x24,0x10,0x42,0x01,0x24,0x28,0xaf,0x00,
-0x24,0x30,0xcf,0x00,0x24,0x38,0xef,0x00,0x02,0x24,0x04,0x00,0x20,0x01,0x03,0x24,
-0x01,0x00,0x42,0x2c,0x02,0x2c,0x05,0x00,0x02,0x34,0x06,0x00,0xf2,0x00,0x83,0x10,
-0x02,0x3c,0x07,0x00,0xf0,0x00,0xa3,0x10,0x20,0x00,0x03,0x24,0xee,0x00,0xc3,0x10,
-0x00,0x00,0x00,0x00,0xec,0x00,0xe3,0x10,0x01,0x00,0x08,0x24,0x80,0x00,0x03,0x24,
-0x08,0x00,0x83,0x10,0x21,0x20,0x00,0x00,0x06,0x00,0xa3,0x10,0x21,0x20,0x00,0x00,
-0xe0,0x03,0x03,0x24,0x03,0x00,0xc3,0x10,0x00,0x00,0x00,0x00,0xe5,0x00,0xe3,0x10,
-0x01,0x00,0x04,0x24,0x06,0x00,0x40,0x10,0x09,0x00,0x02,0x24,0x04,0x00,0x00,0x11,
-0x00,0x00,0x00,0x00,0x6d,0x01,0x80,0x14,0x25,0xb0,0x12,0x3c,0x09,0x00,0x02,0x24,
-0xde,0x00,0xc2,0x12,0x25,0xb0,0x04,0x3c,0x01,0x00,0xd6,0x26,0x0a,0x00,0xc2,0x2e,
-0x1d,0x01,0x40,0x10,0x00,0x00,0x00,0x00,0xc8,0xff,0xa0,0x16,0x01,0x00,0x02,0x24,
-0xa0,0x00,0x03,0x3c,0x25,0xb0,0x09,0x3c,0x30,0x54,0x62,0x34,0x04,0x0c,0x29,0x35,
-0x00,0x00,0x22,0xad,0x25,0xb0,0x0d,0x3c,0x08,0x00,0x02,0x3c,0xe4,0x00,0x42,0x34,
-0x08,0x0c,0xad,0x35,0x25,0xb0,0x09,0x3c,0x00,0x00,0xa2,0xad,0x28,0x0e,0x29,0x35,
-0x80,0x80,0x02,0x3c,0x00,0x00,0x22,0xad,0x14,0x02,0x04,0x3c,0x16,0x68,0x02,0x3c,
-0x48,0x01,0x83,0x34,0x40,0x0e,0xc5,0x37,0x44,0x0e,0xc6,0x37,0xa2,0x04,0x42,0x34,
-0x25,0xb0,0x0d,0x3c,0x00,0x00,0xa3,0xac,0x4c,0x0e,0xad,0x35,0x00,0x00,0xc2,0xac,
-0xd1,0x28,0x02,0x24,0x00,0x00,0xa2,0xad,0x14,0x02,0x03,0x3c,0x16,0x28,0x02,0x3c,
-0x4d,0x01,0x63,0x34,0x60,0x0e,0xc7,0x37,0x64,0x0e,0xc8,0x37,0xba,0x08,0x42,0x34,
-0x00,0x00,0xe3,0xac,0x25,0xb0,0x06,0x3c,0x00,0x00,0x02,0xad,0x00,0xfb,0x0d,0x3c,
-0x25,0xb0,0x09,0x3c,0x00,0xf8,0x02,0x3c,0xd1,0x28,0x07,0x24,0x6c,0x0e,0xc6,0x34,
-0x48,0x0e,0x29,0x35,0x01,0x00,0x42,0x34,0x01,0x00,0xad,0x35,0x00,0x00,0xc7,0xac,
-0x03,0x00,0x04,0x24,0x00,0x00,0x2d,0xad,0x00,0x00,0x22,0xad,0x84,0x0a,0x00,0x0c,
-0x58,0x00,0xaf,0xaf,0xa0,0x00,0x04,0x3c,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x06,0x3c,
-0x25,0xb0,0x07,0x3c,0xe4,0x00,0x02,0x24,0x33,0x54,0x84,0x34,0x04,0x0c,0x63,0x34,
-0x08,0x0c,0xc6,0x34,0x28,0x0e,0xe7,0x34,0x00,0x00,0x64,0xac,0x00,0x00,0xc2,0xac,
-0x00,0x00,0xe0,0xac,0x01,0x00,0x02,0x24,0x58,0x00,0xaf,0x8f,0x8a,0xff,0xa2,0x16,
-0xac,0x0e,0xc2,0x37,0x00,0x10,0x03,0x3c,0x1f,0xdc,0x79,0x34,0x1f,0x8c,0x7f,0x34,
-0x23,0x8c,0x6d,0x34,0xa0,0x00,0x03,0x3c,0x30,0x54,0x65,0x34,0x00,0x01,0x17,0x3c,
-0x25,0xb0,0x09,0x3c,0x25,0xb0,0x03,0x3c,0x00,0x01,0xe2,0x36,0x20,0x08,0x29,0x35,
-0x20,0x08,0x63,0x34,0x00,0x00,0x30,0x8d,0x00,0x00,0x62,0xac,0x25,0xb0,0x03,0x3c,
-0x28,0x08,0x63,0x34,0x00,0x00,0x62,0xac,0x25,0xb0,0x02,0x3c,0x04,0x0c,0x42,0x34,
-0x00,0x00,0x45,0xac,0x25,0xb0,0x03,0x3c,0x08,0x00,0x02,0x3c,0xe4,0x00,0x42,0x34,
-0x08,0x0c,0x63,0x34,0x00,0x00,0x62,0xac,0x25,0xb0,0x03,0x3c,0x00,0x7c,0xf3,0x36,
-0x00,0x48,0xf4,0x36,0x30,0x0e,0xc6,0x37,0x34,0x0e,0xc7,0x37,0x80,0x80,0x02,0x3c,
-0x28,0x0e,0x63,0x34,0x00,0x00,0x62,0xac,0x00,0x00,0xd3,0xac,0x00,0x00,0xf4,0xac,
-0x14,0x02,0x06,0x3c,0x16,0x68,0x07,0x3c,0x38,0x0e,0xc8,0x37,0x40,0x0e,0xca,0x37,
-0x44,0x0e,0xcb,0x37,0x3c,0x0e,0xc9,0x37,0x02,0x01,0xc6,0x34,0xc7,0x04,0xe7,0x34,
-0x00,0x00,0x19,0xad,0x25,0xb0,0x03,0x3c,0x00,0x00,0x3f,0xad,0x00,0x00,0x46,0xad,
-0x25,0xb0,0x09,0x3c,0x00,0x00,0x67,0xad,0x25,0xb0,0x06,0x3c,0x00,0x10,0x07,0x3c,
-0x50,0x0e,0xcc,0x37,0x58,0x0e,0xce,0x37,0x5c,0x0e,0xd8,0x37,0xd1,0x28,0x02,0x24,
-0x23,0xdc,0xe7,0x34,0x4c,0x0e,0x29,0x35,0x6c,0x0e,0x63,0x34,0x54,0x0e,0xc6,0x34,
-0x00,0x00,0x22,0xad,0x00,0x00,0x62,0xac,0x14,0x02,0x09,0x3c,0x00,0x00,0x93,0xad,
-0x25,0xb0,0x02,0x3c,0x00,0x00,0xd4,0xac,0x00,0x00,0xc7,0xad,0x00,0x00,0x0d,0xaf,
-0x16,0x28,0x0d,0x3c,0x48,0x0e,0x42,0x34,0x00,0xf8,0x06,0x3c,0x02,0x01,0x29,0x35,
-0x07,0x0d,0xad,0x35,0x00,0xfb,0x03,0x3c,0x60,0x0e,0xd1,0x37,0x64,0x0e,0xd2,0x37,
-0x00,0x00,0x29,0xae,0x03,0x00,0x04,0x24,0x00,0x00,0x4d,0xae,0x00,0x00,0x43,0xac,
-0x00,0x00,0x46,0xac,0x84,0x0a,0x00,0x0c,0x58,0x00,0xaf,0xaf,0x00,0x02,0x02,0x3c,
-0x25,0xb0,0x07,0x3c,0x25,0xb0,0x09,0x3c,0xd1,0x28,0x42,0x34,0x4c,0x0e,0xe7,0x34,
-0x6c,0x0e,0x29,0x35,0x25,0xb0,0x0d,0x3c,0x00,0x00,0xe2,0xac,0x48,0x0e,0xad,0x35,
-0x00,0x00,0x22,0xad,0x00,0xf8,0x03,0x3c,0x00,0xfb,0x02,0x3c,0x00,0x00,0xa2,0xad,
-0x03,0x00,0x04,0x24,0x00,0x00,0xa3,0xad,0x84,0x0a,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x4c,0x00,0xa6,0x8f,0x25,0xb0,0x04,0x3c,0x04,0x0c,0x84,0x34,0x00,0x00,0x86,0xac,
-0x50,0x00,0xa9,0x8f,0x25,0xb0,0x07,0x3c,0x25,0xb0,0x0d,0x3c,0x00,0x01,0x10,0x32,
-0x08,0x0c,0xe7,0x34,0x28,0x0e,0xad,0x35,0x00,0x00,0xe9,0xac,0x2b,0x80,0x10,0x00,
-0x00,0x00,0xa0,0xad,0x58,0x00,0xaf,0x8f,0x17,0xff,0x00,0x16,0xac,0x0e,0xc2,0x37,
-0x25,0xb0,0x02,0x3c,0x25,0xb0,0x03,0x3c,0x20,0x08,0x42,0x34,0x28,0x08,0x63,0x34,
-0x00,0x00,0x57,0xac,0x25,0xb0,0x09,0x3c,0x00,0x00,0x77,0xac,0xac,0x0e,0xc2,0x37,
-0x94,0x0e,0xc3,0x37,0x00,0x00,0x4a,0x8c,0xbc,0x0e,0x29,0x35,0x00,0x00,0x64,0x8c,
-0xb4,0x0e,0xc2,0x37,0x9c,0x0e,0xc3,0x37,0x00,0x00,0x45,0x8c,0x00,0x00,0x66,0x8c,
-0x00,0x00,0x27,0x8d,0x24,0x20,0x8f,0x00,0x00,0xd8,0x02,0x3c,0x24,0x10,0x42,0x01,
-0x24,0x28,0xaf,0x00,0x24,0x30,0xcf,0x00,0x24,0x38,0xef,0x00,0x02,0x24,0x04,0x00,
-0x20,0x01,0x03,0x24,0x01,0x00,0x42,0x2c,0x02,0x2c,0x05,0x00,0x02,0x34,0x06,0x00,
-0x10,0xff,0x83,0x14,0x02,0x3c,0x07,0x00,0x80,0x00,0x03,0x24,0x16,0xff,0x83,0x14,
-0x21,0x40,0x00,0x00,0xc3,0x51,0x00,0x08,0x21,0x20,0x00,0x00,0xff,0xff,0x02,0x34,
-0xc4,0x02,0x84,0x34,0x00,0x00,0x82,0xac,0x94,0x0e,0xc3,0x37,0x9c,0x0e,0xc2,0x37,
-0xa4,0x0e,0xc4,0x37,0xac,0x0e,0xc7,0x37,0x00,0x00,0x66,0x8c,0x00,0x00,0x49,0x8c,
-0x00,0x00,0x8b,0x8c,0x00,0x00,0xe5,0x8c,0x02,0x80,0x07,0x3c,0x68,0x15,0xe7,0x24,
-0x0c,0x40,0xe3,0x8c,0x10,0x40,0xe4,0x8c,0xb4,0x0e,0xc2,0x37,0x00,0x00,0x47,0x8c,
-0x25,0xb0,0x0d,0x3c,0x00,0xfc,0x02,0x24,0x24,0x30,0xcf,0x00,0x24,0x28,0xaf,0x00,
-0xbc,0x0e,0xad,0x35,0x00,0x00,0xa8,0x8d,0x24,0x20,0x82,0x00,0x02,0x34,0x06,0x00,
-0x24,0x18,0x62,0x00,0x02,0x2c,0x05,0x00,0xc4,0x0e,0xca,0x37,0xcc,0x0e,0xcc,0x37,
-0xf0,0xff,0x02,0x3c,0xff,0x03,0x42,0x34,0x25,0x18,0x66,0x00,0x25,0x20,0x85,0x00,
-0x00,0x00,0x46,0x8d,0x24,0x48,0x2f,0x01,0x00,0x00,0x85,0x8d,0x24,0x38,0xef,0x00,
-0x24,0x20,0x82,0x00,0x24,0x18,0x62,0x00,0x82,0x49,0x09,0x00,0x82,0x39,0x07,0x00,
-0x0f,0xc0,0x02,0x3c,0xff,0xff,0x42,0x34,0x25,0x18,0x69,0x00,0x25,0x20,0x87,0x00,
-0x24,0x58,0x6f,0x01,0x24,0x40,0x0f,0x01,0x24,0x20,0x82,0x00,0x24,0x18,0x62,0x00,
-0x00,0x59,0x0b,0x00,0x00,0x41,0x08,0x00,0x24,0x30,0xcf,0x00,0x24,0x28,0xaf,0x00,
-0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,0x25,0x18,0x6b,0x00,0x25,0x20,0x88,0x00,
-0x02,0x34,0x06,0x00,0x02,0x2c,0x05,0x00,0x01,0x00,0xd6,0x26,0x0c,0x40,0x43,0xac,
-0x10,0x40,0x44,0xac,0x14,0x40,0x46,0xa4,0x16,0x40,0x45,0xa4,0x0a,0x00,0xc2,0x2e,
-0xe5,0xfe,0x40,0x14,0x00,0x00,0x00,0x00,0x18,0x00,0xad,0x8f,0x25,0xb0,0x02,0x3c,
-0xe0,0x0e,0x43,0x34,0x10,0x00,0xa6,0x8f,0x00,0x00,0x6d,0xac,0x1c,0x00,0xa3,0x8f,
-0xdc,0x0e,0x47,0x34,0x70,0x0e,0x48,0x34,0x00,0x00,0xe3,0xac,0x20,0x00,0xa7,0x8f,
-0x74,0x0e,0x49,0x34,0x78,0x0e,0x4a,0x34,0x00,0x00,0x07,0xad,0x24,0x00,0xad,0x8f,
-0x7c,0x0e,0x4b,0x34,0x80,0x0e,0x4c,0x34,0x00,0x00,0x2d,0xad,0x28,0x00,0xa3,0x8f,
-0x25,0xb0,0x0d,0x3c,0x84,0x0e,0xad,0x35,0x00,0x00,0x43,0xad,0x2c,0x00,0xa7,0x8f,
-0x88,0x0e,0x52,0x34,0x8c,0x0e,0x4e,0x34,0x00,0x00,0x67,0xad,0x30,0x00,0xa9,0x8f,
-0xd4,0x0e,0x51,0x34,0xd0,0x0e,0x42,0x34,0x00,0x00,0x89,0xad,0x34,0x00,0xa3,0x8f,
-0x0f,0x00,0x10,0x3c,0xff,0xff,0x05,0x36,0x00,0x00,0xa3,0xad,0x38,0x00,0xa7,0x8f,
-0x21,0x20,0x00,0x00,0x00,0x00,0x47,0xae,0x3c,0x00,0xa9,0x8f,0x00,0x00,0x00,0x00,
-0x00,0x00,0xc9,0xad,0x40,0x00,0xad,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x4d,0xac,
-0x44,0x00,0xa2,0x8f,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0xae,0x48,0x00,0xa3,0x8f,
-0x00,0x00,0x00,0x00,0x00,0x00,0x43,0xae,0xba,0x44,0x00,0x0c,0x00,0x00,0x00,0x00,
-0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0x7a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,
-0x14,0x00,0xa6,0x8f,0xff,0xff,0x05,0x36,0xba,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,
-0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0x84,0x00,0xbf,0x8f,0x80,0x00,0xbe,0x8f,
-0x7c,0x00,0xb7,0x8f,0x78,0x00,0xb6,0x8f,0x74,0x00,0xb5,0x8f,0x70,0x00,0xb4,0x8f,
-0x6c,0x00,0xb3,0x8f,0x68,0x00,0xb2,0x8f,0x64,0x00,0xb1,0x8f,0x60,0x00,0xb0,0x8f,
-0x21,0x20,0x00,0x00,0x7a,0x42,0x00,0x08,0x88,0x00,0xbd,0x27,0x94,0x0e,0x42,0x36,
-0x9c,0x0e,0x43,0x36,0xa4,0x0e,0x44,0x36,0xac,0x0e,0x45,0x36,0x02,0x80,0x0d,0x3c,
-0x00,0x00,0x47,0x8c,0x68,0x15,0xad,0x25,0x00,0x00,0x6a,0x8c,0x00,0x00,0x8c,0x8c,
-0x00,0x00,0xa3,0x8c,0x10,0x40,0xa4,0x8d,0xb4,0x0e,0x42,0x36,0x00,0x00,0x48,0x8c,
-0x0c,0x40,0xa5,0x8d,0x25,0xb0,0x02,0x3c,0x00,0xfc,0x13,0x24,0xbc,0x0e,0x42,0x34,
-0x24,0x18,0x6f,0x00,0x00,0x00,0x49,0x8c,0x02,0x1c,0x03,0x00,0x24,0x38,0xef,0x00,
-0x24,0x20,0x93,0x00,0xf0,0xff,0x06,0x3c,0x25,0x20,0x83,0x00,0xff,0x03,0xc6,0x34,
-0x02,0x3c,0x07,0x00,0xc4,0x0e,0x42,0x36,0x24,0x28,0xb3,0x00,0x24,0x40,0x0f,0x01,
-0xcc,0x0e,0x4b,0x36,0x25,0x28,0xa7,0x00,0x24,0x20,0x86,0x00,0x00,0x00,0x47,0x8c,
-0x24,0x50,0x4f,0x01,0x00,0x00,0x63,0x8d,0x82,0x41,0x08,0x00,0x0f,0xc0,0x02,0x3c,
-0xff,0xff,0x42,0x34,0x25,0x20,0x88,0x00,0x82,0x51,0x0a,0x00,0x24,0x28,0xa6,0x00,
-0x24,0x48,0x2f,0x01,0x24,0x88,0x82,0x00,0x25,0x28,0xaa,0x00,0x24,0x60,0x8f,0x01,
-0x00,0x49,0x09,0x00,0x25,0x88,0x29,0x02,0x24,0x28,0xa2,0x00,0x24,0x18,0x6f,0x00,
-0x00,0x61,0x0c,0x00,0x24,0x38,0xef,0x00,0x25,0x28,0xac,0x00,0x02,0x3c,0x07,0x00,
-0x02,0x1c,0x03,0x00,0x82,0x27,0x11,0x00,0x01,0x00,0x02,0x24,0x16,0x40,0xa3,0xa5,
-0x14,0x40,0xa7,0xa5,0x0c,0x40,0xa5,0xad,0x4a,0x00,0x82,0x10,0x10,0x40,0xb1,0xad,
-0x80,0x0c,0x4c,0x36,0x00,0x00,0x8a,0x8d,0x82,0x72,0x05,0x00,0xff,0x03,0xce,0x31,
-0x00,0x02,0xc3,0x31,0x25,0x10,0xd3,0x01,0x0b,0x70,0x43,0x00,0x82,0x85,0x0a,0x00,
-0x18,0x00,0xd0,0x01,0xff,0x03,0xaf,0x30,0x00,0x02,0xa3,0x30,0x25,0x10,0xf3,0x01,
-0x0b,0x78,0x43,0x00,0x02,0x75,0x11,0x00,0xff,0x03,0xce,0x31,0xc0,0xff,0x08,0x3c,
-0x25,0x18,0xd3,0x01,0x00,0x02,0xc2,0x31,0x00,0xfc,0x06,0x35,0x0b,0x70,0x62,0x00,
-0x24,0x38,0x46,0x01,0x94,0x0c,0x4a,0x36,0xff,0x0f,0x09,0x3c,0xff,0xff,0x29,0x35,
-0x88,0x0c,0x54,0x36,0x12,0x20,0x00,0x00,0x02,0x22,0x04,0x00,0x3f,0x00,0x82,0x30,
-0x18,0x00,0xf0,0x01,0x82,0x7a,0x11,0x00,0xff,0x03,0xef,0x31,0x00,0x14,0x02,0x00,
-0x25,0x38,0xe2,0x00,0x00,0x02,0xe3,0x31,0x25,0x10,0xf3,0x01,0x0b,0x78,0x43,0x00,
-0xc0,0x03,0x84,0x30,0x80,0x25,0x04,0x00,0x9c,0x0c,0x4b,0x36,0x12,0x28,0x00,0x00,
-0x02,0x2a,0x05,0x00,0xff,0x03,0xa2,0x30,0x25,0x10,0xe2,0x00,0x00,0x00,0x82,0xad,
-0x00,0x00,0x42,0x8d,0x00,0x00,0x00,0x00,0x24,0x10,0x49,0x00,0x25,0x10,0x44,0x00,
-0x00,0x00,0x42,0xad,0x00,0x00,0x8a,0x8e,0x00,0x00,0x00,0x00,0x24,0x40,0x48,0x01,
-0x82,0x85,0x08,0x00,0x18,0x00,0xd0,0x01,0x24,0x30,0x46,0x01,0x12,0x18,0x00,0x00,
-0x02,0x1a,0x03,0x00,0x3f,0x00,0x62,0x30,0x18,0x00,0xf0,0x01,0x00,0x14,0x02,0x00,
-0x25,0x30,0xc2,0x00,0xc0,0x03,0x63,0x30,0x80,0x1d,0x03,0x00,0x12,0x20,0x00,0x00,
-0x02,0x22,0x04,0x00,0xff,0x03,0x82,0x30,0x25,0x10,0xc2,0x00,0x00,0x00,0x82,0xae,
-0x00,0x00,0x62,0x8d,0x00,0x00,0x00,0x00,0x24,0x10,0x49,0x00,0x25,0x10,0x43,0x00,
-0x00,0x00,0x62,0xad,0x00,0x17,0x16,0x00,0x25,0xb0,0x03,0x3c,0xdd,0xdd,0x42,0x34,
-0xc4,0x02,0x63,0x34,0x00,0x00,0x62,0xac,0xec,0x52,0x00,0x08,0x00,0x00,0x00,0x00,
-0xe0,0xff,0xbd,0x27,0x44,0x00,0x02,0x24,0x10,0x00,0xa2,0xa3,0x49,0x00,0x03,0x24,
-0x47,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,0x8c,0x97,0xe7,0x24,0x11,0x00,0xa3,0xa3,
-0x12,0x00,0xa2,0xa3,0x10,0x27,0x03,0x24,0x01,0x00,0x02,0x24,0x01,0x80,0x06,0x3c,
-0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0xe8,0x51,0xc6,0x24,0x0c,0x00,0xe3,0xac,
-0x14,0x00,0xe2,0xa0,0x18,0x00,0xbf,0xaf,0xfb,0x0c,0x00,0x0c,0x13,0x00,0xa0,0xa3,
-0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,
-0xd0,0xff,0xbd,0x27,0x25,0xb0,0x02,0x3c,0x20,0x00,0xb4,0xaf,0x1c,0x00,0xb3,0xaf,
-0x03,0x0d,0x44,0x34,0x2c,0x00,0xbf,0xaf,0x28,0x00,0xb6,0xaf,0x24,0x00,0xb5,0xaf,
-0x18,0x00,0xb2,0xaf,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x83,0x90,
-0x42,0x00,0x45,0x34,0xff,0x00,0x73,0x30,0x70,0x00,0x74,0x32,0x29,0x00,0x80,0x16,
-0x8f,0x00,0x62,0x32,0xff,0xff,0x02,0x24,0x00,0x00,0xa2,0xa0,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x0f,0x00,0x11,0x3c,
-0x18,0x00,0x04,0x24,0xdd,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x21,0x80,0x40,0x00,
-0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xb3,0x0a,0x00,0x0c,
-0x64,0x00,0x04,0x24,0x00,0x80,0x06,0x36,0xff,0xff,0x25,0x36,0xba,0x44,0x00,0x0c,
-0x18,0x00,0x04,0x24,0x84,0x0a,0x00,0x0c,0x03,0x00,0x04,0x24,0x21,0x30,0xa0,0x02,
-0xff,0xff,0x25,0x36,0x5c,0x00,0x80,0x16,0x21,0x20,0x00,0x00,0x2c,0x00,0xbf,0x8f,
-0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,
-0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,0x25,0xb0,0x02,0x3c,
-0x42,0x00,0x42,0x34,0x30,0x00,0xbd,0x27,0x00,0x00,0x40,0xa0,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x00,0x00,0x82,0xa0,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x0f,0x00,0x11,0x3c,0x21,0x20,0x00,0x00,
-0xdd,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x21,0xa8,0x40,0x00,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,
-0x7a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x21,0x20,0x00,0x00,0xdd,0x44,0x00,0x0c,
-0xff,0xff,0x25,0x36,0x21,0xb0,0x40,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x00,0x60,0x81,0x40,0x64,0x00,0x04,0x24,0xb3,0x0a,0x00,0x0c,0x08,0x00,0x10,0x3c,
-0xff,0xff,0x10,0x36,0x7a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0x01,0x00,0x12,0x3c,
-0x24,0x30,0xb0,0x02,0x25,0x30,0xd2,0x00,0xff,0xff,0x25,0x36,0xba,0x44,0x00,0x0c,
-0x21,0x20,0x00,0x00,0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0x24,0x80,0xd0,0x02,
-0x7a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,0x25,0x30,0x12,0x02,0xff,0xff,0x25,0x36,
-0xba,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,
-0x7a,0x42,0x00,0x0c,0x21,0x20,0x00,0x00,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,
-0x01,0x00,0x21,0x38,0x00,0x60,0x81,0x40,0x0f,0x00,0x11,0x3c,0x18,0x00,0x04,0x24,
-0xdd,0x44,0x00,0x0c,0xff,0xff,0x25,0x36,0x21,0x80,0x40,0x00,0x00,0x60,0x01,0x40,
-0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,
-0x00,0x80,0x06,0x36,0xff,0xff,0x25,0x36,0xba,0x44,0x00,0x0c,0x18,0x00,0x04,0x24,
-0x84,0x0a,0x00,0x0c,0x03,0x00,0x04,0x24,0x21,0x30,0xa0,0x02,0xff,0xff,0x25,0x36,
-0xa6,0xff,0x80,0x12,0x21,0x20,0x00,0x00,0x25,0xb0,0x02,0x3c,0x03,0x0d,0x42,0x34,
-0x00,0x00,0x53,0xa0,0xba,0x44,0x00,0x0c,0x00,0x00,0x00,0x00,0xb3,0x0a,0x00,0x0c,
-0x64,0x00,0x04,0x24,0x7a,0x42,0x00,0x0c,0x01,0x00,0x04,0x24,0xff,0xff,0x25,0x36,
-0x21,0x30,0xc0,0x02,0xba,0x44,0x00,0x0c,0x21,0x20,0x00,0x00,0xb3,0x0a,0x00,0x0c,
-0x64,0x00,0x04,0x24,0x2c,0x00,0xbf,0x8f,0x28,0x00,0xb6,0x8f,0x24,0x00,0xb5,0x8f,
-0x20,0x00,0xb4,0x8f,0x1c,0x00,0xb3,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x21,0x20,0x00,0x00,0x7a,0x42,0x00,0x08,0x30,0x00,0xbd,0x27,
-0xd0,0xff,0xbd,0x27,0x28,0x00,0xb4,0xaf,0x02,0x80,0x14,0x3c,0x2c,0x00,0xbf,0xaf,
-0x24,0x00,0xb3,0xaf,0x20,0x00,0xb2,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,
-0x68,0x15,0x86,0x26,0x0c,0x40,0xc2,0x8c,0x00,0x00,0x00,0x00,0x82,0x17,0x02,0x00,
-0x01,0x00,0x42,0x30,0x07,0x00,0x40,0x14,0x68,0x15,0x85,0x26,0x08,0x40,0xc2,0x8c,
-0x01,0x00,0x03,0x24,0x42,0x17,0x02,0x00,0x03,0x00,0x42,0x30,0xf0,0x00,0x43,0x10,
-0x25,0xb0,0x02,0x3c,0x0c,0x40,0xa2,0x8c,0x01,0x00,0x03,0x24,0x82,0x17,0x02,0x00,
-0x01,0x00,0x44,0x30,0x0a,0x00,0x83,0x10,0x00,0x00,0x00,0x00,0x2c,0x00,0xbf,0x8f,
-0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,
-0x18,0x00,0xb0,0x8f,0x21,0x10,0x00,0x00,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,
-0x08,0x40,0xa2,0x8c,0x00,0x00,0x00,0x00,0x42,0x17,0x02,0x00,0x03,0x00,0x42,0x30,
-0xf2,0xff,0x44,0x14,0x25,0xb0,0x02,0x3c,0x0e,0x0c,0x44,0x34,0x00,0x00,0x83,0x90,
-0x00,0x01,0x02,0x24,0xff,0x00,0x63,0x30,0x01,0x00,0x63,0x24,0x8b,0x01,0x62,0x10,
-0x00,0x00,0x00,0x00,0x00,0x00,0x83,0xa0,0x68,0x15,0x84,0x26,0x10,0x40,0x82,0x8c,
-0x01,0x00,0x03,0x24,0x82,0x17,0x02,0x00,0xa4,0x01,0x43,0x10,0x0f,0x00,0x10,0x3c,
-0xc7,0x42,0x92,0x90,0x68,0x15,0x90,0x26,0xc6,0x42,0x03,0x92,0x25,0xb0,0x11,0x3c,
-0x62,0x0c,0x22,0x36,0x00,0x00,0x52,0xa0,0x17,0x01,0x60,0x10,0x01,0x00,0x02,0x24,
-0x03,0x0d,0x23,0x36,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x70,0x00,0x42,0x30,
-0x3e,0x01,0x40,0x14,0x63,0x0c,0x23,0x36,0xc4,0x42,0x02,0x96,0x00,0x00,0x00,0x00,
-0x23,0x20,0x52,0x00,0x2b,0x18,0x52,0x00,0x23,0x10,0x42,0x02,0x0a,0x10,0x83,0x00,
-0x03,0x00,0x42,0x2c,0x0b,0x01,0x40,0x10,0x00,0x00,0x00,0x00,0xc4,0x42,0x03,0x96,
-0x63,0x0c,0x22,0x36,0x00,0x00,0x43,0xa0,0x68,0x15,0x83,0x26,0xc3,0x42,0x62,0x90,
-0x08,0x40,0x66,0x8c,0xc2,0x42,0x72,0xa0,0x23,0x20,0x52,0x00,0x2b,0x38,0x42,0x02,
-0x23,0x50,0x42,0x02,0x02,0x2c,0x06,0x00,0x0b,0x50,0x87,0x00,0x3f,0x00,0xa5,0x30,
-0x3f,0x00,0xc4,0x30,0x24,0x00,0x02,0x24,0x20,0x00,0x03,0x24,0x23,0x10,0x44,0x00,
-0x2d,0x01,0x40,0x15,0x23,0x18,0x65,0x00,0x21,0x30,0x80,0x00,0x21,0x48,0xa0,0x00,
-0x02,0x80,0x0b,0x3c,0x68,0x15,0x83,0x26,0x80,0x10,0x06,0x00,0x21,0x10,0x43,0x00,
-0x0c,0x40,0x63,0x8c,0x18,0x40,0x44,0x8c,0xff,0x03,0x67,0x30,0x1b,0x01,0xe0,0x10,
-0x82,0x2d,0x04,0x00,0x00,0x02,0x62,0x30,0x04,0x00,0x40,0x10,0x18,0x00,0xe5,0x00,
-0x00,0xfc,0x02,0x24,0x25,0x38,0xe2,0x00,0x18,0x00,0xe5,0x00,0x82,0x22,0x03,0x00,
-0xff,0x03,0x84,0x30,0x00,0x02,0x83,0x30,0x12,0x10,0x00,0x00,0x02,0x12,0x02,0x00,
-0x03,0x00,0x60,0x10,0xff,0x03,0x48,0x30,0x00,0xfc,0x02,0x24,0x25,0x20,0x82,0x00,
-0x18,0x00,0x85,0x00,0x80,0x2d,0x05,0x00,0x25,0xb0,0x06,0x3c,0x80,0x0c,0xc7,0x34,
-0x94,0x0c,0xc6,0x34,0x12,0x20,0x00,0x00,0x02,0x22,0x04,0x00,0x3f,0x00,0x82,0x30,
-0x00,0x14,0x02,0x00,0x25,0x28,0xa2,0x00,0x25,0x28,0xa8,0x00,0x10,0x00,0xa5,0xaf,
-0x00,0x00,0xe5,0xac,0x00,0x00,0xc3,0x8c,0xff,0x0f,0x02,0x3c,0xc0,0x03,0x84,0x30,
-0xff,0xff,0x42,0x34,0x80,0x25,0x04,0x00,0x24,0x18,0x62,0x00,0x25,0x18,0x64,0x00,
-0x10,0x00,0xa3,0xaf,0x00,0x00,0xc3,0xac,0x68,0x15,0x83,0x26,0x08,0x40,0x62,0x8c,
-0x00,0x00,0x00,0x00,0x08,0x01,0x40,0x04,0xc0,0x28,0x09,0x00,0x21,0x28,0xa3,0x00,
-0xac,0x40,0xa3,0x90,0x25,0xb0,0x04,0x3c,0x22,0x0a,0x82,0x34,0x00,0x00,0x43,0xa0,
-0xad,0x40,0xa6,0x90,0x23,0x0a,0x82,0x34,0x24,0x0a,0x87,0x34,0x00,0x00,0x46,0xa0,
-0xae,0x40,0xa3,0x90,0x25,0x0a,0x86,0x34,0x26,0x0a,0x88,0x34,0x00,0x00,0xe3,0xa0,
-0xaf,0x40,0xa2,0x90,0x27,0x0a,0x87,0x34,0x28,0x0a,0x89,0x34,0x00,0x00,0xc2,0xa0,
-0xb0,0x40,0xa3,0x90,0x29,0x0a,0x84,0x34,0x00,0x00,0x03,0xa1,0xb1,0x40,0xa2,0x90,
-0x00,0x00,0x00,0x00,0x00,0x00,0xe2,0xa0,0xb2,0x40,0xa3,0x90,0x00,0x00,0x00,0x00,
-0x00,0x00,0x23,0xa1,0xb3,0x40,0xa2,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x82,0xa0,
-0x8e,0x7d,0x63,0x91,0x22,0x00,0x02,0x24,0x03,0x00,0x62,0x10,0x92,0x00,0x02,0x24,
-0x62,0xff,0x62,0x14,0x00,0x00,0x00,0x00,0x68,0x15,0x82,0x26,0x08,0x40,0x43,0x8c,
-0x01,0x00,0x44,0x39,0x24,0x00,0x02,0x24,0x02,0x1a,0x03,0x00,0x3f,0x00,0x63,0x30,
-0x01,0x00,0x84,0x30,0x04,0x01,0x80,0x10,0x23,0x28,0x43,0x00,0x42,0x18,0x0a,0x00,
-0x40,0x10,0x03,0x00,0x21,0x50,0x43,0x00,0x68,0x15,0x83,0x26,0xc3,0x42,0x62,0x90,
-0x00,0x00,0x00,0x00,0x2b,0x10,0x42,0x02,0x08,0x01,0x40,0x10,0x21,0x20,0x00,0x00,
-0x2b,0x10,0x45,0x01,0x07,0x00,0x40,0x10,0x24,0x00,0x04,0x24,0x08,0x40,0x62,0x8c,
-0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x3f,0x00,0x42,0x30,0x21,0x20,0x4a,0x00,
-0x68,0x15,0x83,0x26,0x80,0x10,0x04,0x00,0x10,0x40,0x66,0x8c,0x21,0x10,0x43,0x00,
-0x18,0x40,0x44,0x8c,0x82,0x3a,0x06,0x00,0xff,0x03,0xe7,0x30,0xf0,0x00,0xe0,0x10,
-0x82,0x2d,0x04,0x00,0x00,0x02,0xe2,0x30,0x04,0x00,0x40,0x10,0x18,0x00,0xe5,0x00,
-0x00,0xfc,0x02,0x24,0x25,0x38,0xe2,0x00,0x18,0x00,0xe5,0x00,0x02,0x25,0x06,0x00,
-0xff,0x03,0x84,0x30,0x00,0x02,0x83,0x30,0x12,0x10,0x00,0x00,0x02,0x12,0x02,0x00,
-0x03,0x00,0x60,0x10,0xff,0x03,0x48,0x30,0x00,0xfc,0x02,0x24,0x25,0x20,0x82,0x00,
-0x18,0x00,0x85,0x00,0x80,0x2d,0x05,0x00,0x25,0xb0,0x06,0x3c,0x88,0x0c,0xc7,0x34,
-0x9c,0x0c,0xc6,0x34,0x12,0x20,0x00,0x00,0x02,0x22,0x04,0x00,0x3f,0x00,0x82,0x30,
-0x00,0x14,0x02,0x00,0x25,0x28,0xa2,0x00,0x25,0x28,0xa8,0x00,0x10,0x00,0xa5,0xaf,
-0x00,0x00,0xe5,0xac,0x00,0x00,0xc3,0x8c,0xff,0x0f,0x02,0x3c,0xc0,0x03,0x84,0x30,
-0xff,0xff,0x42,0x34,0x80,0x25,0x04,0x00,0x24,0x18,0x62,0x00,0x25,0x18,0x64,0x00,
-0x10,0x00,0xa3,0xaf,0x00,0x00,0xc3,0xac,0x95,0x54,0x00,0x08,0x00,0x00,0x00,0x00,
-0x80,0x0c,0x42,0x34,0x00,0x00,0x43,0x8c,0xc0,0xff,0x02,0x3c,0x21,0x88,0x00,0x00,
-0x24,0x28,0x62,0x00,0xc0,0xff,0x04,0x3c,0x8a,0x55,0x00,0x08,0x18,0x40,0xc3,0x24,
-0x01,0x00,0x31,0x26,0x25,0x00,0x22,0x2e,0x0d,0x00,0x40,0x10,0x02,0x80,0x0b,0x3c,
-0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x44,0x00,0xf8,0xff,0x45,0x14,
-0x04,0x00,0x63,0x24,0x08,0x40,0xc2,0x8c,0xc0,0xff,0x03,0x24,0x3f,0x00,0x24,0x32,
-0x24,0x10,0x43,0x00,0x25,0x10,0x44,0x00,0x08,0x40,0xc2,0xac,0x02,0x80,0x0b,0x3c,
-0x8e,0x7d,0x63,0x91,0x22,0x00,0x02,0x24,0x3e,0x00,0x62,0x10,0x92,0x00,0x02,0x24,
-0x3d,0x00,0x62,0x10,0x25,0xb0,0x02,0x3c,0x25,0xb0,0x02,0x3c,0x24,0x0a,0x42,0x34,
-0x00,0x00,0x44,0x8c,0x3f,0x3f,0x03,0x3c,0x3f,0x3f,0x63,0x34,0x24,0x20,0x83,0x00,
-0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0x16,0x56,0x53,0x24,0x1e,0x57,0x72,0x24,
-0x21,0x88,0x00,0x00,0xb1,0x55,0x00,0x08,0x10,0x00,0xa4,0xaf,0xd4,0x45,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x47,0x00,0x40,0x10,0x68,0x15,0x85,0x26,0x01,0x00,0x31,0x26,
-0x21,0x00,0x22,0x2e,0x17,0x00,0x40,0x10,0x68,0x15,0x84,0x26,0xc0,0x80,0x11,0x00,
-0x10,0x00,0xa4,0x27,0x21,0x28,0x13,0x02,0xd4,0x45,0x00,0x0c,0x04,0x00,0x06,0x24,
-0x21,0x28,0x12,0x02,0x10,0x00,0xa4,0x27,0xf0,0xff,0x40,0x14,0x04,0x00,0x06,0x24,
-0x68,0x15,0x85,0x26,0x08,0x40,0xa3,0x8c,0xc0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,
-0x3f,0x00,0x24,0x32,0x24,0x18,0x62,0x00,0x00,0x24,0x04,0x00,0xff,0x7f,0x02,0x3c,
-0x25,0x18,0x64,0x00,0xff,0xff,0x42,0x34,0x24,0x18,0x62,0x00,0x08,0x40,0xa3,0xac,
-0x68,0x15,0x84,0x26,0x0c,0x40,0x83,0x8c,0x00,0x40,0x02,0x3c,0x25,0x18,0x62,0x00,
-0x25,0xb0,0x02,0x3c,0x0e,0x0c,0x42,0x34,0x0c,0x40,0x83,0xac,0x00,0x00,0x40,0xa0,
-0x8f,0x54,0x00,0x08,0x68,0x15,0x85,0x26,0xc6,0x42,0x02,0xa2,0xba,0x54,0x00,0x08,
-0xc4,0x42,0x12,0xa6,0xda,0x53,0x00,0x0c,0x00,0x00,0x00,0x00,0xc9,0x54,0x00,0x08,
-0xc4,0x42,0x12,0xa6,0x25,0xb0,0x02,0x3c,0x88,0x0c,0x42,0x34,0x00,0x00,0x44,0x8c,
-0x02,0x80,0x03,0x3c,0x68,0x15,0x66,0x24,0xc0,0xff,0x02,0x3c,0x24,0x28,0x82,0x00,
-0x21,0x88,0x00,0x00,0xc0,0xff,0x04,0x3c,0xe6,0x55,0x00,0x08,0x18,0x40,0xc3,0x24,
-0x01,0x00,0x31,0x26,0x25,0x00,0x22,0x2e,0xb8,0xff,0x40,0x10,0x25,0xb0,0x02,0x3c,
-0x00,0x00,0x62,0x8c,0x00,0x00,0x00,0x00,0x24,0x10,0x44,0x00,0xf8,0xff,0x45,0x14,
-0x04,0x00,0x63,0x24,0x08,0x40,0xc2,0x8c,0x3f,0x00,0x23,0x32,0xff,0xc0,0x04,0x24,
-0x24,0x10,0x44,0x00,0x00,0x1a,0x03,0x00,0x25,0x10,0x43,0x00,0x9c,0x55,0x00,0x08,
-0x08,0x40,0xc2,0xac,0x08,0x40,0xa3,0x8c,0xc0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,
-0x3f,0x00,0x24,0x32,0x24,0x18,0x62,0x00,0x00,0x24,0x04,0x00,0x25,0x18,0x64,0x00,
-0x00,0x80,0x02,0x3c,0xc5,0x55,0x00,0x08,0x25,0x18,0x62,0x00,0xcc,0xff,0x02,0x24,
-0x00,0x00,0x62,0xa0,0xcd,0x54,0x00,0x08,0x68,0x15,0x83,0x26,0x25,0xb0,0x02,0x3c,
-0x94,0x0c,0x43,0x34,0x80,0x0c,0x42,0x34,0x00,0x00,0x44,0xac,0x00,0x00,0x60,0xac,
-0x0d,0x55,0x00,0x08,0x68,0x15,0x83,0x26,0x2f,0x00,0xe0,0x10,0x21,0x30,0x00,0x00,
-0x2b,0x10,0x42,0x01,0x21,0x20,0x8a,0x00,0x00,0x00,0x42,0x38,0x24,0x00,0x06,0x24,
-0x2b,0x18,0x43,0x01,0x0b,0x30,0x82,0x00,0xcd,0xfe,0x60,0x10,0x20,0x00,0x09,0x24,
-0x68,0x15,0x83,0x26,0x0a,0x40,0x62,0x94,0x02,0x80,0x0b,0x3c,0x3f,0x00,0x42,0x30,
-0xe0,0x54,0x00,0x08,0x21,0x48,0x4a,0x00,0x21,0x28,0xa3,0x00,0xb4,0x41,0xa3,0x90,
-0x25,0xb0,0x04,0x3c,0x22,0x0a,0x82,0x34,0x00,0x00,0x43,0xa0,0xb5,0x41,0xa6,0x90,
-0x23,0x0a,0x82,0x34,0x24,0x0a,0x87,0x34,0x00,0x00,0x46,0xa0,0xb6,0x41,0xa3,0x90,
-0x25,0x0a,0x86,0x34,0x26,0x0a,0x88,0x34,0x00,0x00,0xe3,0xa0,0xb7,0x41,0xa2,0x90,
-0x27,0x0a,0x87,0x34,0x28,0x0a,0x89,0x34,0x00,0x00,0xc2,0xa0,0xb8,0x41,0xa3,0x90,
-0x29,0x0a,0x84,0x34,0x00,0x00,0x03,0xa1,0xb9,0x41,0xa2,0x90,0x00,0x00,0x00,0x00,
-0x00,0x00,0xe2,0xa0,0xba,0x41,0xa3,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0xa1,
-0xbb,0x41,0xa2,0x90,0x2d,0x55,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xa0,
-0xad,0x54,0x00,0x08,0x68,0x15,0x84,0x26,0x23,0x10,0x8a,0x00,0x2b,0x18,0x44,0x01,
-0x2b,0x20,0x45,0x01,0x0b,0x30,0x43,0x00,0xa1,0xfe,0x80,0x14,0x23,0x48,0xaa,0x00,
-0xde,0x54,0x00,0x08,0x21,0x48,0x00,0x00,0xff,0xff,0x43,0x25,0x42,0x18,0x03,0x00,
-0x40,0x10,0x03,0x00,0x21,0x10,0x43,0x00,0x40,0x55,0x00,0x08,0x01,0x00,0x4a,0x24,
-0x25,0xb0,0x02,0x3c,0x9c,0x0c,0x43,0x34,0x88,0x0c,0x42,0x34,0x00,0x00,0x44,0xac,
-0x00,0x00,0x60,0xac,0x95,0x54,0x00,0x08,0x00,0x00,0x00,0x00,0x08,0x40,0x62,0x8c,
-0x00,0x00,0x00,0x00,0x02,0x12,0x02,0x00,0x3f,0x00,0x42,0x30,0x23,0x18,0x4a,0x00,
-0x2b,0x10,0x42,0x01,0x4e,0x55,0x00,0x08,0x0b,0x20,0x62,0x00,0xff,0xff,0x05,0x36,
-0x60,0x00,0x06,0x24,0xba,0x44,0x00,0x0c,0x24,0x00,0x04,0x24,0x84,0x0a,0x00,0x0c,
-0xe8,0x03,0x04,0x24,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x01,0x00,0x21,0x38,
-0x00,0x60,0x81,0x40,0x24,0x00,0x04,0x24,0xdd,0x44,0x00,0x0c,0xff,0xff,0x05,0x36,
-0x1f,0x00,0x52,0x30,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0xb3,0x0a,0x00,0x0c,0x64,0x00,0x04,0x24,0xb4,0x54,0x00,0x08,0x68,0x15,0x90,0x26,
-0x00,0xff,0x84,0x30,0x02,0x22,0x04,0x00,0x08,0x00,0x80,0x10,0x02,0x80,0x02,0x3c,
-0xff,0x00,0x02,0x24,0x04,0x00,0x82,0x10,0xcc,0xff,0x03,0x24,0x02,0x80,0x02,0x3c,
-0x08,0x00,0xe0,0x03,0x4e,0x58,0x43,0xa0,0x02,0x80,0x02,0x3c,0x08,0x00,0xe0,0x03,
-0x4e,0x58,0x44,0xa0,0x02,0x24,0x04,0x00,0xff,0x00,0x84,0x30,0xc0,0x10,0x04,0x00,
-0x21,0x10,0x44,0x00,0x80,0x10,0x02,0x00,0x21,0x10,0x44,0x00,0x02,0x80,0x03,0x3c,
-0x80,0x10,0x02,0x00,0x68,0x15,0x63,0x24,0x20,0x00,0x84,0x2c,0x09,0x00,0x80,0x10,
-0x21,0x10,0x43,0x00,0x68,0x51,0x43,0x8c,0x25,0xb0,0x02,0x3c,0xc4,0x02,0x42,0x34,
-0x02,0x19,0x03,0x00,0x7f,0x00,0x63,0x30,0x00,0x00,0x43,0xac,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x44,0x79,0x43,0x8c,0x25,0xb0,0x02,0x3c,
-0xc4,0x02,0x42,0x34,0x02,0x19,0x03,0x00,0x7f,0x00,0x63,0x30,0x00,0x00,0x43,0xac,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xff,0x00,0x85,0x30,0xd2,0xff,0xa3,0x24,
-0xfe,0xff,0xa2,0x24,0xda,0xff,0xa4,0x24,0x04,0x00,0x63,0x2c,0x08,0x00,0x84,0x2c,
-0x06,0x00,0x60,0x14,0xff,0x00,0x42,0x30,0xf0,0xff,0xa2,0x24,0xfc,0xff,0xa3,0x24,
-0x16,0x00,0x46,0x2c,0x03,0x00,0x80,0x10,0xff,0x00,0x62,0x30,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0xfa,0xff,0xa3,0x24,0xfc,0xff,0xc0,0x10,0x21,0x10,0xa0,0x00,
-0x08,0x00,0xe0,0x03,0xff,0x00,0x62,0x30,0x25,0xb0,0x04,0x3c,0x03,0x0d,0x85,0x34,
-0x00,0x00,0xa3,0x90,0x2d,0x0a,0x84,0x34,0xff,0x00,0x63,0x30,0x08,0x00,0x63,0x34,
-0x00,0x00,0xa3,0xa0,0x00,0x00,0xa2,0x90,0x00,0x00,0x00,0x00,0xf7,0x00,0x42,0x30,
-0x00,0x00,0xa2,0xa0,0x00,0x00,0x83,0x90,0x00,0x00,0x00,0x00,0x3f,0x00,0x63,0x30,
-0x00,0x00,0x83,0xa0,0x00,0x00,0x82,0x90,0x80,0xff,0x03,0x24,0x25,0x10,0x43,0x00,
-0x00,0x00,0x82,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x25,0xb0,0x02,0x3c,
-0xff,0x00,0x03,0x3c,0x82,0x01,0x49,0x34,0x81,0x01,0x48,0x34,0x24,0x10,0x83,0x00,
-0x02,0x3c,0x02,0x00,0x00,0xff,0x63,0x34,0x02,0x80,0x02,0x3c,0x68,0x15,0x45,0x24,
-0x02,0x32,0x04,0x00,0x01,0x00,0x02,0x24,0x24,0x20,0x83,0x00,0xc2,0x4c,0xa2,0xa0,
-0xb0,0x4c,0xa0,0xac,0xb4,0x4c,0xa0,0xac,0xb8,0x4c,0xa0,0xac,0x06,0x00,0x80,0x14,
-0xbc,0x4c,0xa0,0xac,0x00,0x00,0x02,0x91,0x00,0x00,0x23,0x91,0xc0,0x4c,0xa2,0xa0,
-0x08,0x00,0xe0,0x03,0xc1,0x4c,0xa3,0xa0,0xc1,0x4c,0xa7,0xa0,0x08,0x00,0xe0,0x03,
-0xc0,0x4c,0xa6,0xa0,0x02,0x80,0x03,0x3c,0x68,0x15,0x63,0x24,0xc1,0x4c,0x66,0x90,
-0xc0,0x4c,0x65,0x90,0x25,0xb0,0x02,0x3c,0x82,0x01,0x44,0x34,0x81,0x01,0x42,0x34,
-0x00,0x00,0x45,0xa0,0x00,0x00,0x86,0xa0,0x08,0x00,0xe0,0x03,0xc2,0x4c,0x60,0xa0,
-0x02,0x80,0x08,0x3c,0x68,0x15,0x04,0x25,0xc2,0x4c,0x82,0x90,0x00,0x00,0x00,0x00,
-0x15,0x00,0x40,0x10,0x21,0x18,0x00,0x00,0xb4,0x4c,0x82,0x8c,0xb0,0x4c,0x85,0x8c,
-0x25,0xb0,0x03,0x3c,0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00,0x82,0x01,0x67,0x34,
-0x0f,0x00,0x40,0x10,0x81,0x01,0x66,0x34,0xc1,0x4c,0x83,0x90,0xc0,0x4c,0x82,0x90,
-0xf0,0x00,0x63,0x30,0x1f,0x00,0x42,0x30,0x00,0x00,0xc2,0xa0,0x00,0x00,0xe3,0xa0,
-0x68,0x15,0x02,0x25,0x01,0x00,0x03,0x24,0xbc,0x4c,0x40,0xac,0xb0,0x4c,0x40,0xac,
-0xb4,0x4c,0x40,0xac,0xb8,0x4c,0x40,0xac,0x08,0x00,0xe0,0x03,0x21,0x10,0x60,0x00,
-0xb8,0x4c,0x82,0x8c,0x25,0xb0,0x03,0x3c,0x82,0x01,0x69,0x34,0x40,0x11,0x02,0x00,
-0x2b,0x10,0xa2,0x00,0x0e,0x00,0x40,0x14,0x81,0x01,0x66,0x34,0xbc,0x4c,0x82,0x8c,
-0x00,0x00,0x00,0x00,0x40,0x11,0x02,0x00,0x2b,0x10,0xa2,0x00,0x08,0x00,0x40,0x14,
-0x00,0x00,0x00,0x00,0xc1,0x4c,0x83,0x90,0xc0,0x4c,0x82,0x90,0x00,0x00,0x00,0x00,
-0x00,0x00,0xc2,0xa0,0x00,0x00,0x23,0xa1,0xf7,0x56,0x00,0x08,0x68,0x15,0x02,0x25,
-0xc1,0x4c,0x83,0x90,0xc0,0x4c,0x82,0x90,0xf0,0x00,0x63,0x30,0x7f,0x00,0x42,0x30,
-0x00,0x00,0xc2,0xa0,0x00,0x00,0x23,0xa1,0xf7,0x56,0x00,0x08,0x68,0x15,0x02,0x25,
-0x02,0x00,0x03,0x24,0x02,0x80,0x02,0x3c,0x08,0x00,0xe0,0x03,0x3d,0x58,0x43,0xa0,
-0xcc,0xff,0x03,0x24,0x02,0x80,0x02,0x3c,0x08,0x00,0xe0,0x03,0x3d,0x58,0x43,0xa0,
-0x25,0xb0,0x03,0x3c,0x33,0x02,0x65,0x34,0x00,0x11,0x04,0x00,0x00,0x00,0xa2,0xa0,
-0x30,0x02,0x63,0x34,0x00,0x00,0x65,0x8c,0x0f,0x00,0x02,0x3c,0xff,0xff,0x42,0x34,
-0x24,0x28,0xa2,0x00,0x01,0x00,0x03,0x24,0x04,0x18,0x83,0x00,0x02,0x00,0xa0,0x10,
-0x21,0x10,0x00,0x00,0xff,0xff,0x62,0x30,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0xe0,0xff,0xbd,0x27,0x14,0x00,0xb1,0xaf,0x25,0xb0,0x11,0x3c,0x18,0x00,0xb2,0xaf,
-0x4c,0x00,0x22,0x36,0x1c,0x00,0xbf,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x44,0x90,
-0x02,0x80,0x03,0x3c,0x02,0x00,0x02,0x24,0xff,0x00,0x84,0x30,0x07,0x00,0x82,0x10,
-0x68,0x15,0x72,0x24,0x1c,0x00,0xbf,0x8f,0x18,0x00,0xb2,0x8f,0x14,0x00,0xb1,0x8f,
-0x10,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe6,0x63,0x43,0x96,
-0x01,0x00,0x02,0x24,0xf7,0xff,0x62,0x14,0x21,0x20,0x00,0x00,0x22,0x57,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x24,0x22,0x57,0x00,0x0c,0x21,0x80,0x40,0x00,
-0x25,0x80,0x02,0x02,0x33,0x02,0x23,0x36,0x08,0x00,0x02,0x24,0xff,0xff,0x10,0x32,
-0x40,0x00,0x25,0x36,0x00,0x00,0x62,0xa0,0xea,0xff,0x00,0x16,0x00,0x00,0x00,0x00,
-0x00,0x00,0xa2,0x94,0xe4,0x63,0x43,0x96,0xff,0xdf,0x42,0x30,0x00,0x20,0x44,0x34,
-0x01,0x00,0x63,0x24,0xe4,0x63,0x43,0xa6,0x00,0x00,0xa2,0xa4,0x00,0x00,0xa4,0xa4,
-0x3f,0x57,0x00,0x08,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,0x25,0xb0,0x02,0x3c,
-0x18,0x03,0x42,0x34,0x80,0x5d,0x63,0x24,0x00,0x00,0x43,0xac,0x63,0x00,0x02,0x24,
-0xff,0xff,0x42,0x24,0xff,0xff,0x41,0x04,0xff,0xff,0x42,0x24,0x02,0x80,0x02,0x3c,
-0x88,0x7d,0x45,0x94,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x8b,0x7d,0x66,0x90,
-0x98,0x7d,0x47,0x90,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xa3,0x7d,0x69,0x90,
-0xa5,0x7d,0x4a,0x90,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xa8,0x7d,0x6b,0x90,
-0xaa,0x7d,0x4c,0x90,0x07,0x00,0x03,0x24,0x02,0x80,0x02,0x3c,0x25,0xb0,0x04,0x3c,
-0x95,0x7d,0x43,0xa0,0xb0,0x03,0x84,0x34,0x02,0x80,0x02,0x3c,0x02,0x80,0x18,0x3c,
-0x8a,0x7d,0x08,0x93,0x00,0x00,0x85,0xac,0x96,0x7d,0x40,0xa0,0x02,0x80,0x02,0x3c,
-0x00,0x00,0x86,0xac,0x02,0x80,0x0f,0x3c,0x97,0x7d,0x40,0xa0,0x02,0x80,0x02,0x3c,
-0x00,0x00,0x87,0xac,0x68,0x15,0xee,0x25,0xb8,0x7d,0x40,0xa0,0xfd,0xff,0x02,0x24,
-0xd5,0x4a,0xc2,0xa1,0x01,0x00,0x03,0x24,0x00,0x78,0x02,0x24,0xd4,0x4a,0xc3,0xa1,
-0xd8,0x4a,0xc2,0xa5,0xff,0x07,0x03,0x24,0x0f,0x00,0x0d,0x31,0x02,0x00,0x02,0x24,
-0xda,0x4a,0xc3,0xa5,0x00,0x00,0x88,0xac,0x00,0x00,0x89,0xac,0x00,0x00,0x8a,0xac,
-0x00,0x00,0x8b,0xac,0x00,0x00,0x8c,0xac,0x17,0x00,0xa2,0x11,0x02,0x80,0x02,0x3c,
-0x8a,0x7d,0x02,0x93,0x01,0x00,0x03,0x24,0x0f,0x00,0x42,0x30,0x05,0x00,0x43,0x10,
-0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0xca,0x7d,0x40,0xa4,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x00,0x80,0x02,0x3c,0x68,0x15,0xe4,0x25,0x02,0xbc,0x42,0x34,
-0x68,0x4b,0x82,0xac,0x15,0x15,0x03,0x3c,0x02,0x02,0x02,0x3c,0x07,0x07,0x63,0x34,
-0x64,0x4b,0x82,0xac,0x02,0x80,0x02,0x3c,0x60,0x4b,0x83,0xac,0xca,0x7d,0x40,0xa4,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x8f,0x7d,0x44,0x90,0x06,0x00,0x03,0x24,
-0x15,0x00,0x83,0x10,0x0b,0x00,0x02,0x24,0x0a,0x00,0x82,0x10,0x00,0xe0,0x02,0x3c,
-0x68,0x15,0xe4,0x25,0x00,0xb2,0x42,0x34,0x00,0x1c,0x03,0x3c,0x68,0x4b,0x82,0xac,
-0x00,0x1c,0x63,0x34,0x00,0x04,0x02,0x24,0x60,0x4b,0x83,0xac,0x9a,0x57,0x00,0x08,
-0x64,0x4b,0x82,0xac,0x00,0x80,0x02,0x3c,0x00,0xbc,0x42,0x34,0x15,0x15,0x03,0x3c,
-0x68,0x4b,0xc2,0xad,0x07,0x07,0x63,0x34,0x03,0x03,0x02,0x3c,0x60,0x4b,0xc3,0xad,
-0x9a,0x57,0x00,0x08,0x64,0x4b,0xc2,0xad,0x00,0xc0,0x02,0x3c,0x00,0xb2,0x42,0x34,
-0x1c,0x1c,0x03,0x3c,0x68,0x4b,0xc2,0xad,0x07,0x07,0x63,0x34,0x00,0x04,0x02,0x24,
-0x60,0x4b,0xc3,0xad,0x9a,0x57,0x00,0x08,0x64,0x4b,0xc2,0xad,0x25,0xb0,0x02,0x3c,
-0x4d,0x00,0x44,0x34,0xff,0x00,0x03,0x3c,0xec,0x02,0x42,0x34,0x00,0x00,0x43,0xac,
-0x00,0x00,0x80,0xa0,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x01,0x80,0x03,0x3c,
-0x25,0xb0,0x02,0x3c,0x64,0x5f,0x63,0x24,0x18,0x03,0x42,0x34,0x00,0x00,0x43,0xac,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x7f,0x00,0x02,0x3c,0xfd,0xbf,0x45,0x34,
-0x80,0x04,0x03,0x3c,0x25,0x28,0xa3,0x00,0x00,0x08,0x04,0x3c,0x02,0x80,0x02,0x3c,
-0x68,0x15,0x42,0x24,0x25,0x28,0xa4,0x00,0x41,0xb0,0x03,0x3c,0x00,0x00,0x65,0xac,
-0x04,0x4b,0x45,0xac,0xfc,0x4a,0x45,0xac,0x08,0x00,0x63,0x34,0x86,0x00,0x05,0x24,
-0x00,0x00,0x65,0xa4,0x08,0x4b,0x45,0xa4,0x00,0x4b,0x40,0xac,0x0a,0x4b,0x40,0xa4,
-0x0c,0x4b,0x45,0xa4,0x00,0x60,0x01,0x40,0x01,0x00,0x21,0x34,0x00,0x60,0x81,0x40,
-0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xf8,0x57,0x00,0x08,0x00,0x00,0x00,0x00,
-0x42,0xb0,0x02,0x3c,0xa0,0xff,0x03,0x24,0x01,0x00,0x42,0x34,0xe8,0xff,0xbd,0x27,
-0x21,0x20,0x00,0x00,0x01,0x00,0x05,0x24,0x00,0x01,0x06,0x24,0x00,0x00,0x43,0xa0,
-0x10,0x00,0xbf,0xaf,0xc4,0x0c,0x00,0x0c,0x00,0x00,0x00,0x00,0x10,0x00,0xbf,0x8f,
-0x03,0x00,0x04,0x24,0x01,0x00,0x05,0x24,0x40,0x1f,0x06,0x24,0xc4,0x0c,0x00,0x08,
-0x18,0x00,0xbd,0x27,0xe8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x14,0x00,0xbf,0xaf,
-0x21,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,0x68,0x15,0x42,0x24,
-0x48,0x01,0x03,0x24,0xe0,0x63,0x43,0xac,0xdc,0x63,0x43,0xac,0x21,0x80,0x40,0x00,
-0x1f,0x00,0x03,0x24,0xff,0xff,0x63,0x24,0xc4,0x4c,0x40,0xa4,0xc6,0x4c,0x40,0xa4,
-0xc8,0x4c,0x40,0xa4,0xca,0x4c,0x40,0xa4,0xcc,0x4c,0x40,0xa4,0xce,0x4c,0x40,0xa4,
-0xd0,0x4c,0x40,0xa4,0xd2,0x4c,0x40,0xa4,0xd4,0x4c,0x40,0xa4,0xf5,0xff,0x61,0x04,
-0x24,0x00,0x42,0x24,0x25,0xb0,0x02,0x3c,0x10,0x00,0x03,0x24,0xb0,0x03,0x42,0x34,
-0x02,0x80,0x04,0x3c,0x8c,0x58,0x84,0x24,0x00,0x00,0x43,0xac,0x21,0x28,0x00,0x00,
-0x97,0x45,0x00,0x0c,0x04,0x00,0x06,0x24,0xef,0x5b,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x71,0x5c,0x00,0x0c,0x8c,0x65,0x00,0xae,0xa7,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x4b,0x5e,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x03,0x3c,0x8e,0x7d,0x64,0x90,
-0x92,0x00,0x02,0x24,0x03,0x00,0x82,0x10,0x00,0x00,0x00,0x00,0xf7,0x5d,0x00,0x0c,
-0x00,0x00,0x00,0x00,0xdd,0x5d,0x00,0x0c,0x00,0x00,0x00,0x00,0x8b,0x5c,0x00,0x0c,
-0x00,0x00,0x00,0x00,0xe4,0x63,0x00,0xa6,0x67,0x5e,0x00,0x0c,0xe6,0x63,0x00,0xa6,
-0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x02,0x80,0x04,0x3c,0x02,0x80,0x05,0x3c,
-0xf8,0x7a,0x82,0x24,0x00,0x7b,0xa3,0x24,0x18,0x00,0xbd,0x27,0x04,0x00,0x42,0xac,
-0xf8,0x7a,0x82,0xac,0x00,0x7b,0xa3,0xac,0x08,0x00,0xe0,0x03,0x04,0x00,0x63,0xac,
-0xe8,0xff,0xbd,0x27,0x10,0x00,0xb0,0xaf,0x01,0x80,0x02,0x3c,0x25,0xb0,0x10,0x3c,
-0x18,0x03,0x03,0x36,0x38,0x61,0x42,0x24,0x00,0x00,0x62,0xac,0x14,0x00,0xbf,0xaf,
-0x60,0x57,0x00,0x0c,0x00,0x00,0x00,0x00,0xd5,0x58,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x01,0x00,0x03,0x24,0x02,0x80,0x02,0x3c,0xfd,0x5a,0x00,0x0c,0xdb,0x60,0x43,0xa0,
-0xd1,0x57,0x00,0x0c,0x00,0x00,0x00,0x00,0x32,0x41,0x00,0x0c,0x00,0x00,0x00,0x00,
-0x0b,0x58,0x00,0x0c,0x00,0x00,0x00,0x00,0x44,0x00,0x03,0x36,0x00,0x00,0x62,0x94,
-0x00,0x00,0x00,0x00,0x40,0x00,0x42,0x34,0x00,0x00,0x62,0xa4,0xd9,0x57,0x00,0x0c,
-0x00,0x00,0x00,0x00,0xfa,0x57,0x00,0x0c,0x00,0x00,0x00,0x00,0xc9,0x5a,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x8e,0x5a,0x00,0x0c,0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x3c,
-0xb4,0x24,0x84,0x24,0xe6,0x5a,0x00,0x0c,0x01,0x00,0x05,0x24,0x01,0x80,0x04,0x3c,
-0x08,0x1e,0x84,0x24,0xe6,0x5a,0x00,0x0c,0x02,0x00,0x05,0x24,0x81,0x4e,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x00,0x80,0x04,0x3c,0x54,0x34,0x84,0x24,0xe6,0x5a,0x00,0x0c,
-0x03,0x00,0x05,0x24,0x02,0x80,0x02,0x3c,0x98,0x7d,0x43,0x90,0x43,0x00,0x04,0x36,
-0x29,0x00,0x60,0x10,0xd8,0x00,0x10,0x36,0x07,0x00,0x02,0x24,0x2b,0x00,0x62,0x10,
-0x25,0xb0,0x04,0x3c,0x10,0x02,0x86,0x34,0x43,0x00,0x85,0x34,0x03,0x00,0x02,0x24,
-0x10,0x00,0x03,0x24,0x00,0x00,0xa2,0xa0,0xd8,0x00,0x84,0x34,0x00,0x00,0xc3,0xa0,
-0x00,0x00,0x82,0x90,0x80,0xff,0x03,0x24,0x42,0xb0,0x05,0x3c,0x25,0x10,0x43,0x00,
-0x00,0x00,0x82,0xa0,0x25,0xb0,0x04,0x3c,0x44,0x00,0x84,0x34,0x00,0x00,0x82,0x94,
-0x00,0x00,0x00,0x00,0xc0,0x00,0x42,0x34,0x00,0x00,0x82,0xa4,0x00,0x00,0xa3,0x90,
-0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x34,0x00,0x00,0xa3,0xa0,0xe0,0x57,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,0x08,0x00,0x84,0x24,0x21,0x28,0x00,0x00,
-0x21,0x30,0x00,0x00,0x31,0x1c,0x00,0x0c,0x21,0x38,0x00,0x00,0xf8,0x57,0x00,0x0c,
-0x00,0x00,0x00,0x00,0x14,0x00,0xbf,0x8f,0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,
-0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,0x00,0x00,0x80,0xa0,0x00,0x00,0x03,0x92,
-0x80,0xff,0x02,0x24,0x25,0x18,0x62,0x00,0x00,0x00,0x03,0xa2,0x25,0xb0,0x04,0x3c,
-0x44,0x00,0x84,0x34,0x00,0x00,0x82,0x94,0x42,0xb0,0x05,0x3c,0xc0,0x00,0x42,0x34,
-0x00,0x00,0x82,0xa4,0x00,0x00,0xa3,0x90,0x00,0x00,0x00,0x00,0x01,0x00,0x63,0x34,
-0x00,0x00,0xa3,0xa0,0xe0,0x57,0x00,0x0c,0x00,0x00,0x00,0x00,0x02,0x80,0x04,0x3c,
-0x08,0x00,0x84,0x24,0x21,0x28,0x00,0x00,0x21,0x30,0x00,0x00,0x31,0x1c,0x00,0x0c,
-0x21,0x38,0x00,0x00,0xf8,0x57,0x00,0x0c,0x00,0x00,0x00,0x00,0x14,0x00,0xbf,0x8f,
-0x10,0x00,0xb0,0x8f,0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x18,0x00,0xbd,0x27,
-0x21,0x20,0x00,0x00,0x20,0xb0,0x06,0x3c,0xff,0xff,0x05,0x34,0x21,0x18,0x86,0x00,
-0x04,0x00,0x84,0x24,0x2a,0x10,0xa4,0x00,0x00,0x00,0x60,0xac,0xfb,0xff,0x40,0x10,
-0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0xb8,0xff,0xbd,0x27,
-0x25,0xb0,0x04,0x3c,0x44,0x00,0xbf,0xaf,0x40,0x00,0xbe,0xaf,0x3c,0x00,0xb7,0xaf,
-0x38,0x00,0xb6,0xaf,0x34,0x00,0xb5,0xaf,0x30,0x00,0xb4,0xaf,0x2c,0x00,0xb3,0xaf,
-0x28,0x00,0xb2,0xaf,0x24,0x00,0xb1,0xaf,0x20,0x00,0xb0,0xaf,0x0a,0x00,0x83,0x34,
-0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x20,0x00,0x42,0x30,0x0c,0x00,0x40,0x10,
-0x4c,0x87,0x02,0x3c,0x00,0x00,0x62,0x90,0x00,0x00,0x00,0x00,0x10,0x00,0x42,0x30,
-0x66,0x01,0x40,0x10,0x4c,0x87,0x02,0x3c,0x54,0x00,0x83,0x34,0x50,0x00,0x82,0x34,
-0x00,0x00,0x45,0xac,0x00,0x00,0x65,0xa4,0xf9,0x58,0x00,0x08,0x02,0x80,0x03,0x3c,
-0x54,0x00,0x85,0x34,0x00,0xe0,0x42,0x34,0x50,0x00,0x84,0x34,0x12,0x01,0x03,0x24,
-0x00,0x00,0x82,0xac,0x00,0x00,0xa3,0xac,0x02,0x80,0x03,0x3c,0x68,0x15,0x62,0x24,
-0xd5,0x4a,0x43,0x90,0xda,0x4a,0x45,0x94,0x25,0xb0,0x1e,0x3c,0x1c,0x00,0xa3,0xa3,
-0x60,0x4b,0x43,0x8c,0x58,0x00,0xc6,0x37,0xff,0xff,0x04,0x24,0x10,0x00,0xa3,0xaf,
-0x64,0x4b,0x43,0x8c,0x5c,0x00,0xc7,0x37,0x60,0x00,0xc8,0x37,0x14,0x00,0xa3,0xaf,
-0x68,0x4b,0x42,0x8c,0x64,0x00,0xc9,0x37,0x8a,0x00,0xca,0x37,0x18,0x00,0xa2,0xaf,
-0x24,0x10,0x02,0x3c,0x21,0x28,0xa2,0x00,0x4c,0x81,0x02,0x3c,0x00,0xe0,0x42,0x34,
-0x00,0x00,0xc2,0xac,0x96,0x01,0x03,0x24,0x28,0x28,0x02,0x24,0x00,0x00,0xe3,0xac,
-0x89,0x00,0xcb,0x37,0x00,0x00,0x04,0xad,0x8c,0x00,0xcc,0x37,0x00,0x00,0x24,0xad,
-0x09,0x00,0x03,0x24,0x00,0x00,0x42,0xa5,0x10,0x10,0x02,0x24,0x00,0x00,0x63,0xa1,
-0x8e,0x00,0xcd,0x37,0x00,0x00,0x82,0xa5,0x0a,0x0a,0x03,0x24,0x13,0x00,0x02,0x24,
-0x90,0x00,0xce,0x37,0x00,0x00,0xa3,0xa5,0x00,0x00,0xc2,0xa1,0x25,0xb0,0x02,0x3c,
-0x40,0x00,0x03,0x24,0x91,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0x25,0xb0,0x03,0x3c,
-0x3a,0x01,0x02,0x24,0x92,0x00,0x63,0x34,0x00,0x00,0x62,0xa4,0xb5,0x00,0xd1,0x37,
-0x21,0x00,0x03,0x24,0x00,0x00,0x23,0xa2,0x10,0x00,0xa2,0x8f,0xa0,0x00,0xd2,0x37,
-0xa4,0x00,0xd3,0x37,0x00,0x00,0x42,0xae,0x14,0x00,0xa3,0x8f,0xa8,0x00,0xd4,0x37,
-0xac,0x00,0xd5,0x37,0x00,0x00,0x63,0xae,0x18,0x00,0xa2,0x8f,0x25,0xb0,0x03,0x3c,
-0xb0,0x00,0x63,0x34,0x00,0x00,0x82,0xae,0x21,0x10,0x02,0x3c,0xff,0x77,0x42,0x34,
-0x00,0x00,0xa2,0xae,0x25,0xb0,0x02,0x3c,0xd8,0x00,0x42,0x34,0x00,0x00,0x65,0xac,
-0x00,0x00,0x40,0xa0,0x1c,0x00,0xa2,0x93,0x25,0xb0,0x03,0x3c,0xb4,0x00,0x63,0x34,
-0x00,0x00,0x62,0xa0,0x25,0xb0,0x03,0x3c,0x04,0x00,0x02,0x24,0xb6,0x00,0x63,0x34,
-0x00,0x00,0x62,0xa0,0x25,0xb0,0x03,0x3c,0x0f,0x00,0x02,0x24,0xba,0x00,0x63,0x34,
-0xb9,0x00,0xdf,0x37,0x00,0x00,0xe4,0xa3,0x00,0x00,0x62,0xa4,0x25,0xb0,0x02,0x3c,
-0x1a,0x01,0x42,0x34,0x16,0x01,0xd0,0x37,0x18,0x01,0xcf,0x37,0x00,0x00,0x00,0xa6,
-0x25,0xb0,0x03,0x3c,0x00,0x00,0xe0,0xa5,0x00,0x00,0x40,0xa4,0xff,0xff,0x02,0x3c,
-0xff,0x0f,0x42,0x34,0xdc,0x00,0x63,0x34,0x00,0x00,0x62,0xac,0x2f,0x00,0x03,0x3c,
-0x25,0xb0,0x02,0x3c,0x32,0x32,0x63,0x34,0xd0,0x01,0x42,0x34,0x00,0x00,0x43,0xac,
-0x5e,0x00,0x02,0x3c,0x25,0xb0,0x03,0x3c,0x32,0x43,0x42,0x34,0xd4,0x01,0x63,0x34,
-0x00,0x00,0x62,0xac,0x08,0x00,0x03,0x3c,0x25,0xb0,0x02,0x3c,0x30,0xa5,0x63,0x34,
-0xd8,0x01,0x42,0x34,0x00,0x00,0x43,0xac,0xdc,0x01,0xc4,0x37,0x02,0x80,0x03,0x3c,
-0x49,0xa5,0x02,0x34,0x8e,0x7d,0x6d,0x90,0x00,0x00,0x82,0xac,0xc2,0x00,0x02,0x3c,
-0x1a,0x06,0x03,0x24,0x51,0x10,0x42,0x34,0xe0,0x01,0xc5,0x37,0xf4,0x01,0xc6,0x37,
-0xf8,0x01,0xc7,0x37,0x07,0x07,0x04,0x24,0x00,0x00,0xa3,0xa4,0x00,0x02,0xc8,0x37,
-0x00,0x00,0xc4,0xa4,0x26,0x00,0x03,0x24,0x00,0x00,0xe2,0xac,0x03,0x02,0xc9,0x37,
-0x04,0x00,0x02,0x24,0x00,0x00,0x03,0xa5,0x36,0x02,0xca,0x37,0x00,0x00,0x22,0xa1,
-0xc0,0x01,0x03,0x24,0x0c,0x00,0x02,0x24,0x34,0x02,0xcb,0x37,0x00,0x00,0x42,0xa1,
-0x37,0x02,0xcc,0x37,0x00,0x00,0x63,0xa5,0x03,0x00,0x02,0x24,0x22,0x00,0x03,0x24,
-0x00,0x00,0x82,0xa1,0xd6,0x00,0xa3,0x11,0x1b,0x1b,0x02,0x3c,0x13,0x13,0x02,0x3c,
-0x13,0x13,0x42,0x34,0x60,0x01,0xc3,0x37,0x64,0x01,0xc4,0x37,0x68,0x01,0xc5,0x37,
-0x7c,0x01,0xca,0x37,0x6c,0x01,0xc6,0x37,0x70,0x01,0xc7,0x37,0x74,0x01,0xc8,0x37,
-0x78,0x01,0xc9,0x37,0x00,0x00,0x62,0xac,0x00,0x00,0x82,0xac,0x02,0x80,0x03,0x3c,
-0x00,0x00,0xa2,0xac,0x00,0x00,0xc2,0xac,0x00,0x00,0xe2,0xac,0x00,0x00,0x02,0xad,
-0x00,0x00,0x22,0xad,0x00,0x00,0x42,0xad,0x8e,0x7d,0x65,0x90,0x25,0xb0,0x0c,0x3c,
-0x01,0x70,0x03,0x3c,0x80,0x01,0x82,0x35,0x08,0x5f,0x63,0x34,0x22,0x00,0x04,0x24,
-0x00,0x00,0x43,0xac,0xb5,0x00,0xa4,0x10,0x0f,0x1f,0x02,0x3c,0x92,0x00,0x02,0x24,
-0xb2,0x00,0xa2,0x10,0x0f,0x1f,0x02,0x3c,0x0f,0x10,0x02,0x3c,0x00,0xf0,0x51,0x34,
-0xf7,0x01,0x92,0x35,0x15,0xf0,0x4d,0x34,0x77,0x00,0x0e,0x24,0x84,0x01,0x87,0x35,
-0x88,0x01,0x88,0x35,0x10,0xf0,0x44,0x34,0x8c,0x01,0x85,0x35,0x05,0xf0,0x42,0x34,
-0x00,0x00,0xed,0xac,0x90,0x01,0x83,0x35,0x00,0x00,0x04,0xad,0x94,0x01,0x86,0x35,
-0x00,0x00,0xa2,0xac,0xf5,0x0f,0x02,0x24,0x00,0x00,0x71,0xac,0x25,0xb0,0x05,0x3c,
-0x00,0x00,0xc2,0xac,0x98,0x01,0x89,0x35,0x9c,0x01,0x8a,0x35,0xf0,0x0f,0x03,0x24,
-0x0d,0x00,0x02,0x24,0x00,0x00,0x23,0xad,0xa0,0x01,0x8b,0x35,0x00,0x00,0x42,0xad,
-0xa7,0x01,0xb7,0x34,0xf6,0x01,0x8c,0x35,0xff,0xff,0x02,0x24,0x00,0x00,0x6d,0xad,
-0x00,0x00,0x8e,0xa1,0x00,0x00,0x4e,0xa2,0x00,0x00,0xe2,0xa2,0x25,0xb0,0x02,0x3c,
-0xa8,0x01,0xb6,0x34,0xff,0xff,0x09,0x24,0xac,0x01,0x42,0x34,0x00,0x00,0xc9,0xae,
-0x03,0x04,0x04,0x3c,0x00,0x00,0x49,0xac,0x07,0x08,0x03,0x3c,0x25,0xb0,0x02,0x3c,
-0x01,0x02,0x84,0x34,0x05,0x06,0x63,0x34,0xb4,0x01,0xb1,0x34,0xb8,0x01,0xb2,0x34,
-0xbc,0x01,0xb3,0x34,0xb0,0x01,0x42,0x34,0x00,0x00,0x44,0xac,0x00,0x00,0x23,0xae,
-0x25,0xb0,0x02,0x3c,0x00,0x00,0x44,0xae,0x00,0x00,0x63,0xae,0x25,0xb0,0x03,0x3c,
-0x0c,0x00,0x06,0x24,0xc0,0x01,0xb4,0x34,0xc1,0x01,0xb5,0x34,0x0d,0x00,0x08,0x24,
-0xc2,0x01,0x63,0x34,0xc3,0x01,0x42,0x34,0x00,0x00,0x86,0xa2,0xc4,0x01,0xab,0x34,
-0x00,0x00,0xa6,0xa2,0xc5,0x01,0xac,0x34,0x00,0x00,0x66,0xa0,0x0e,0x00,0x07,0x24,
-0x00,0x00,0x48,0xa0,0xc6,0x01,0xaa,0x34,0xc7,0x01,0xad,0x34,0x0f,0x00,0x02,0x24,
-0x00,0x00,0x68,0xa1,0x00,0x00,0x87,0xa1,0x00,0x00,0x47,0xa1,0x00,0x00,0xa2,0xa1,
-0x57,0x01,0x02,0x3c,0x48,0x00,0xbf,0x34,0x46,0x00,0xae,0x34,0x0e,0xe2,0x42,0x34,
-0x00,0x00,0xc0,0xa5,0x4c,0x00,0xbe,0x34,0x00,0x00,0xe2,0xaf,0x4d,0x00,0xb9,0x34,
-0x80,0xff,0x02,0x24,0x00,0x00,0xc0,0xa3,0x00,0x00,0x22,0xa3,0x25,0xb0,0x02,0x3c,
-0xbc,0x00,0x03,0x24,0x40,0x00,0x42,0x34,0x00,0x00,0x43,0xa4,0x25,0xb0,0x03,0x3c,
-0x64,0x03,0xb8,0x34,0xfc,0x37,0x02,0x24,0x40,0x00,0x63,0x34,0x00,0x00,0x00,0xa3,
-0xd8,0x00,0xa7,0x34,0x00,0x00,0x62,0xa4,0x00,0x00,0xe3,0x90,0x2a,0xb0,0x04,0x3c,
-0x80,0xff,0x02,0x24,0x26,0xb0,0x06,0x3c,0x25,0x18,0x62,0x00,0x30,0x00,0x89,0x34,
-0x20,0x20,0x02,0x24,0x38,0x00,0x84,0x34,0x00,0x00,0xe3,0xa0,0x79,0x00,0xc8,0x34,
-0x00,0x00,0x82,0xa4,0x40,0x00,0x03,0x24,0x16,0x00,0x02,0x24,0x00,0x00,0x23,0xa1,
-0x94,0x00,0xaa,0x34,0x00,0x00,0x02,0xa1,0x98,0x00,0xab,0x34,0x64,0x00,0x03,0x24,
-0x22,0x00,0x02,0x24,0x00,0x00,0x43,0xa5,0x7c,0x00,0xd1,0x34,0x00,0x00,0x62,0xa5,
-0x04,0x00,0x12,0x24,0x9c,0x00,0xac,0x34,0x7a,0x00,0xc6,0x34,0x20,0x0c,0x02,0x24,
-0x0a,0x00,0x03,0x24,0x00,0x00,0xd2,0xa0,0x9a,0x00,0xad,0x34,0x00,0x00,0x22,0xa6,
-0x96,0x00,0xae,0x34,0x00,0x00,0x83,0xa1,0xff,0x03,0x02,0x24,0x02,0x00,0x03,0x24,
-0x00,0x00,0xa2,0xa5,0x00,0x00,0xc3,0xa5,0x25,0xb0,0x03,0x3c,0x20,0x00,0x02,0x24,
-0xb7,0x00,0x63,0x34,0x00,0x00,0x62,0xa0,0x25,0xb0,0x02,0x3c,0x09,0x00,0x03,0x24,
-0x89,0x00,0x42,0x34,0x00,0x00,0x43,0xa0,0x44,0x00,0xa5,0x34,0x00,0x00,0xa2,0x94,
-0x02,0x80,0x03,0x3c,0x68,0x15,0x66,0x24,0xff,0xfd,0x03,0x24,0x24,0x10,0x43,0x00,
-0x00,0x00,0xa2,0xa4,0x00,0x00,0xa3,0x94,0xd5,0x4a,0xc4,0x90,0x29,0xb0,0x02,0x3c,
-0x40,0x00,0x42,0x34,0x00,0x02,0x63,0x34,0x00,0x00,0xa3,0xa4,0x00,0x00,0x52,0xa0,
-0xd3,0x0a,0x00,0x0c,0x00,0x00,0x00,0x00,0x44,0x00,0xbf,0x8f,0x40,0x00,0xbe,0x8f,
-0x3c,0x00,0xb7,0x8f,0x38,0x00,0xb6,0x8f,0x34,0x00,0xb5,0x8f,0x30,0x00,0xb4,0x8f,
-0x2c,0x00,0xb3,0x8f,0x28,0x00,0xb2,0x8f,0x24,0x00,0xb1,0x8f,0x20,0x00,0xb0,0x8f,
-0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x48,0x00,0xbd,0x27,0x54,0x00,0x85,0x34,
-0x00,0xe0,0x42,0x34,0x50,0x00,0x84,0x34,0x12,0x01,0x03,0x24,0x00,0x00,0x82,0xac,
-0x00,0x00,0xa3,0xa4,0xf9,0x58,0x00,0x08,0x02,0x80,0x03,0x3c,0x00,0xf0,0x51,0x34,
-0xf7,0x01,0x92,0x35,0x15,0xf0,0x4d,0x34,0xad,0x59,0x00,0x08,0xff,0xff,0x0e,0x24,
-0x8b,0x59,0x00,0x08,0x1b,0x1b,0x42,0x34,0x25,0xb0,0x03,0x3c,0x25,0xb0,0x08,0x3c,
-0xfc,0x37,0x02,0x24,0x40,0x00,0x63,0x34,0x02,0x80,0x04,0x3c,0x00,0x00,0x62,0xa4,
-0x14,0x80,0x84,0x24,0xff,0x00,0x07,0x24,0xb0,0x03,0x06,0x35,0x00,0x00,0x83,0x94,
-0x00,0x00,0x00,0x00,0xff,0x00,0x62,0x30,0x21,0x18,0x68,0x00,0x0a,0x00,0x47,0x10,
-0xff,0x00,0x65,0x30,0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xac,
-0x00,0x00,0xc3,0xac,0x04,0x00,0x82,0x8c,0x08,0x00,0x84,0x24,0x00,0x00,0xc2,0xac,
-0xf2,0xff,0xa7,0x14,0x00,0x00,0x00,0x00,0x25,0xb0,0x08,0x3c,0x01,0x80,0x02,0x3c,
-0x0c,0x7a,0x44,0x24,0xff,0x00,0x07,0x24,0xb0,0x03,0x06,0x35,0x00,0x00,0x83,0x94,
-0x00,0x00,0x00,0x00,0xff,0x00,0x62,0x30,0x21,0x18,0x68,0x00,0x0a,0x00,0x47,0x10,
-0xff,0x00,0x65,0x30,0x04,0x00,0x82,0x8c,0x00,0x00,0x00,0x00,0x00,0x00,0x62,0xac,
-0x00,0x00,0xc3,0xac,0x04,0x00,0x82,0x8c,0x08,0x00,0x84,0x24,0x00,0x00,0xc2,0xac,
-0xf2,0xff,0xa7,0x14,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,
-0x01,0x80,0x02,0x3c,0x02,0x80,0x05,0x3c,0x10,0x6b,0x42,0x24,0x02,0x80,0x03,0x3c,
-0xcc,0x7d,0xa2,0xac,0x00,0x80,0x02,0x3c,0x6c,0x7e,0x60,0xac,0xcc,0x7d,0xa4,0x24,
-0x02,0x80,0x03,0x3c,0xc8,0x06,0x42,0x24,0x70,0x7e,0x60,0xa4,0x08,0x00,0x82,0xac,
-0x02,0x80,0x03,0x3c,0x00,0x80,0x02,0x3c,0x72,0x7e,0x60,0xa4,0x02,0x80,0x06,0x3c,
-0x08,0x0a,0x42,0x24,0x00,0x80,0x03,0x3c,0x74,0x7e,0xc7,0x24,0x14,0x00,0x82,0xac,
-0x38,0x08,0x63,0x24,0x02,0x80,0x02,0x3c,0x74,0x7e,0xc0,0xac,0x10,0x00,0x83,0xac,
-0x04,0x00,0xe0,0xac,0x7c,0x7e,0x40,0xa0,0x00,0x80,0x02,0x3c,0x88,0x19,0x42,0x24,
-0x3c,0x00,0x82,0xac,0x00,0x80,0x03,0x3c,0x00,0x80,0x02,0x3c,0x24,0x0c,0x63,0x24,
-0x78,0x0f,0x42,0x24,0x1c,0x00,0x83,0xac,0x20,0x00,0x82,0xac,0x00,0x80,0x03,0x3c,
-0x00,0x80,0x02,0x3c,0xc8,0x12,0x63,0x24,0x28,0x16,0x42,0x24,0x24,0x00,0x83,0xac,
-0x28,0x00,0x82,0xac,0x00,0x80,0x03,0x3c,0x01,0x80,0x02,0x3c,0x4c,0x1f,0x63,0x24,
-0xd0,0x04,0x42,0x24,0x2c,0x00,0x83,0xac,0x30,0x00,0x82,0xac,0x00,0x80,0x03,0x3c,
-0x00,0x80,0x02,0x3c,0xe4,0x19,0x63,0x24,0x00,0x03,0x42,0x24,0x38,0x00,0x83,0xac,
-0x08,0x00,0xe0,0x03,0x4c,0x00,0x82,0xac,0x25,0xb0,0x02,0x3c,0x08,0x00,0x42,0x34,
-0x00,0x00,0x43,0x8c,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x0e,0x3c,
-0x02,0x80,0x08,0x3c,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,0xf8,0x03,0x4d,0x24,
-0x00,0x14,0x6c,0x24,0x01,0x00,0x07,0x24,0x00,0x00,0xcb,0x25,0xff,0xff,0x0a,0x24,
-0x00,0x04,0x09,0x25,0x80,0x1a,0x07,0x00,0x21,0x10,0x6b,0x00,0x00,0x00,0x42,0xac,
-0x90,0x00,0x4a,0xac,0x00,0x04,0x04,0x8d,0x01,0x00,0xe7,0x24,0x08,0x00,0x45,0x24,
-0x21,0x18,0x6d,0x00,0x05,0x00,0xe6,0x28,0x04,0x00,0x82,0xac,0x00,0x00,0x44,0xac,
-0x04,0x00,0x49,0xac,0x00,0x04,0x02,0xad,0x8c,0x00,0x40,0xac,0x6c,0x00,0xa3,0xac,
-0xf0,0xff,0xc0,0x14,0x68,0x00,0xac,0xac,0x08,0x00,0xe0,0x03,0x00,0x00,0xc9,0xad,
-0x05,0x00,0xa2,0x2c,0x13,0x00,0x40,0x10,0xff,0xff,0x07,0x24,0x02,0x80,0x02,0x3c,
-0x80,0x1a,0x05,0x00,0x00,0x00,0x42,0x24,0x0e,0x00,0xa0,0x10,0x21,0x30,0x62,0x00,
-0x90,0x00,0xc3,0x8c,0xff,0xff,0x02,0x24,0x0a,0x00,0x62,0x14,0x00,0x00,0x00,0x00,
-0x8c,0x00,0xc2,0x8c,0x00,0x00,0x00,0x00,0x06,0x00,0x40,0x14,0x00,0x00,0x00,0x00,
-0x01,0x00,0x02,0x24,0x88,0x00,0xc4,0xac,0x8c,0x00,0xc2,0xac,0x90,0x00,0xc5,0xac,
-0x21,0x38,0xa0,0x00,0x08,0x00,0xe0,0x03,0x21,0x10,0xe0,0x00,0x25,0xb0,0x04,0x3c,
-0x01,0x80,0x02,0x3c,0x18,0x03,0x85,0x34,0xf4,0x6b,0x42,0x24,0xe0,0xff,0xbd,0x27,
-0x00,0x00,0xa2,0xac,0x1b,0x00,0x86,0x34,0xdb,0xff,0x03,0x24,0x27,0x00,0x84,0x34,
-0x07,0x00,0x02,0x24,0x14,0x00,0xb1,0xaf,0x10,0x00,0xb0,0xaf,0x00,0x00,0x83,0xa0,
-0x18,0x00,0xbf,0xaf,0x00,0x00,0xc2,0xa0,0x01,0x00,0x11,0x24,0x21,0x80,0x00,0x00,
-0x7a,0x42,0x00,0x0c,0x21,0x20,0x00,0x02,0x01,0x00,0x02,0x26,0xff,0x00,0x50,0x30,
-0x2b,0x18,0x30,0x02,0xfa,0xff,0x60,0x10,0x00,0x00,0x00,0x00,0x7a,0x42,0x00,0x0c,
-0x21,0x20,0x00,0x00,0x18,0x00,0xbf,0x8f,0x14,0x00,0xb1,0x8f,0x10,0x00,0xb0,0x8f,
-0x01,0x00,0x02,0x24,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x08,0x00,0xe0,0x03,
-0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x00,0x00,0x00,0x00,0x02,0x80,0x02,0x3c,
-0x68,0x15,0x42,0x24,0x40,0x10,0x03,0x3c,0xff,0xff,0x44,0x30,0x25,0xc0,0x83,0x00,
-0x94,0x64,0x58,0xac,0x40,0x00,0x18,0x27,0xa0,0x64,0x58,0xac,0x40,0x00,0x18,0x27,
-0xac,0x64,0x58,0xac,0x40,0x00,0x18,0x27,0xb8,0x64,0x58,0xac,0x40,0x00,0x18,0x27,
-0xe0,0xff,0xbd,0x27,0xc4,0x64,0x58,0xac,0x40,0x00,0x18,0x27,0x1c,0x00,0xb7,0xaf,
-0x18,0x00,0xb6,0xaf,0x14,0x00,0xb5,0xaf,0x10,0x00,0xb4,0xaf,0x0c,0x00,0xb3,0xaf,
-0x08,0x00,0xb2,0xaf,0x04,0x00,0xb1,0xaf,0x00,0x00,0xb0,0xaf,0xd0,0x64,0x58,0xac,
-0xa0,0x64,0x45,0x8c,0xac,0x64,0x46,0x8c,0xb8,0x64,0x47,0x8c,0xc4,0x64,0x48,0x8c,
-0xd0,0x64,0x49,0x8c,0x40,0x00,0x18,0x27,0xdc,0x64,0x58,0xac,0x21,0x50,0x00,0x03,
-0x25,0x20,0x83,0x00,0x40,0x00,0x18,0x27,0x20,0x10,0x03,0x3c,0x90,0x64,0x44,0xac,
-0x9c,0x64,0x45,0xac,0xa8,0x64,0x46,0xac,0xb4,0x64,0x47,0xac,0xc0,0x64,0x48,0xac,
-0xcc,0x64,0x49,0xac,0x25,0xb0,0x06,0x3c,0x28,0x64,0x43,0xac,0x24,0x64,0x43,0xac,
-0x34,0x64,0x43,0xac,0x30,0x64,0x43,0xac,0x40,0x64,0x43,0xac,0x3c,0x64,0x43,0xac,
-0x4c,0x64,0x43,0xac,0x48,0x64,0x43,0xac,0xe8,0x64,0x58,0xac,0x00,0x02,0x18,0x27,
-0xd8,0x64,0x4a,0xac,0x00,0x65,0x58,0xac,0x58,0x64,0x43,0xac,0x54,0x64,0x43,0xac,
-0x64,0x64,0x43,0xac,0x60,0x64,0x43,0xac,0x70,0x64,0x43,0xac,0x6c,0x64,0x43,0xac,
-0xac,0x00,0xc4,0x34,0xb0,0x00,0xc5,0x34,0x00,0x00,0x92,0x8c,0xe8,0x64,0x50,0x8c,
-0x00,0x00,0xb3,0x8c,0x21,0x10,0x04,0x3c,0x23,0x10,0x09,0x3c,0x22,0x10,0x0c,0x3c,
-0x02,0x80,0x14,0x3c,0x02,0x80,0x15,0x3c,0x02,0x80,0x16,0x3c,0x02,0x80,0x17,0x3c,
-0x24,0x10,0x05,0x3c,0x21,0x88,0x00,0x03,0x08,0x7b,0x87,0x26,0x00,0x04,0x18,0x27,
-0x10,0x7b,0xa8,0x26,0x18,0x7b,0xca,0x26,0x20,0x7b,0xeb,0x26,0x00,0x04,0x2d,0x35,
-0x00,0x40,0x8e,0x34,0x00,0x80,0x8f,0x35,0x00,0x01,0xc6,0x34,0xe4,0x64,0x50,0xac,
-0xfc,0x64,0x51,0xac,0x64,0x65,0x4d,0xac,0x28,0x65,0x52,0xac,0x34,0x65,0x4e,0xac,
-0x58,0x65,0x4f,0xac,0x4c,0x65,0x53,0xac,0x00,0x00,0xc5,0xac,0x48,0x65,0x45,0xac,
-0x68,0x65,0x43,0xac,0x74,0x65,0x58,0xac,0x7c,0x64,0x43,0xac,0x78,0x64,0x43,0xac,
-0x06,0x65,0x40,0xa4,0x05,0x65,0x40,0xa0,0x04,0x65,0x40,0xa0,0x5c,0x65,0x49,0xac,
-0x60,0x65,0x49,0xac,0x20,0x65,0x44,0xac,0x24,0x65,0x44,0xac,0x2c,0x65,0x44,0xac,
-0x30,0x65,0x44,0xac,0x50,0x65,0x4c,0xac,0x54,0x65,0x4c,0xac,0x44,0x65,0x45,0xac,
-0x6c,0x65,0x43,0xac,0x78,0x65,0x58,0xac,0x04,0x00,0x08,0xad,0x08,0x7b,0x87,0xae,
-0x04,0x00,0x4a,0xad,0x10,0x7b,0xa8,0xae,0x04,0x00,0x6b,0xad,0x18,0x7b,0xca,0xae,
-0x20,0x7b,0xeb,0xae,0x04,0x00,0xe7,0xac,0x02,0x80,0x02,0x3c,0x00,0x14,0x43,0x24,
-0x21,0x20,0xe0,0x00,0x03,0x00,0x06,0x24,0x21,0x10,0x80,0x00,0xff,0xff,0xc6,0x24,
-0x08,0x00,0x78,0xac,0x00,0x00,0x63,0xac,0x10,0x00,0x60,0xac,0x00,0x00,0x67,0xac,
-0x21,0x20,0x60,0x00,0x04,0x00,0x62,0xac,0x00,0x00,0x43,0xac,0x00,0x01,0x18,0x27,
-0xf5,0xff,0xc1,0x04,0x18,0x00,0x63,0x24,0x02,0x80,0x02,0x3c,0x10,0x7b,0x49,0x24,
-0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x04,0x00,0x28,0x8d,0x60,0x14,0x4b,0x24,
-0x04,0x00,0xe4,0xac,0x00,0x14,0x6a,0x24,0x01,0x00,0x07,0x24,0x21,0x28,0x00,0x00,
-0x07,0x00,0x06,0x24,0x21,0x20,0xab,0x00,0x21,0x10,0xaa,0x00,0xff,0xff,0xc6,0x24,
-0x68,0x00,0x58,0xac,0x70,0x00,0x47,0xac,0x18,0x00,0xa5,0x24,0x00,0x00,0x89,0xac,
-0x04,0x00,0x88,0xac,0x00,0x00,0x04,0xad,0x00,0x01,0x18,0x27,0xf5,0xff,0xc1,0x04,
-0x21,0x40,0x80,0x00,0x02,0x80,0x02,0x3c,0x18,0x7b,0x4a,0x24,0x02,0x80,0x03,0x3c,
-0x02,0x80,0x02,0x3c,0x04,0x00,0x45,0x8d,0x20,0x15,0x4b,0x24,0x04,0x00,0x24,0xad,
-0x02,0x00,0x07,0x24,0x00,0x14,0x69,0x24,0x21,0x20,0x00,0x00,0x01,0x00,0x06,0x24,
-0x21,0x40,0x8b,0x00,0x21,0x10,0x89,0x00,0xff,0xff,0xc6,0x24,0x28,0x01,0x58,0xac,
-0x30,0x01,0x47,0xac,0x18,0x00,0x84,0x24,0x00,0x00,0x0a,0xad,0x04,0x00,0x05,0xad,
-0x00,0x00,0xa8,0xac,0x00,0x02,0x18,0x27,0xf5,0xff,0xc1,0x04,0x21,0x28,0x00,0x01,
-0x02,0x80,0x05,0x3c,0x20,0x7b,0xa5,0x24,0x04,0x00,0xa6,0x8c,0x1c,0x00,0xb7,0x8f,
-0x18,0x00,0xb6,0x8f,0x14,0x00,0xb5,0x8f,0x10,0x00,0xb4,0x8f,0x0c,0x00,0xb3,0x8f,
-0x08,0x00,0xb2,0x8f,0x04,0x00,0xb1,0x8f,0x00,0x00,0xb0,0x8f,0x02,0x80,0x07,0x3c,
-0x02,0x80,0x03,0x3c,0x50,0x15,0xe4,0x24,0x00,0x14,0x63,0x24,0x03,0x00,0x02,0x24,
-0x20,0x00,0xbd,0x27,0x58,0x01,0x78,0xac,0x04,0x00,0x48,0xad,0x04,0x00,0xa4,0xac,
-0x60,0x01,0x62,0xac,0x50,0x15,0xe5,0xac,0x04,0x00,0x86,0xac,0x08,0x00,0xe0,0x03,
-0x00,0x00,0xc4,0xac,0xd0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x20,0x00,0xb2,0xaf,
-0x02,0x80,0x03,0x3c,0x4c,0x91,0x52,0x24,0x02,0x80,0x02,0x3c,0x28,0x00,0xb4,0xaf,
-0x24,0x00,0xb3,0xaf,0x1c,0x00,0xb1,0xaf,0x18,0x00,0xb0,0xaf,0x2c,0x00,0xbf,0xaf,
-0xd8,0x90,0x73,0x24,0x68,0x15,0x50,0x24,0x21,0x88,0x00,0x00,0x02,0x80,0x14,0x3c,
-0xee,0x4e,0x00,0x0c,0x21,0x20,0x20,0x02,0x78,0x51,0x05,0x8e,0x6c,0x00,0x66,0x8e,
-0xb8,0x90,0x82,0x26,0x6c,0x00,0x43,0x8e,0x1b,0x00,0x44,0x90,0xff,0xf1,0x02,0x24,
-0x21,0x18,0x66,0x00,0x24,0x28,0xa2,0x00,0x00,0x21,0x04,0x00,0x42,0x18,0x03,0x00,
-0x00,0x02,0xa5,0x34,0x44,0x51,0x03,0xae,0x68,0x51,0x04,0xae,0x78,0x51,0x05,0xae,
-0x6c,0x51,0x04,0xae,0x21,0x30,0x00,0x00,0x21,0x10,0x06,0x02,0x01,0x00,0xc6,0x24,
-0x1d,0x00,0xc3,0x28,0x99,0x51,0x40,0xa0,0x7c,0x51,0x40,0xa0,0xfa,0xff,0x60,0x14,
-0xb6,0x51,0x40,0xa0,0x01,0x00,0x31,0x26,0x20,0x00,0x22,0x2a,0xd4,0x51,0x00,0xae,
-0xe3,0xff,0x40,0x14,0x94,0x00,0x10,0x26,0x02,0x80,0x02,0x3c,0x02,0x80,0x03,0x3c,
-0x68,0x15,0x4b,0x24,0x02,0x80,0x02,0x3c,0x4c,0x91,0x6f,0x24,0xd8,0x90,0x4d,0x24,
-0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0xb8,0x90,0x6e,0x24,0x98,0x90,0x4c,0x24,
-0x21,0x88,0x00,0x00,0x80,0x18,0x11,0x00,0x21,0x20,0x6d,0x00,0x21,0x10,0x6f,0x00,
-0x21,0x28,0x2e,0x02,0x21,0x30,0x2c,0x02,0x00,0x00,0x88,0x8c,0x00,0x00,0xa9,0x90,
-0x00,0x00,0xc7,0x90,0x00,0x00,0x4a,0x8c,0x21,0x10,0x2b,0x02,0x01,0x00,0x31,0x26,
-0x21,0x18,0x6b,0x00,0x1d,0x00,0x24,0x2a,0xec,0x44,0x68,0xac,0xca,0x44,0x47,0xa0,
-0x60,0x45,0x6a,0xac,0xef,0xff,0x80,0x14,0x90,0x44,0x49,0xa0,0x02,0x80,0x02,0x3c,
-0x68,0x15,0x4a,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x02,0x3c,0x74,0x8f,0x6b,0x24,
-0x14,0x8e,0x4c,0x24,0x21,0x88,0x00,0x00,0x21,0x48,0x00,0x00,0x21,0x30,0x00,0x00,
-0x21,0x40,0x2a,0x01,0x21,0x38,0x2b,0x01,0x21,0x10,0xe6,0x00,0x91,0x00,0x44,0x90,
-0x00,0x00,0x45,0x90,0x21,0x18,0x06,0x01,0x01,0x00,0xc6,0x24,0x05,0x00,0xc2,0x28,
-0xc5,0x43,0x64,0xa0,0xf8,0xff,0x40,0x14,0x34,0x43,0x65,0xa0,0x21,0x10,0x2c,0x02,
-0x1d,0x00,0x44,0x90,0x00,0x00,0x45,0x90,0x21,0x18,0x2a,0x02,0x01,0x00,0x31,0x26,
-0x1d,0x00,0x22,0x2a,0x73,0x44,0x64,0xa0,0x56,0x44,0x65,0xa0,0xeb,0xff,0x40,0x14,
-0x05,0x00,0x29,0x25,0x52,0x00,0x02,0x24,0x10,0x00,0xa2,0xa3,0x41,0x00,0x03,0x24,
-0x4d,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,0x1c,0x97,0xe7,0x24,0x11,0x00,0xa3,0xa3,
-0x12,0x00,0xa2,0xa3,0xe8,0x03,0x03,0x24,0x01,0x00,0x02,0x24,0x00,0x80,0x06,0x3c,
-0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0xf0,0x37,0xc6,0x24,0x0c,0x00,0xe3,0xac,
-0x14,0x00,0xe2,0xa0,0xfb,0x0c,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x2c,0x00,0xbf,0x8f,
-0x28,0x00,0xb4,0x8f,0x24,0x00,0xb3,0x8f,0x20,0x00,0xb2,0x8f,0x1c,0x00,0xb1,0x8f,
-0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x30,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,
-0x02,0x80,0x02,0x3c,0x42,0x00,0x03,0x24,0x10,0x00,0xa3,0xa3,0x55,0x60,0x40,0xa0,
-0x4e,0x00,0x03,0x24,0x43,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,0x54,0x97,0xe7,0x24,
-0x11,0x00,0xa2,0xa3,0x12,0x00,0xa3,0xa3,0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24,
-0x00,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0xdc,0x44,0xc6,0x24,
-0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,0x18,0x00,0xbf,0xaf,0xfb,0x0c,0x00,0x0c,
-0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x20,0x00,0xbd,0x27,0x48,0xfd,0xbd,0x27,0xb4,0x02,0xb3,0xaf,0x02,0x80,0x02,0x3c,
-0x02,0x80,0x13,0x3c,0x24,0x92,0x46,0x24,0x68,0x15,0x63,0x26,0xb0,0x02,0xb2,0xaf,
-0xac,0x02,0xb1,0xaf,0xa8,0x02,0xb0,0xaf,0x03,0x40,0x60,0xa0,0x21,0x38,0xa0,0x03,
-0x90,0x00,0xc8,0x24,0x00,0x00,0xc2,0x8c,0x04,0x00,0xc3,0x8c,0x08,0x00,0xc4,0x8c,
-0x0c,0x00,0xc5,0x8c,0x10,0x00,0xc6,0x24,0x00,0x00,0xe2,0xac,0x04,0x00,0xe3,0xac,
-0x08,0x00,0xe4,0xac,0x0c,0x00,0xe5,0xac,0xf6,0xff,0xc8,0x14,0x10,0x00,0xe7,0x24,
-0x00,0x00,0xc3,0x8c,0x02,0x80,0x02,0x3c,0xb8,0x92,0x58,0x24,0x00,0x00,0xe3,0xac,
-0x98,0x00,0xb9,0x27,0x00,0x01,0x12,0x27,0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,
-0x09,0x00,0x04,0x93,0x0d,0x00,0x05,0x93,0x00,0x00,0x11,0x93,0x02,0x00,0x0d,0x93,
-0x04,0x00,0x10,0x93,0x06,0x00,0x0c,0x93,0x08,0x00,0x0f,0x93,0x0a,0x00,0x07,0x93,
-0x0c,0x00,0x0e,0x93,0x0e,0x00,0x06,0x93,0x03,0x00,0x08,0x93,0x07,0x00,0x09,0x93,
-0x0b,0x00,0x0a,0x93,0x0f,0x00,0x0b,0x93,0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,
-0x00,0x22,0x04,0x00,0x00,0x2a,0x05,0x00,0x25,0x10,0x51,0x00,0x25,0x18,0x70,0x00,
-0x25,0x20,0x8f,0x00,0x25,0x28,0xae,0x00,0x00,0x6c,0x0d,0x00,0x00,0x64,0x0c,0x00,
-0x00,0x3c,0x07,0x00,0x00,0x34,0x06,0x00,0x25,0x68,0xa2,0x01,0x25,0x60,0x83,0x01,
-0x25,0x38,0xe4,0x00,0x25,0x30,0xc5,0x00,0x00,0x46,0x08,0x00,0x00,0x4e,0x09,0x00,
-0x00,0x56,0x0a,0x00,0x00,0x5e,0x0b,0x00,0x25,0x40,0x0d,0x01,0x25,0x48,0x2c,0x01,
-0x25,0x50,0x47,0x01,0x25,0x58,0x66,0x01,0x10,0x00,0x18,0x27,0x00,0x00,0x28,0xaf,
-0x04,0x00,0x29,0xaf,0x08,0x00,0x2a,0xaf,0x0c,0x00,0x2b,0xaf,0xd2,0xff,0x12,0x17,
-0x10,0x00,0x39,0x27,0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,0x00,0x00,0x09,0x93,
-0x02,0x00,0x04,0x93,0x04,0x00,0x08,0x93,0x06,0x00,0x05,0x93,0x07,0x00,0x06,0x93,
-0x03,0x00,0x07,0x93,0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,0x25,0x10,0x49,0x00,
-0x25,0x18,0x68,0x00,0x00,0x24,0x04,0x00,0x00,0x2c,0x05,0x00,0x25,0x20,0x82,0x00,
-0x25,0x28,0xa3,0x00,0x00,0x3e,0x07,0x00,0x00,0x36,0x06,0x00,0x02,0x80,0x02,0x3c,
-0x25,0x38,0xe4,0x00,0x25,0x30,0xc5,0x00,0xc0,0x93,0x58,0x24,0x04,0x00,0x26,0xaf,
-0x00,0x00,0x27,0xaf,0x00,0x01,0x12,0x27,0xa0,0x01,0xb9,0x27,0x01,0x00,0x02,0x93,
-0x05,0x00,0x03,0x93,0x09,0x00,0x04,0x93,0x0d,0x00,0x05,0x93,0x00,0x00,0x11,0x93,
-0x02,0x00,0x0d,0x93,0x04,0x00,0x10,0x93,0x06,0x00,0x0c,0x93,0x08,0x00,0x0f,0x93,
-0x0a,0x00,0x07,0x93,0x0c,0x00,0x0e,0x93,0x0e,0x00,0x06,0x93,0x03,0x00,0x08,0x93,
-0x07,0x00,0x09,0x93,0x0b,0x00,0x0a,0x93,0x0f,0x00,0x0b,0x93,0x00,0x12,0x02,0x00,
-0x00,0x1a,0x03,0x00,0x00,0x22,0x04,0x00,0x00,0x2a,0x05,0x00,0x25,0x10,0x51,0x00,
-0x25,0x18,0x70,0x00,0x25,0x20,0x8f,0x00,0x25,0x28,0xae,0x00,0x00,0x6c,0x0d,0x00,
-0x00,0x64,0x0c,0x00,0x00,0x3c,0x07,0x00,0x00,0x34,0x06,0x00,0x25,0x68,0xa2,0x01,
-0x25,0x60,0x83,0x01,0x25,0x38,0xe4,0x00,0x25,0x30,0xc5,0x00,0x00,0x46,0x08,0x00,
-0x00,0x4e,0x09,0x00,0x00,0x56,0x0a,0x00,0x00,0x5e,0x0b,0x00,0x25,0x40,0x0d,0x01,
-0x25,0x48,0x2c,0x01,0x25,0x50,0x47,0x01,0x25,0x58,0x66,0x01,0x10,0x00,0x18,0x27,
-0x00,0x00,0x28,0xaf,0x04,0x00,0x29,0xaf,0x08,0x00,0x2a,0xaf,0x0c,0x00,0x2b,0xaf,
-0xd2,0xff,0x12,0x17,0x10,0x00,0x39,0x27,0x01,0x00,0x02,0x93,0x05,0x00,0x03,0x93,
-0x00,0x00,0x09,0x93,0x02,0x00,0x04,0x93,0x04,0x00,0x08,0x93,0x06,0x00,0x05,0x93,
-0x07,0x00,0x06,0x93,0x03,0x00,0x07,0x93,0x00,0x12,0x02,0x00,0x00,0x1a,0x03,0x00,
-0x25,0x10,0x49,0x00,0x25,0x18,0x68,0x00,0x00,0x24,0x04,0x00,0x00,0x2c,0x05,0x00,
-0x25,0x20,0x82,0x00,0x25,0x28,0xa3,0x00,0x00,0x3e,0x07,0x00,0x00,0x36,0x06,0x00,
-0x25,0x30,0xc5,0x00,0x25,0x38,0xe4,0x00,0x02,0x80,0x02,0x3c,0x04,0x00,0x26,0xaf,
-0x00,0x00,0x27,0xaf,0x68,0x15,0x46,0x24,0x21,0x50,0x00,0x00,0x80,0x20,0x0a,0x00,
-0x21,0x10,0x9d,0x00,0x00,0x00,0x45,0x8c,0x01,0x00,0x43,0x25,0xff,0x00,0x6a,0x30,
-0x21,0x20,0x86,0x00,0x25,0x00,0x42,0x2d,0xf8,0xff,0x40,0x14,0x18,0x40,0x85,0xac,
-0x02,0x80,0x02,0x3c,0x68,0x15,0x4b,0x24,0x21,0x50,0x00,0x00,0xc0,0x10,0x0a,0x00,
-0x21,0x48,0x5d,0x00,0x21,0x38,0x00,0x00,0x21,0x40,0x4b,0x00,0x21,0x10,0x27,0x01,
-0xa0,0x01,0x46,0x90,0x98,0x00,0x45,0x90,0x01,0x00,0xe4,0x24,0x21,0x18,0x07,0x01,
-0xff,0x00,0x87,0x30,0x08,0x00,0xe2,0x2c,0xb4,0x41,0x66,0xa0,0xf7,0xff,0x40,0x14,
-0xac,0x40,0x65,0xa0,0x01,0x00,0x42,0x25,0xff,0x00,0x4a,0x30,0x21,0x00,0x43,0x2d,
-0xef,0xff,0x60,0x14,0xc0,0x10,0x0a,0x00,0x25,0xb0,0x02,0x3c,0x0a,0x00,0x42,0x34,
-0x00,0x00,0x43,0x90,0x00,0x00,0x00,0x00,0x20,0x00,0x63,0x30,0x42,0x00,0x60,0x10,
-0x68,0x15,0x64,0x26,0x33,0x00,0x02,0x24,0xc1,0x42,0x62,0xa1,0x1c,0x00,0x03,0x24,
-0x0f,0x00,0x02,0x24,0xbc,0x42,0x63,0xa1,0xbd,0x42,0x62,0xa1,0x68,0x15,0x65,0x26,
-0x08,0x40,0xa4,0x8c,0xff,0x7f,0x08,0x3c,0xff,0xff,0x08,0x35,0xc0,0xff,0x02,0x24,
-0x24,0x20,0x88,0x00,0x24,0x20,0x82,0x00,0x0c,0x00,0x84,0x34,0xff,0xc0,0x02,0x24,
-0x24,0x20,0x82,0x00,0xc0,0xff,0x02,0x3c,0xff,0xff,0x42,0x34,0x00,0x18,0x84,0x34,
-0xbf,0xff,0x03,0x3c,0x24,0x20,0x82,0x00,0xff,0xff,0x63,0x34,0x7f,0xff,0x02,0x3c,
-0x24,0x20,0x83,0x00,0xff,0xff,0x42,0x34,0x24,0x20,0x82,0x00,0x0c,0x40,0xa6,0x8c,
-0x7f,0xff,0x03,0x24,0x40,0x40,0x84,0x34,0xff,0xff,0x02,0x3c,0x24,0x20,0x83,0x00,
-0xff,0x7f,0x42,0x34,0xff,0xbf,0x03,0x3c,0x10,0x40,0xa7,0x8c,0x24,0x20,0x82,0x00,
-0xff,0xff,0x63,0x34,0xff,0x9f,0x02,0x3c,0x24,0x30,0xc3,0x00,0xff,0xff,0x42,0x34,
-0xff,0x3f,0x03,0x3c,0x24,0x20,0x82,0x00,0xff,0xff,0x63,0x34,0x12,0x00,0x02,0x24,
-0xb4,0x02,0xb3,0x8f,0xb0,0x02,0xb2,0x8f,0xac,0x02,0xb1,0x8f,0xa8,0x02,0xb0,0x8f,
-0x24,0x38,0xe3,0x00,0xc7,0x42,0xa2,0xa0,0x1f,0x00,0x03,0x24,0x01,0x00,0x02,0x24,
-0x24,0x30,0xc8,0x00,0xbe,0x42,0xa3,0xa0,0xc0,0x42,0xa2,0xa0,0xff,0x00,0x03,0x24,
-0xff,0xff,0x02,0x24,0xb8,0x02,0xbd,0x27,0x08,0x40,0xa4,0xac,0x10,0x40,0xa7,0xac,
-0x0c,0x40,0xa6,0xac,0xc2,0x42,0xa2,0xa0,0xc4,0x42,0xa3,0xa4,0xbf,0x42,0xa0,0xa0,
-0x08,0x00,0xe0,0x03,0xc6,0x42,0xa0,0xa0,0x33,0x00,0x02,0x24,0xc1,0x42,0x82,0xa0,
-0x0d,0x00,0x03,0x24,0x03,0x00,0x02,0x24,0xbc,0x42,0x83,0xa0,0x65,0x5d,0x00,0x08,
-0xbd,0x42,0x82,0xa0,0xe0,0xff,0xbd,0x27,0x02,0x80,0x07,0x3c,0x68,0x15,0xe7,0x24,
-0x18,0x00,0xbf,0xaf,0x00,0x40,0xe3,0x8c,0xf0,0xff,0x02,0x24,0x02,0x80,0x08,0x3c,
-0x24,0x18,0x62,0x00,0xff,0xf0,0x02,0x24,0x24,0x18,0x62,0x00,0x00,0x40,0xe3,0xac,
-0x1c,0x00,0x03,0x24,0x36,0x00,0x02,0x24,0xcf,0x42,0xe3,0xa0,0x20,0x00,0x03,0x24,
-0xce,0x42,0xe2,0xa0,0xd1,0x42,0xe3,0xa0,0x32,0x00,0x02,0x24,0x20,0x00,0x03,0x24,
-0xd0,0x42,0xe2,0xa0,0xc8,0x42,0xe3,0xa4,0x0a,0x00,0x02,0x24,0x00,0x02,0x03,0x24,
-0xd2,0x42,0xe2,0xa0,0xcc,0x42,0xe3,0xa4,0x00,0x01,0x02,0x24,0x49,0x00,0x03,0x24,
-0x38,0x97,0x08,0x25,0xff,0xff,0x0a,0x34,0x01,0x00,0x09,0x24,0x11,0x00,0xa3,0xa3,
-0xca,0x42,0xe2,0xa4,0xd0,0x07,0x03,0x24,0x44,0x00,0x02,0x24,0x00,0x80,0x06,0x3c,
-0x10,0x00,0xa2,0xa3,0x10,0x00,0xa5,0x27,0x47,0x00,0x02,0x24,0x21,0x20,0x00,0x01,
-0x54,0x45,0xc6,0x24,0x04,0x40,0xea,0xac,0x02,0x40,0xe9,0xa0,0x0c,0x00,0x03,0xad,
-0x14,0x00,0x09,0xa1,0xe6,0x42,0xe0,0xa0,0xdc,0x63,0xea,0xac,0xd7,0x42,0xe0,0xa0,
-0x12,0x00,0xa2,0xa3,0xfb,0x0c,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,
-0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,
-0x02,0x80,0x02,0x3c,0x50,0x00,0x03,0x24,0x10,0x00,0xa3,0xa3,0x2a,0x62,0x40,0xa0,
-0x41,0x00,0x03,0x24,0x52,0x00,0x02,0x24,0x02,0x80,0x07,0x3c,0xc4,0x97,0xe7,0x24,
-0x11,0x00,0xa2,0xa3,0x12,0x00,0xa3,0xa3,0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24,
-0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0x88,0x5b,0xc6,0x24,
-0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,0x18,0x00,0xbf,0xaf,0xfb,0x0c,0x00,0x0c,
-0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x20,0x00,0xbd,0x27,0xd8,0xff,0xbd,0x27,0x18,0x00,0xb0,0xaf,0x02,0x80,0x10,0x3c,
-0x68,0x15,0x10,0x26,0x20,0x00,0xbf,0xaf,0x1c,0x00,0xb1,0xaf,0x00,0x40,0x09,0x8e,
-0xff,0xff,0x02,0x24,0xff,0x00,0x4b,0x30,0x0f,0xff,0x02,0x24,0x24,0x48,0x22,0x01,
-0xff,0xff,0x02,0x3c,0xff,0x0f,0x42,0x34,0x24,0x48,0x22,0x01,0x01,0x00,0x07,0x3c,
-0x47,0x00,0x02,0x24,0x3b,0x00,0x03,0x24,0x02,0x80,0x08,0x3c,0x10,0x00,0xa2,0xa3,
-0x11,0x00,0xa3,0xa3,0xe0,0x97,0x08,0x25,0x56,0x30,0xea,0x34,0xd0,0x07,0x02,0x24,
-0x01,0x00,0x03,0x24,0xf4,0x98,0xe7,0x34,0x00,0x80,0x06,0x3c,0x04,0x43,0x0b,0xae,
-0x00,0x40,0x09,0xae,0x43,0x00,0x11,0x24,0x10,0x00,0xa5,0x27,0x0c,0x43,0x07,0xae,
-0x10,0x43,0x0a,0xae,0x0c,0x00,0x02,0xad,0x14,0x00,0x03,0xa1,0x08,0x43,0x00,0xae,
-0x14,0x43,0x00,0xae,0x18,0x43,0x00,0xae,0x21,0x20,0x00,0x01,0xe4,0x4e,0xc6,0x24,
-0x12,0x00,0xb1,0xa3,0xfb,0x0c,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x1e,0x00,0x02,0x24,
-0x21,0x43,0x02,0xa2,0x4a,0x00,0x03,0x24,0x45,0x00,0x02,0x24,0x1c,0x43,0x03,0xa2,
-0x1d,0x43,0x02,0xa2,0x23,0x00,0x03,0x24,0x3e,0x00,0x02,0x24,0x1e,0x43,0x11,0xa2,
-0x1f,0x43,0x02,0xa2,0x20,0x43,0x03,0xa2,0x20,0x00,0xbf,0x8f,0x1c,0x00,0xb1,0x8f,
-0x18,0x00,0xb0,0x8f,0x08,0x00,0xe0,0x03,0x28,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,
-0x3b,0x00,0x02,0x24,0x43,0x00,0x03,0x24,0x10,0x00,0xa2,0xa3,0x11,0x00,0xa3,0xa3,
-0x36,0x00,0x02,0x24,0x02,0x80,0x03,0x3c,0x02,0x80,0x07,0x3c,0xfc,0x97,0xe7,0x24,
-0x12,0x00,0xa2,0xa3,0x3b,0x58,0x60,0xa0,0xd0,0x07,0x02,0x24,0x01,0x00,0x03,0x24,
-0x00,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0xe0,0x00,0x20,0x53,0xc6,0x24,
-0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,0x18,0x00,0xbf,0xaf,0xfb,0x0c,0x00,0x0c,
-0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x20,0x00,0xbd,0x27,0xff,0xff,0x07,0x24,0x02,0x80,0x02,0x3c,0xe0,0xff,0xbd,0x27,
-0x3d,0x58,0x47,0xa0,0x3b,0x00,0x03,0x24,0x43,0x00,0x02,0x24,0x10,0x00,0xa3,0xa3,
-0x11,0x00,0xa2,0xa3,0x36,0x00,0x03,0x24,0x16,0x00,0x02,0x24,0x02,0x80,0x08,0x3c,
-0x18,0x98,0x08,0x25,0x12,0x00,0xa3,0xa3,0x13,0x00,0xa2,0xa3,0xd0,0x07,0x03,0x24,
-0x01,0x00,0x02,0x24,0x00,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,0x21,0x20,0x00,0x01,
-0x0c,0x00,0x03,0xad,0x14,0x00,0x02,0xa1,0x18,0x00,0xbf,0xaf,0xfb,0x0c,0x00,0x0c,
-0xb8,0x54,0xc6,0x24,0x18,0x00,0xbf,0x8f,0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,
-0x20,0x00,0xbd,0x27,0xe0,0xff,0xbd,0x27,0x02,0x80,0x02,0x3c,0x52,0x00,0x03,0x24,
-0x10,0x00,0xa3,0xa3,0x4c,0x79,0x40,0xa4,0x54,0x00,0x03,0x24,0x53,0x00,0x02,0x24,
-0x02,0x80,0x07,0x3c,0x34,0x98,0xe7,0x24,0x11,0x00,0xa2,0xa3,0x12,0x00,0xa3,0xa3,
-0xf4,0x01,0x02,0x24,0x01,0x00,0x03,0x24,0x01,0x80,0x06,0x3c,0x10,0x00,0xa5,0x27,
-0x21,0x20,0xe0,0x00,0xc8,0x5c,0xc6,0x24,0x0c,0x00,0xe2,0xac,0x14,0x00,0xe3,0xa0,
-0x18,0x00,0xbf,0xaf,0xfb,0x0c,0x00,0x0c,0x13,0x00,0xa0,0xa3,0x18,0x00,0xbf,0x8f,
-0x00,0x00,0x00,0x00,0x08,0x00,0xe0,0x03,0x20,0x00,0xbd,0x27,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x78,0x0c,0x00,0x00,0x01,0x00,0x00,0x5e,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x01,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x02,0x5e,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x03,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x04,0x5d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x05,0x5b,0x78,0x0c,0x00,0x00,0x01,0x00,0x06,0x59,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x07,0x57,0x78,0x0c,0x00,0x00,0x01,0x00,0x08,0x55,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x09,0x53,0x78,0x0c,0x00,0x00,0x01,0x00,0x0a,0x51,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x0b,0x4f,0x78,0x0c,0x00,0x00,0x01,0x00,0x0c,0x4d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x0d,0x4b,0x78,0x0c,0x00,0x00,0x01,0x00,0x0e,0x49,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x0f,0x47,0x78,0x0c,0x00,0x00,0x01,0x00,0x10,0x45,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x11,0x43,0x78,0x0c,0x00,0x00,0x01,0x00,0x12,0x41,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x13,0x3f,0x78,0x0c,0x00,0x00,0x01,0x00,0x14,0x3d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x15,0x3b,0x78,0x0c,0x00,0x00,0x01,0x00,0x16,0x39,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x17,0x37,0x78,0x0c,0x00,0x00,0x01,0x00,0x18,0x35,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x19,0x33,0x78,0x0c,0x00,0x00,0x01,0x00,0x1a,0x31,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x1b,0x2f,0x78,0x0c,0x00,0x00,0x01,0x00,0x1c,0x2d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x1d,0x2b,0x78,0x0c,0x00,0x00,0x01,0x00,0x1e,0x29,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x1f,0x27,0x78,0x0c,0x00,0x00,0x01,0x00,0x20,0x25,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x21,0x23,0x78,0x0c,0x00,0x00,0x01,0x00,0x22,0x21,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x23,0x1f,0x78,0x0c,0x00,0x00,0x01,0x00,0x24,0x1d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x25,0x1b,0x78,0x0c,0x00,0x00,0x01,0x00,0x26,0x19,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x27,0x17,0x78,0x0c,0x00,0x00,0x01,0x00,0x28,0x15,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x29,0x13,0x78,0x0c,0x00,0x00,0x01,0x00,0x2a,0x11,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x2b,0x0f,0x78,0x0c,0x00,0x00,0x01,0x00,0x2c,0x0d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x2d,0x0b,0x78,0x0c,0x00,0x00,0x01,0x00,0x2e,0x09,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x2f,0x07,0x78,0x0c,0x00,0x00,0x01,0x00,0x30,0x05,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x31,0x03,0x78,0x0c,0x00,0x00,0x01,0x00,0x32,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x33,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x34,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x35,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x36,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x37,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x38,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x39,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3a,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x3b,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3c,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x3d,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x3e,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x3f,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x40,0x5e,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x41,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x42,0x5e,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x43,0x5e,0x78,0x0c,0x00,0x00,0x01,0x00,0x44,0x5d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x45,0x5b,0x78,0x0c,0x00,0x00,0x01,0x00,0x46,0x59,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x47,0x57,0x78,0x0c,0x00,0x00,0x01,0x00,0x48,0x55,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x49,0x53,0x78,0x0c,0x00,0x00,0x01,0x00,0x4a,0x51,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x4b,0x4f,0x78,0x0c,0x00,0x00,0x01,0x00,0x4c,0x4d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x4d,0x4b,0x78,0x0c,0x00,0x00,0x01,0x00,0x4e,0x49,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x4f,0x47,0x78,0x0c,0x00,0x00,0x01,0x00,0x50,0x45,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x51,0x43,0x78,0x0c,0x00,0x00,0x01,0x00,0x52,0x41,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x53,0x3f,0x78,0x0c,0x00,0x00,0x01,0x00,0x54,0x3d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x55,0x3b,0x78,0x0c,0x00,0x00,0x01,0x00,0x56,0x39,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x57,0x37,0x78,0x0c,0x00,0x00,0x01,0x00,0x58,0x35,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x59,0x33,0x78,0x0c,0x00,0x00,0x01,0x00,0x5a,0x31,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x5b,0x2f,0x78,0x0c,0x00,0x00,0x01,0x00,0x5c,0x2d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x5d,0x2b,0x78,0x0c,0x00,0x00,0x01,0x00,0x5e,0x29,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x5f,0x27,0x78,0x0c,0x00,0x00,0x01,0x00,0x60,0x25,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x61,0x23,0x78,0x0c,0x00,0x00,0x01,0x00,0x62,0x21,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x63,0x1f,0x78,0x0c,0x00,0x00,0x01,0x00,0x64,0x1d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x65,0x1b,0x78,0x0c,0x00,0x00,0x01,0x00,0x66,0x19,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x67,0x17,0x78,0x0c,0x00,0x00,0x01,0x00,0x68,0x15,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x69,0x13,0x78,0x0c,0x00,0x00,0x01,0x00,0x6a,0x11,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x6b,0x0f,0x78,0x0c,0x00,0x00,0x01,0x00,0x6c,0x0d,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x6d,0x0b,0x78,0x0c,0x00,0x00,0x01,0x00,0x6e,0x09,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x6f,0x07,0x78,0x0c,0x00,0x00,0x01,0x00,0x70,0x05,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x71,0x03,0x78,0x0c,0x00,0x00,0x01,0x00,0x72,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x73,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x74,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x75,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x76,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x77,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x78,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x79,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7a,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x7b,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7c,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x7d,0x01,0x78,0x0c,0x00,0x00,0x01,0x00,0x7e,0x01,0x78,0x0c,0x00,0x00,
-0x01,0x00,0x7f,0x01,0x78,0x0c,0x00,0x00,0x1e,0x00,0x00,0x30,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x01,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x02,0x30,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x03,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x04,0x30,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x05,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x06,0x30,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x07,0x30,0x78,0x0c,0x00,0x00,0x1e,0x00,0x08,0x3e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x09,0x40,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0a,0x42,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x0b,0x44,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0c,0x46,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x0d,0x48,0x78,0x0c,0x00,0x00,0x1e,0x00,0x0e,0x48,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x0f,0x4a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x10,0x4a,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x11,0x4c,0x78,0x0c,0x00,0x00,0x1e,0x00,0x12,0x4c,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x13,0x4e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x14,0x50,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x15,0x50,0x78,0x0c,0x00,0x00,0x1e,0x00,0x16,0x50,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x17,0x52,0x78,0x0c,0x00,0x00,0x1e,0x00,0x18,0x52,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x19,0x52,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1a,0x54,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x1b,0x54,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1c,0x54,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x1d,0x56,0x78,0x0c,0x00,0x00,0x1e,0x00,0x1e,0x56,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x1f,0x56,0x78,0x0c,0x00,0x00,0x1e,0x00,0x20,0x56,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x21,0x58,0x78,0x0c,0x00,0x00,0x1e,0x00,0x22,0x58,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x23,0x58,0x78,0x0c,0x00,0x00,0x1e,0x00,0x24,0x58,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x25,0x5a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x26,0x5a,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x27,0x5a,0x78,0x0c,0x00,0x00,0x1e,0x00,0x28,0x5c,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x29,0x5c,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2a,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x2b,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2c,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x2d,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x2e,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x2f,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x30,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x31,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x32,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x33,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x34,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x35,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x36,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x37,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x38,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x39,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3a,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x3b,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3c,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x3d,0x5e,0x78,0x0c,0x00,0x00,0x1e,0x00,0x3e,0x5e,0x78,0x0c,0x00,0x00,
-0x1e,0x00,0x3f,0x5e,0xff,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x08,0x00,0x00,
-0x00,0x00,0x04,0x03,0x04,0x08,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x08,0x00,0x00,
-0x00,0xfc,0x00,0x00,0x0c,0x08,0x00,0x00,0x0a,0x00,0x00,0x04,0x10,0x08,0x00,0x00,
-0xff,0x10,0x10,0x80,0x14,0x08,0x00,0x00,0x10,0x3d,0x0c,0x02,0x18,0x08,0x00,0x00,
-0xc5,0x03,0x00,0x00,0x1c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x08,0x00,0x00,
-0x04,0x00,0x00,0x00,0x24,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x28,0x08,0x00,0x00,
-0x04,0x00,0x00,0x00,0x2c,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x30,0x08,0x00,0x00,
-0x04,0x00,0x00,0x00,0x34,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x38,0x08,0x00,0x00,
-0x04,0x00,0x00,0x00,0x3c,0x08,0x00,0x00,0x00,0x02,0x69,0x00,0x40,0x08,0x00,0x00,
-0x00,0x00,0x00,0x00,0x44,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x08,0x00,0x00,
-0x00,0x00,0x00,0x00,0x4c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x50,0x08,0x00,0x00,
-0x00,0x00,0x00,0x00,0x54,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x08,0x00,0x00,
-0x65,0xa9,0x65,0xa9,0x5c,0x08,0x00,0x00,0x65,0xa9,0x65,0xa9,0x60,0x08,0x00,0x00,
-0x30,0x01,0x7f,0x0f,0x64,0x08,0x00,0x00,0x30,0x01,0x7f,0x0f,0x68,0x08,0x00,0x00,
-0x30,0x01,0x7f,0x0f,0x6c,0x08,0x00,0x00,0x30,0x01,0x7f,0x0f,0x70,0x08,0x00,0x00,
-0x00,0x03,0x00,0x03,0x74,0x08,0x00,0x00,0x00,0x03,0x00,0x03,0x78,0x08,0x00,0x00,
-0x00,0x00,0x00,0x00,0x7c,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x08,0x00,0x00,
-0x00,0x00,0x00,0x00,0x94,0x08,0x00,0x00,0xfe,0xff,0xff,0xff,0x98,0x08,0x00,0x00,
-0x10,0x20,0x30,0x40,0x9c,0x08,0x00,0x00,0x50,0x60,0x70,0x00,0xb0,0x08,0x00,0x00,
-0x00,0x00,0x00,0x00,0xe0,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x08,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x04,0x0e,0x00,0x00,
-0x03,0x03,0x03,0x03,0x08,0x0e,0x00,0x00,0x03,0x03,0x00,0x00,0x0c,0x0e,0x00,0x00,
-0x00,0x00,0x00,0x00,0x10,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x14,0x0e,0x00,0x00,
-0x03,0x03,0x03,0x03,0x18,0x0e,0x00,0x00,0x03,0x03,0x03,0x03,0x1c,0x0e,0x00,0x00,
-0x03,0x03,0x03,0x03,0x00,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x09,0x00,0x00,
-0x23,0x00,0x00,0x00,0x08,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x09,0x00,0x00,
-0x33,0x13,0x32,0x03,0x08,0x0a,0x00,0x00,0x00,0x86,0x88,0x8f,0x2c,0x0a,0x00,0x00,
-0x00,0x00,0x92,0x00,0x00,0x0c,0x00,0x00,0x80,0x00,0x00,0x00,0x04,0x0c,0x00,0x00,
-0x33,0x54,0x00,0x00,0x08,0x0c,0x00,0x00,0xe4,0x00,0x00,0x00,0x0c,0x0c,0x00,0x00,
-0x6c,0x6c,0x6c,0x6c,0x10,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x14,0x0c,0x00,0x00,
-0x00,0x01,0x00,0x40,0x18,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x1c,0x0c,0x00,0x00,
-0x00,0x01,0x00,0x40,0x20,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x24,0x0c,0x00,0x00,
-0x00,0x01,0x00,0x40,0x28,0x0c,0x00,0x00,0x00,0x00,0x00,0x08,0x2c,0x0c,0x00,0x00,
-0x00,0x01,0x00,0x40,0x30,0x0c,0x00,0x00,0x44,0x6a,0xe9,0x8d,0x34,0x0c,0x00,0x00,
-0xcd,0x52,0x96,0x46,0x38,0x0c,0x00,0x00,0x90,0x5a,0x01,0x48,0x3c,0x0c,0x00,0x00,
-0x64,0x97,0x97,0x1a,0x40,0x0c,0x00,0x00,0x3f,0x42,0x7c,0x1f,0x44,0x0c,0x00,0x00,
-0xb7,0x00,0x01,0x00,0x48,0x0c,0x00,0x00,0x00,0x00,0x02,0xec,0x4c,0x0c,0x00,0x00,
-0x03,0x03,0xfc,0x00,0x50,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x54,0x0c,0x00,0x00,
-0x94,0x00,0x3c,0x43,0x58,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x5c,0x0c,0x00,0x00,
-0x94,0x00,0x3c,0x43,0x60,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x64,0x0c,0x00,0x00,
-0x94,0x00,0x3c,0x43,0x68,0x0c,0x00,0x00,0x1c,0x34,0x54,0x69,0x6c,0x0c,0x00,0x00,
-0x94,0x00,0x3c,0x43,0x70,0x0c,0x00,0x00,0x0d,0x00,0x5a,0x2c,0x74,0x0c,0x00,0x00,
-0x1b,0x15,0x86,0x01,0x78,0x0c,0x00,0x00,0x1f,0x00,0x00,0x00,0x7c,0x0c,0x00,0x00,
-0x12,0x16,0xb9,0x00,0x80,0x0c,0x00,0x00,0x80,0x00,0x00,0x20,0x84,0x0c,0x00,0x00,
-0x00,0x00,0x00,0x00,0x88,0x0c,0x00,0x00,0x80,0x00,0x00,0x20,0x8c,0x0c,0x00,0x00,
-0x00,0x00,0x20,0x08,0x90,0x0c,0x00,0x00,0x00,0x01,0x00,0x40,0x94,0x0c,0x00,0x00,
-0x00,0x00,0x00,0x00,0x98,0x0c,0x00,0x00,0x00,0x01,0x00,0x40,0x9c,0x0c,0x00,0x00,
-0x00,0x00,0x00,0x00,0xa0,0x0c,0x00,0x00,0x92,0x24,0x49,0x00,0xa4,0x0c,0x00,0x00,
-0x00,0x00,0x00,0x00,0xa8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x0c,0x00,0x00,
-0x00,0x00,0x00,0x00,0xb0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xb4,0x0c,0x00,0x00,
-0x00,0x00,0x00,0x00,0xb8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xbc,0x0c,0x00,0x00,
-0x92,0x24,0x49,0x00,0xc0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xc4,0x0c,0x00,0x00,
-0x00,0x00,0x00,0x00,0xc8,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xcc,0x0c,0x00,0x00,
-0x00,0x00,0x00,0x00,0xd0,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0xd4,0x0c,0x00,0x00,
-0x00,0x00,0x00,0x00,0xd8,0x0c,0x00,0x00,0x27,0x24,0xb2,0x64,0xdc,0x0c,0x00,0x00,
-0x32,0x69,0x76,0x00,0xe0,0x0c,0x00,0x00,0x22,0x22,0x22,0x00,0xe4,0x0c,0x00,0x00,
-0x00,0x00,0x00,0x00,0xe8,0x0c,0x00,0x00,0x02,0x43,0x64,0x07,0x00,0x0d,0x00,0x00,
-0x80,0x07,0x00,0x00,0x04,0x0d,0x00,0x00,0x03,0x04,0x00,0x00,0x08,0x0d,0x00,0x00,
-0x7f,0x90,0x00,0x00,0x0c,0x0d,0x00,0x00,0x01,0x00,0x00,0x00,0x10,0x0d,0x00,0x00,
-0x99,0x99,0x69,0xa0,0x14,0x0d,0x00,0x00,0x67,0x3c,0x99,0x99,0x18,0x0d,0x00,0x00,
-0x6b,0x5b,0x8f,0x6a,0x1c,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x0d,0x00,0x00,
-0x00,0x00,0x00,0x00,0x24,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x0d,0x00,0x00,
-0x00,0x00,0x00,0x00,0x2c,0x0d,0x00,0x00,0x75,0x19,0x97,0xcc,0x30,0x0d,0x00,0x00,
-0x00,0x00,0x00,0x00,0x34,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x0d,0x00,0x00,
-0x00,0x00,0x00,0x00,0x3c,0x0d,0x00,0x00,0x93,0x72,0x02,0x00,0x40,0x0d,0x00,0x00,
-0x00,0x00,0x00,0x00,0x44,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x0d,0x00,0x00,
-0x00,0x00,0x00,0x00,0x50,0x0d,0x00,0x00,0x0a,0x14,0x37,0x64,0x54,0x0d,0x00,0x00,
-0x02,0xbd,0x4d,0x02,0x58,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x5c,0x0d,0x00,0x00,
-0x64,0x20,0x03,0x30,0x60,0x0d,0x00,0x00,0x68,0xde,0x53,0x46,0x64,0x0d,0x00,0x00,
-0x3c,0x8a,0x51,0x00,0x68,0x0d,0x00,0x00,0x06,0x01,0x00,0x00,0xff,0x00,0x00,0x00,
-0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
-0x44,0x05,0x01,0x80,0x10,0x00,0x00,0x00,0x74,0x05,0x01,0x80,0x10,0x00,0x00,0x00,
-0xe0,0x2e,0x00,0x80,0x10,0x00,0x00,0x00,0xec,0x2e,0x00,0x80,0x10,0x00,0x00,0x00,
-0xa0,0x08,0x01,0x80,0x08,0x00,0x00,0x00,0x38,0x06,0x01,0x80,0x00,0xb7,0x00,0x00,
-0x01,0xe0,0x0e,0x00,0x02,0x4d,0x04,0x00,0x03,0x41,0x04,0x00,0x04,0xc3,0x08,0x00,
-0x05,0x72,0x0c,0x00,0x06,0xe6,0x00,0x00,0x07,0x2a,0x08,0x00,0x08,0x3f,0x00,0x00,
-0x09,0x35,0x03,0x00,0x0a,0xd4,0x09,0x00,0x0b,0xbb,0x07,0x00,0x0c,0x50,0x08,0x00,
-0x0d,0xdf,0x0c,0x00,0x0e,0x2b,0x00,0x00,0x0f,0x14,0x01,0x00,0x00,0xb7,0x01,0x00,
-0x01,0x01,0x00,0x00,0x02,0x00,0x04,0x00,0x01,0x02,0x00,0x00,0x02,0x01,0x04,0x00,
-0x01,0x03,0x00,0x00,0x02,0x02,0x04,0x00,0x01,0x04,0x00,0x00,0x02,0x03,0x04,0x00,
-0x01,0x05,0x00,0x00,0x02,0x04,0x04,0x00,0x01,0x06,0x00,0x00,0x02,0x05,0x04,0x00,
-0x01,0x07,0x00,0x00,0x02,0x08,0x04,0x00,0x01,0x08,0x00,0x00,0x02,0x09,0x04,0x00,
-0x01,0x09,0x00,0x00,0x02,0x0a,0x04,0x00,0x01,0x0a,0x00,0x00,0x02,0x0b,0x04,0x00,
-0x01,0x0b,0x00,0x00,0x02,0x02,0x05,0x00,0x01,0x0c,0x00,0x00,0x02,0x03,0x05,0x00,
-0x01,0x0d,0x00,0x00,0x02,0x04,0x05,0x00,0x01,0x0e,0x00,0x00,0x02,0x05,0x05,0x00,
-0x01,0x0f,0x00,0x00,0x02,0x40,0x05,0x00,0x01,0x10,0x00,0x00,0x02,0x41,0x05,0x00,
-0x01,0x11,0x00,0x00,0x02,0x42,0x05,0x00,0x01,0x12,0x00,0x00,0x02,0x43,0x05,0x00,
-0x01,0x13,0x00,0x00,0x02,0x44,0x05,0x00,0x01,0x14,0x00,0x00,0x02,0x45,0x05,0x00,
-0x01,0x15,0x00,0x00,0x02,0x80,0x05,0x00,0x01,0x16,0x00,0x00,0x02,0x81,0x05,0x00,
-0x01,0x17,0x00,0x00,0x02,0x82,0x05,0x00,0x01,0x18,0x00,0x00,0x02,0x83,0x05,0x00,
-0x01,0x19,0x00,0x00,0x02,0x84,0x05,0x00,0x01,0x1a,0x00,0x00,0x02,0x85,0x05,0x00,
-0x01,0x1b,0x00,0x00,0x02,0x88,0x05,0x00,0x01,0x1c,0x00,0x00,0x02,0x89,0x05,0x00,
-0x01,0x1d,0x00,0x00,0x02,0x8a,0x05,0x00,0x01,0x1e,0x00,0x00,0x02,0x8b,0x05,0x00,
-0x01,0x1f,0x00,0x00,0x02,0x43,0x06,0x00,0x01,0x20,0x00,0x00,0x02,0x44,0x06,0x00,
-0x01,0x21,0x00,0x00,0x02,0x45,0x06,0x00,0x01,0x22,0x00,0x00,0x02,0x80,0x06,0x00,
-0x01,0x23,0x00,0x00,0x02,0x81,0x06,0x00,0x01,0x24,0x00,0x00,0x02,0x82,0x06,0x00,
-0x01,0x25,0x00,0x00,0x02,0x83,0x06,0x00,0x01,0x26,0x00,0x00,0x02,0x84,0x06,0x00,
-0x01,0x27,0x00,0x00,0x02,0x85,0x06,0x00,0x01,0x28,0x00,0x00,0x02,0x88,0x06,0x00,
-0x01,0x29,0x00,0x00,0x02,0x89,0x06,0x00,0x01,0x2a,0x00,0x00,0x02,0x8a,0x06,0x00,
-0x01,0x2b,0x00,0x00,0x02,0x8b,0x06,0x00,0x01,0x2c,0x00,0x00,0x02,0x8c,0x06,0x00,
-0x01,0x2d,0x00,0x00,0x02,0x42,0x07,0x00,0x01,0x2e,0x00,0x00,0x02,0x43,0x07,0x00,
-0x01,0x2f,0x00,0x00,0x02,0x44,0x07,0x00,0x01,0x30,0x00,0x00,0x02,0x45,0x07,0x00,
-0x01,0x31,0x00,0x00,0x02,0x80,0x07,0x00,0x01,0x32,0x00,0x00,0x02,0x81,0x07,0x00,
-0x01,0x33,0x00,0x00,0x02,0x82,0x07,0x00,0x01,0x34,0x00,0x00,0x02,0x83,0x07,0x00,
-0x01,0x35,0x00,0x00,0x02,0x84,0x07,0x00,0x01,0x36,0x00,0x00,0x02,0x85,0x07,0x00,
-0x01,0x37,0x00,0x00,0x02,0x88,0x07,0x00,0x01,0x38,0x00,0x00,0x02,0x89,0x07,0x00,
-0x01,0x39,0x00,0x00,0x02,0x8a,0x07,0x00,0x01,0x3a,0x00,0x00,0x02,0x8b,0x07,0x00,
-0x01,0x3b,0x00,0x00,0x02,0x8c,0x07,0x00,0x01,0x3c,0x00,0x00,0x02,0x8d,0x07,0x00,
-0x01,0x3d,0x00,0x00,0x02,0x90,0x07,0x00,0x01,0x3e,0x00,0x00,0x02,0x91,0x07,0x00,
-0x01,0x3f,0x00,0x00,0x02,0x92,0x07,0x00,0x01,0x40,0x00,0x00,0x02,0x93,0x07,0x00,
-0x01,0x41,0x00,0x00,0x02,0x94,0x07,0x00,0x01,0x42,0x00,0x00,0x02,0x95,0x07,0x00,
-0x01,0x43,0x00,0x00,0x02,0x98,0x07,0x00,0x01,0x44,0x00,0x00,0x02,0x99,0x07,0x00,
-0x01,0x45,0x00,0x00,0x02,0x9a,0x07,0x00,0x01,0x46,0x00,0x00,0x02,0x9b,0x07,0x00,
-0x01,0x47,0x00,0x00,0x02,0x9c,0x07,0x00,0x01,0x48,0x00,0x00,0x02,0x9d,0x07,0x00,
-0x01,0x49,0x00,0x00,0x02,0xa0,0x07,0x00,0x01,0x4a,0x00,0x00,0x02,0xa1,0x07,0x00,
-0x01,0x4b,0x00,0x00,0x02,0xa2,0x07,0x00,0x01,0x4c,0x00,0x00,0x02,0xa3,0x07,0x00,
-0x01,0x4d,0x00,0x00,0x02,0xa4,0x07,0x00,0x01,0x4e,0x00,0x00,0x02,0xa5,0x07,0x00,
-0x01,0x4f,0x00,0x00,0x02,0xa8,0x07,0x00,0x01,0x50,0x00,0x00,0x02,0xa9,0x07,0x00,
-0x01,0x51,0x00,0x00,0x02,0xaa,0x03,0x00,0x01,0x52,0x00,0x00,0x02,0xab,0x03,0x00,
-0x01,0x53,0x00,0x00,0x02,0xac,0x03,0x00,0x01,0x54,0x00,0x00,0x02,0xad,0x03,0x00,
-0x01,0x55,0x00,0x00,0x02,0xb0,0x03,0x00,0x01,0x56,0x00,0x00,0x02,0xb1,0x03,0x00,
-0x01,0x57,0x00,0x00,0x02,0xb2,0x03,0x00,0x01,0x58,0x00,0x00,0x02,0xb3,0x03,0x00,
-0x01,0x59,0x00,0x00,0x02,0xb4,0x03,0x00,0x01,0x5a,0x00,0x00,0x02,0xb5,0x03,0x00,
-0x01,0x5b,0x00,0x00,0x02,0xb8,0x03,0x00,0x01,0x5c,0x00,0x00,0x02,0xb9,0x03,0x00,
-0x01,0x5d,0x00,0x00,0x02,0xba,0x03,0x00,0x01,0x5e,0x00,0x00,0x02,0xbb,0x03,0x00,
-0x01,0x5f,0x00,0x00,0x02,0xbb,0x03,0x00,0x03,0x80,0x00,0x00,0x05,0x04,0x00,0x00,
-0x00,0xb7,0x00,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,
-0x02,0x4d,0x0c,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x02,0x4d,0x04,0x00,
-0x00,0xbf,0x02,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0xb7,0x00,0x00,
-0x01,0xe0,0x0e,0x00,0x02,0x4d,0x04,0x00,0x03,0x41,0x04,0x00,0x04,0xc3,0x08,0x00,
-0x05,0x72,0x0c,0x00,0x06,0xe6,0x00,0x00,0x07,0x2a,0x08,0x00,0x08,0x3f,0x00,0x00,
-0x09,0x35,0x03,0x00,0x0a,0xd4,0x09,0x00,0x0b,0xbb,0x07,0x00,0x0c,0x50,0x08,0x00,
-0x0d,0xdf,0x0c,0x00,0x0e,0x2b,0x00,0x00,0x0f,0x14,0x01,0x00,0x00,0xb7,0x01,0x00,
-0x01,0x01,0x00,0x00,0x02,0x00,0x04,0x00,0x01,0x02,0x00,0x00,0x02,0x01,0x04,0x00,
-0x01,0x03,0x00,0x00,0x02,0x02,0x04,0x00,0x01,0x04,0x00,0x00,0x02,0x03,0x04,0x00,
-0x01,0x05,0x00,0x00,0x02,0x04,0x04,0x00,0x01,0x06,0x00,0x00,0x02,0x05,0x04,0x00,
-0x01,0x07,0x00,0x00,0x02,0x08,0x04,0x00,0x01,0x08,0x00,0x00,0x02,0x09,0x04,0x00,
-0x01,0x09,0x00,0x00,0x02,0x0a,0x04,0x00,0x01,0x0a,0x00,0x00,0x02,0x0b,0x04,0x00,
-0x01,0x0b,0x00,0x00,0x02,0x02,0x05,0x00,0x01,0x0c,0x00,0x00,0x02,0x03,0x05,0x00,
-0x01,0x0d,0x00,0x00,0x02,0x04,0x05,0x00,0x01,0x0e,0x00,0x00,0x02,0x05,0x05,0x00,
-0x01,0x0f,0x00,0x00,0x02,0x40,0x05,0x00,0x01,0x10,0x00,0x00,0x02,0x41,0x05,0x00,
-0x01,0x11,0x00,0x00,0x02,0x42,0x05,0x00,0x01,0x12,0x00,0x00,0x02,0x43,0x05,0x00,
-0x01,0x13,0x00,0x00,0x02,0x44,0x05,0x00,0x01,0x14,0x00,0x00,0x02,0x45,0x05,0x00,
-0x01,0x15,0x00,0x00,0x02,0x80,0x05,0x00,0x01,0x16,0x00,0x00,0x02,0x81,0x05,0x00,
-0x01,0x17,0x00,0x00,0x02,0x82,0x05,0x00,0x01,0x18,0x00,0x00,0x02,0x83,0x05,0x00,
-0x01,0x19,0x00,0x00,0x02,0x84,0x05,0x00,0x01,0x1a,0x00,0x00,0x02,0x85,0x05,0x00,
-0x01,0x1b,0x00,0x00,0x02,0x88,0x05,0x00,0x01,0x1c,0x00,0x00,0x02,0x89,0x05,0x00,
-0x01,0x1d,0x00,0x00,0x02,0x8a,0x05,0x00,0x01,0x1e,0x00,0x00,0x02,0x8b,0x05,0x00,
-0x01,0x1f,0x00,0x00,0x02,0x43,0x06,0x00,0x01,0x20,0x00,0x00,0x02,0x44,0x06,0x00,
-0x01,0x21,0x00,0x00,0x02,0x45,0x06,0x00,0x01,0x22,0x00,0x00,0x02,0x80,0x06,0x00,
-0x01,0x23,0x00,0x00,0x02,0x81,0x06,0x00,0x01,0x24,0x00,0x00,0x02,0x82,0x06,0x00,
-0x01,0x25,0x00,0x00,0x02,0x83,0x06,0x00,0x01,0x26,0x00,0x00,0x02,0x84,0x06,0x00,
-0x01,0x27,0x00,0x00,0x02,0x85,0x06,0x00,0x01,0x28,0x00,0x00,0x02,0x88,0x06,0x00,
-0x01,0x29,0x00,0x00,0x02,0x89,0x06,0x00,0x01,0x2a,0x00,0x00,0x02,0x8a,0x06,0x00,
-0x01,0x2b,0x00,0x00,0x02,0x8b,0x06,0x00,0x01,0x2c,0x00,0x00,0x02,0x8c,0x06,0x00,
-0x01,0x2d,0x00,0x00,0x02,0x42,0x07,0x00,0x01,0x2e,0x00,0x00,0x02,0x43,0x07,0x00,
-0x01,0x2f,0x00,0x00,0x02,0x44,0x07,0x00,0x01,0x30,0x00,0x00,0x02,0x45,0x07,0x00,
-0x01,0x31,0x00,0x00,0x02,0x80,0x07,0x00,0x01,0x32,0x00,0x00,0x02,0x81,0x07,0x00,
-0x01,0x33,0x00,0x00,0x02,0x82,0x07,0x00,0x01,0x34,0x00,0x00,0x02,0x83,0x07,0x00,
-0x01,0x35,0x00,0x00,0x02,0x84,0x07,0x00,0x01,0x36,0x00,0x00,0x02,0x85,0x07,0x00,
-0x01,0x37,0x00,0x00,0x02,0x88,0x07,0x00,0x01,0x38,0x00,0x00,0x02,0x89,0x07,0x00,
-0x01,0x39,0x00,0x00,0x02,0x8a,0x07,0x00,0x01,0x3a,0x00,0x00,0x02,0x8b,0x07,0x00,
-0x01,0x3b,0x00,0x00,0x02,0x8c,0x07,0x00,0x01,0x3c,0x00,0x00,0x02,0x8d,0x07,0x00,
-0x01,0x3d,0x00,0x00,0x02,0x90,0x07,0x00,0x01,0x3e,0x00,0x00,0x02,0x91,0x07,0x00,
-0x01,0x3f,0x00,0x00,0x02,0x92,0x07,0x00,0x01,0x40,0x00,0x00,0x02,0x93,0x07,0x00,
-0x01,0x41,0x00,0x00,0x02,0x94,0x07,0x00,0x01,0x42,0x00,0x00,0x02,0x95,0x07,0x00,
-0x01,0x43,0x00,0x00,0x02,0x98,0x07,0x00,0x01,0x44,0x00,0x00,0x02,0x99,0x07,0x00,
-0x01,0x45,0x00,0x00,0x02,0x9a,0x07,0x00,0x01,0x46,0x00,0x00,0x02,0x9b,0x07,0x00,
-0x01,0x47,0x00,0x00,0x02,0x9c,0x07,0x00,0x01,0x48,0x00,0x00,0x02,0x9d,0x07,0x00,
-0x01,0x49,0x00,0x00,0x02,0xa0,0x07,0x00,0x01,0x4a,0x00,0x00,0x02,0xa1,0x07,0x00,
-0x01,0x4b,0x00,0x00,0x02,0xa2,0x07,0x00,0x01,0x4c,0x00,0x00,0x02,0xa3,0x07,0x00,
-0x01,0x4d,0x00,0x00,0x02,0xa4,0x07,0x00,0x01,0x4e,0x00,0x00,0x02,0xa5,0x07,0x00,
-0x01,0x4f,0x00,0x00,0x02,0xa8,0x07,0x00,0x01,0x50,0x00,0x00,0x02,0xa9,0x07,0x00,
-0x01,0x51,0x00,0x00,0x02,0xaa,0x03,0x00,0x01,0x52,0x00,0x00,0x02,0xab,0x03,0x00,
-0x01,0x53,0x00,0x00,0x02,0xac,0x03,0x00,0x01,0x54,0x00,0x00,0x02,0xad,0x03,0x00,
-0x01,0x55,0x00,0x00,0x02,0xb0,0x03,0x00,0x01,0x56,0x00,0x00,0x02,0xb1,0x03,0x00,
-0x01,0x57,0x00,0x00,0x02,0xb2,0x03,0x00,0x01,0x58,0x00,0x00,0x02,0xb3,0x03,0x00,
-0x01,0x59,0x00,0x00,0x02,0xb4,0x03,0x00,0x01,0x5a,0x00,0x00,0x02,0xb5,0x03,0x00,
-0x01,0x5b,0x00,0x00,0x02,0xb8,0x03,0x00,0x01,0x5c,0x00,0x00,0x02,0xb9,0x03,0x00,
-0x01,0x5d,0x00,0x00,0x02,0xba,0x03,0x00,0x01,0x5e,0x00,0x00,0x02,0xbb,0x03,0x00,
-0x01,0x5f,0x00,0x00,0x02,0xbb,0x03,0x00,0x03,0x80,0x00,0x00,0x05,0x04,0x00,0x00,
-0x00,0xb7,0x00,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,
-0x02,0x4d,0x0c,0x00,0xfe,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x02,0x4d,0x04,0x00,
-0x00,0xbf,0x02,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x0a,0x00,0x00,0x00,
-0x4f,0x6e,0x41,0x73,0x73,0x6f,0x63,0x52,0x65,0x71,0x00,0x00,0x4f,0x6e,0x41,0x73,
-0x73,0x6f,0x63,0x52,0x73,0x70,0x00,0x00,0x4f,0x6e,0x52,0x65,0x41,0x73,0x73,0x6f,
-0x63,0x52,0x65,0x71,0x00,0x00,0x00,0x00,0x4f,0x6e,0x52,0x65,0x41,0x73,0x73,0x6f,
-0x63,0x52,0x73,0x70,0x00,0x00,0x00,0x00,0x4f,0x6e,0x50,0x72,0x6f,0x62,0x65,0x52,
-0x65,0x71,0x00,0x00,0x4f,0x6e,0x50,0x72,0x6f,0x62,0x65,0x52,0x73,0x70,0x00,0x00,
-0x44,0x6f,0x52,0x65,0x73,0x65,0x72,0x76,0x65,0x64,0x00,0x00,0x44,0x6f,0x52,0x65,
-0x73,0x65,0x72,0x76,0x65,0x64,0x00,0x00,0x4f,0x6e,0x42,0x65,0x61,0x63,0x6f,0x6e,
-0x00,0x00,0x00,0x00,0x4f,0x6e,0x41,0x54,0x49,0x4d,0x00,0x00,0x4f,0x6e,0x44,0x69,
-0x73,0x61,0x73,0x73,0x6f,0x63,0x00,0x00,0x4f,0x6e,0x41,0x75,0x74,0x68,0x00,0x00,
-0x4f,0x6e,0x44,0x65,0x41,0x75,0x74,0x68,0x00,0x00,0x00,0x00,0x4f,0x6e,0x41,0x63,
-0x74,0x69,0x6f,0x6e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x8b,0x01,0x80,
-0x28,0x14,0x01,0x80,0x10,0x00,0x00,0x00,0x94,0x8b,0x01,0x80,0x30,0x14,0x01,0x80,
-0x20,0x00,0x00,0x00,0xa0,0x8b,0x01,0x80,0x28,0x14,0x01,0x80,0x30,0x00,0x00,0x00,
-0xb0,0x8b,0x01,0x80,0x30,0x14,0x01,0x80,0x40,0x00,0x00,0x00,0xc0,0x8b,0x01,0x80,
-0x38,0x14,0x01,0x80,0x50,0x00,0x00,0x00,0xcc,0x8b,0x01,0x80,0x40,0x14,0x01,0x80,
-0x00,0x00,0x00,0x00,0xd8,0x8b,0x01,0x80,0xa8,0x14,0x01,0x80,0x00,0x00,0x00,0x00,
-0xe4,0x8b,0x01,0x80,0xa8,0x14,0x01,0x80,0x80,0x00,0x00,0x00,0xf0,0x8b,0x01,0x80,
-0x48,0x14,0x01,0x80,0x90,0x00,0x00,0x00,0xfc,0x8b,0x01,0x80,0x50,0x14,0x01,0x80,
-0xa0,0x00,0x00,0x00,0x04,0x8c,0x01,0x80,0x58,0x14,0x01,0x80,0xb0,0x00,0x00,0x00,
-0x10,0x8c,0x01,0x80,0x90,0x14,0x01,0x80,0xc0,0x00,0x00,0x00,0x18,0x8c,0x01,0x80,
-0x98,0x14,0x01,0x80,0xd0,0x00,0x00,0x00,0x24,0x8c,0x01,0x80,0xa0,0x14,0x01,0x80,
-0x00,0x00,0x00,0x00,0xdc,0x8c,0x01,0x80,0xdc,0x8c,0x01,0x80,0x31,0x10,0x10,0x00,
-0x00,0x30,0x00,0x00,0x31,0x20,0x10,0x00,0x00,0x30,0x00,0x00,0x31,0x28,0x10,0x00,
-0x00,0x30,0x00,0x00,0x31,0x2c,0x10,0x10,0x00,0x30,0x00,0x00,0x31,0x2f,0x10,0x10,
-0x00,0x30,0x00,0x00,0x31,0x30,0x18,0x00,0x00,0x30,0x00,0x00,0x31,0x30,0x20,0x10,
-0x00,0x30,0x00,0x00,0x22,0x20,0x18,0x08,0x00,0x20,0x00,0x00,0x22,0x21,0x14,0x08,
-0x00,0x20,0x00,0x00,0x22,0x21,0x1c,0x08,0x00,0x20,0x00,0x00,0x22,0x21,0x20,0x08,
-0x00,0x20,0x00,0x00,0x22,0x21,0x20,0x10,0x00,0x20,0x00,0x00,0x22,0x21,0x20,0x18,
-0x00,0x20,0x00,0x00,0x1a,0x19,0x18,0x10,0x00,0x18,0x00,0x00,0x12,0x11,0x10,0x08,
-0x00,0x10,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x08,0x00,0x00,0x0a,0x09,0x08,0x02,
-0x00,0x08,0x00,0x00,0x0a,0x09,0x08,0x04,0x00,0x08,0x00,0x00,0x0a,0x09,0x08,0x06,
-0x00,0x08,0x00,0x00,0x08,0x07,0x06,0x04,0x00,0x06,0x00,0x00,0x06,0x05,0x04,0x02,
-0x00,0x04,0x00,0x00,0x06,0x05,0x04,0x03,0x00,0x04,0x00,0x00,0x05,0x04,0x03,0x02,
-0x00,0x03,0x00,0x00,0x09,0x08,0x07,0x06,0x07,0x06,0x06,0x05,0x05,0x04,0x04,0x03,
-0x06,0x05,0x05,0x04,0x04,0x03,0x03,0x03,0x05,0x04,0x04,0x03,0x03,0x02,0x02,0x02,
-0x00,0x09,0x08,0x07,0x06,0x07,0x06,0x06,0x05,0x05,0x04,0x04,0x03,0x05,0x04,0x04,
-0x03,0x03,0x02,0x02,0x02,0x04,0x03,0x03,0x02,0x02,0x01,0x01,0x01,0x00,0x00,0x00,
-0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x08,0x08,0x08,0x08,
-0x20,0x20,0x20,0x20,0x08,0x08,0x08,0x08,0x08,0x20,0x20,0x20,0x30,0x08,0x08,0x08,
-0x08,0x18,0x18,0x18,0x18,0x18,0x20,0x30,0x30,0x10,0x20,0x20,0x20,0x20,0x20,0x30,
-0x30,0x08,0x10,0x20,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x08,0x08,0x08,0x08,
-0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x08,0x08,0x08,0x08,0x08,0x20,0x20,0x20,
-0x08,0x08,0x08,0x08,0x08,0x20,0x20,0x20,0x20,0x08,0x08,0x08,0x08,0x18,0x18,0x18,
-0x18,0x18,0x20,0x30,0x30,0x10,0x20,0x20,0x20,0x20,0x20,0x30,0x30,0x08,0x10,0x20,
-0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,
-0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x00,
-0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,
-0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x12,0x11,0x10,0x08,0x00,0x22,
-0x21,0x20,0x18,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,
-0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,
-0x18,0x00,0x22,0x21,0x1c,0x08,0x00,0x22,0x20,0x18,0x08,0x00,0x0a,0x09,0x08,0x02,
-0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,
-0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20,0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x22,
-0x21,0x1c,0x08,0x00,0x31,0x30,0x18,0x00,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,
-0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x1a,0x19,0x18,
-0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,
-0x00,0x1a,0x19,0x18,0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x31,0x2c,0x10,0x10,0x00,
-0x31,0x28,0x10,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x22,
-0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x08,0x00,0x22,0x21,0x14,0x08,0x00,0x22,0x20,
-0x18,0x08,0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2c,0x10,0x10,0x00,0x0a,0x09,0x08,
-0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x18,
-0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2f,0x10,0x10,0x00,0x31,0x2f,0x10,0x10,0x00,
-0x31,0x10,0x10,0x00,0x00,0x31,0x2c,0x10,0x10,0x00,0x00,0x00,0x0a,0x09,0x08,0x04,
-0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,
-0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,
-0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x12,0x11,
-0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,
-0x04,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x00,0x00,0x0a,0x09,0x08,0x00,
-0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x1c,0x08,0x00,0x22,0x21,0x14,0x08,0x00,
-0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x02,0x00,0x0a,
-0x09,0x08,0x02,0x00,0x0a,0x09,0x08,0x00,0x00,0x22,0x21,0x20,0x10,0x00,0x22,0x21,
-0x20,0x08,0x00,0x22,0x21,0x14,0x08,0x00,0x22,0x21,0x14,0x08,0x00,0x0a,0x09,0x08,
-0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,0x00,0x0a,0x09,0x08,0x04,
-0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,
-0x1a,0x19,0x18,0x10,0x00,0x1a,0x19,0x18,0x10,0x00,0x22,0x21,0x20,0x08,0x00,0x31,
-0x2c,0x10,0x10,0x00,0x31,0x28,0x10,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,
-0x20,0x18,0x00,0x22,0x21,0x20,0x18,0x00,0x22,0x21,0x20,0x08,0x00,0x22,0x21,0x14,
-0x08,0x00,0x22,0x20,0x18,0x08,0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2c,0x10,0x10,
-0x00,0x0a,0x09,0x08,0x00,0x00,0x12,0x11,0x10,0x08,0x00,0x22,0x21,0x20,0x18,0x00,
-0x22,0x21,0x20,0x18,0x00,0x31,0x30,0x20,0x10,0x00,0x31,0x2f,0x10,0x10,0x00,0x31,
-0x2f,0x10,0x10,0x00,0x31,0x10,0x10,0x00,0x00,0x31,0x2c,0x10,0x10,0x00,0x00,0x00,
-0x01,0x02,0x04,0x08,0x02,0x04,0x08,0x0c,0x10,0x18,0x20,0x30,0x02,0x04,0x08,0x0c,
-0x10,0x18,0x20,0x30,0x06,0x0c,0x10,0x18,0x24,0x30,0x3c,0x48,0x48,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x27,0x2c,0x19,0x1b,0x1e,0x20,
-0x23,0x29,0x2a,0x2b,0x00,0x00,0x00,0x00,0x25,0x29,0x2b,0x2e,0x2e,0x00,0x00,0x00,
-0x04,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x10,0x00,0x00,0x00,
-0x18,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x48,0x00,0x00,0x00,
-0x60,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xd8,0x00,0x00,0x00,
-0x50,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,
-0x40,0x01,0x00,0x00,0x90,0x01,0x00,0x00,0xe0,0x01,0x00,0x00,0x30,0x02,0x00,0x00,
-0x2c,0x01,0x00,0x00,0x40,0x01,0x00,0x00,0xe0,0x01,0x00,0x00,0xd0,0x02,0x00,0x00,
-0x80,0x0c,0x00,0x00,0x80,0x0c,0x00,0x00,0x80,0x0c,0x00,0x00,0xa0,0x0f,0x00,0x00,
-0xa0,0x0f,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
-0x08,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x12,0x00,0x00,0x00,0x18,0x00,0x00,0x00,
-0x24,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x60,0x00,0x00,0x00,
-0x6c,0x00,0x00,0x00,0x28,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x50,0x00,0x00,0x00,
-0x64,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,0xc8,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,
-0x18,0x01,0x00,0x00,0x64,0x00,0x00,0x00,0xa0,0x00,0x00,0x00,0xf0,0x00,0x00,0x00,
-0x68,0x01,0x00,0x00,0x40,0x06,0x00,0x00,0x40,0x06,0x00,0x00,0x40,0x06,0x00,0x00,
-0xd0,0x07,0x00,0x00,0xd0,0x07,0x00,0x00,0x2c,0x05,0x00,0x80,0x20,0x05,0x00,0x80,
-0x14,0x05,0x00,0x80,0x08,0x05,0x00,0x80,0xfc,0x04,0x00,0x80,0xf0,0x04,0x00,0x80,
-0xe4,0x04,0x00,0x80,0xd8,0x04,0x00,0x80,0xcc,0x04,0x00,0x80,0xc0,0x04,0x00,0x80,
-0x78,0x04,0x00,0x80,0x68,0x15,0x02,0x80,0xc0,0x3a,0x00,0x80,0xcc,0x3a,0x00,0x80,
-0xd8,0x3a,0x00,0x80,0xe4,0x3a,0x00,0x80,0xc0,0x3a,0x00,0x80,0xc0,0x3a,0x00,0x80,
-0xc0,0x3a,0x00,0x80,0xc0,0x3a,0x00,0x80,0xf0,0x3a,0x00,0x80,0xfc,0x3a,0x00,0x80,
-0x08,0x3b,0x00,0x80,0x14,0x3b,0x00,0x80,0x68,0x15,0x02,0x80,0xfe,0x01,0x80,0x7f,
-0xe2,0x01,0x80,0x78,0xc7,0x01,0xc0,0x71,0xae,0x01,0x80,0x6b,0x95,0x01,0x40,0x65,
-0x7f,0x01,0xc0,0x5f,0x69,0x01,0x40,0x5a,0x55,0x01,0x40,0x55,0x42,0x01,0x80,0x50,
-0x30,0x01,0x00,0x4c,0x1f,0x01,0xc0,0x47,0x0f,0x01,0xc0,0x43,0x00,0x01,0x00,0x40,
-0xf2,0x00,0x80,0x3c,0xe4,0x00,0x00,0x39,0xd7,0x00,0xc0,0x35,0xcb,0x00,0xc0,0x32,
-0xc0,0x00,0x00,0x30,0xb5,0x00,0x40,0x2d,0xab,0x00,0xc0,0x2a,0xa2,0x00,0x80,0x28,
-0x98,0x00,0x00,0x26,0x90,0x00,0x00,0x24,0x88,0x00,0x00,0x22,0x80,0x00,0x00,0x20,
-0x79,0x00,0x40,0x1e,0x72,0x00,0x80,0x1c,0x6c,0x00,0x00,0x1b,0x66,0x00,0x80,0x19,
-0x60,0x00,0x00,0x18,0x5b,0x00,0xc0,0x16,0x56,0x00,0x80,0x15,0x51,0x00,0x40,0x14,
-0x4c,0x00,0x00,0x13,0x48,0x00,0x00,0x12,0x44,0x00,0x00,0x11,0x40,0x00,0x00,0x10,
-0x36,0x35,0x2e,0x25,0x1c,0x12,0x09,0x04,0x33,0x32,0x2b,0x23,0x1a,0x11,0x08,0x04,
-0x30,0x2f,0x29,0x21,0x19,0x10,0x08,0x03,0x2d,0x2d,0x27,0x1f,0x18,0x0f,0x08,0x03,
-0x2b,0x2a,0x25,0x1e,0x16,0x0e,0x07,0x03,0x28,0x28,0x22,0x1c,0x15,0x0d,0x07,0x03,
-0x26,0x25,0x21,0x1b,0x14,0x0d,0x06,0x03,0x24,0x23,0x1f,0x19,0x13,0x0c,0x06,0x03,
-0x22,0x21,0x1d,0x18,0x11,0x0b,0x06,0x02,0x20,0x20,0x1b,0x16,0x11,0x08,0x05,0x02,
-0x1f,0x1e,0x1a,0x15,0x10,0x0a,0x05,0x02,0x1d,0x1c,0x18,0x14,0x0f,0x0a,0x05,0x02,
-0x1b,0x1a,0x17,0x13,0x0e,0x09,0x04,0x02,0x1a,0x19,0x16,0x12,0x0d,0x09,0x04,0x02,
-0x18,0x17,0x15,0x11,0x0c,0x08,0x04,0x02,0x17,0x16,0x13,0x10,0x0c,0x08,0x04,0x02,
-0x16,0x15,0x12,0x0f,0x0b,0x07,0x04,0x01,0x14,0x14,0x11,0x0e,0x0b,0x07,0x03,0x02,
-0x13,0x13,0x10,0x0d,0x0a,0x06,0x03,0x01,0x12,0x12,0x0f,0x0c,0x09,0x06,0x03,0x01,
-0x11,0x11,0x0f,0x0c,0x09,0x06,0x03,0x01,0x10,0x10,0x0e,0x0b,0x08,0x05,0x03,0x01,
-0x0f,0x0f,0x0d,0x0b,0x08,0x05,0x03,0x01,0x0e,0x0e,0x0c,0x0a,0x08,0x05,0x02,0x01,
-0x0d,0x0d,0x0c,0x0a,0x07,0x05,0x02,0x01,0x0d,0x0c,0x0b,0x09,0x07,0x04,0x02,0x01,
-0x0c,0x0c,0x0a,0x09,0x06,0x04,0x02,0x01,0x0b,0x0b,0x0a,0x08,0x06,0x04,0x02,0x01,
-0x0b,0x0a,0x09,0x08,0x06,0x04,0x02,0x01,0x0a,0x0a,0x09,0x07,0x05,0x03,0x02,0x01,
-0x0a,0x09,0x08,0x07,0x05,0x03,0x02,0x01,0x09,0x09,0x08,0x06,0x05,0x03,0x01,0x01,
-0x09,0x08,0x07,0x06,0x04,0x03,0x01,0x01,0x36,0x35,0x2e,0x1b,0x00,0x00,0x00,0x00,
-0x33,0x32,0x2b,0x19,0x00,0x00,0x00,0x00,0x30,0x2f,0x29,0x18,0x00,0x00,0x00,0x00,
-0x2d,0x2d,0x17,0x17,0x00,0x00,0x00,0x00,0x2b,0x2a,0x25,0x15,0x00,0x00,0x00,0x00,
-0x28,0x28,0x24,0x14,0x00,0x00,0x00,0x00,0x26,0x25,0x21,0x13,0x00,0x00,0x00,0x00,
-0x24,0x23,0x1f,0x12,0x00,0x00,0x00,0x00,0x22,0x21,0x1d,0x11,0x00,0x00,0x00,0x00,
-0x20,0x20,0x1b,0x10,0x00,0x00,0x00,0x00,0x1f,0x1e,0x1a,0x0f,0x00,0x00,0x00,0x00,
-0x1d,0x1c,0x18,0x0e,0x00,0x00,0x00,0x00,0x1b,0x1a,0x17,0x0e,0x00,0x00,0x00,0x00,
-0x1a,0x19,0x16,0x0d,0x00,0x00,0x00,0x00,0x18,0x17,0x15,0x0c,0x00,0x00,0x00,0x00,
-0x17,0x16,0x13,0x0b,0x00,0x00,0x00,0x00,0x16,0x15,0x12,0x0b,0x00,0x00,0x00,0x00,
-0x14,0x14,0x11,0x0a,0x00,0x00,0x00,0x00,0x13,0x13,0x10,0x0a,0x00,0x00,0x00,0x00,
-0x12,0x12,0x0f,0x09,0x00,0x00,0x00,0x00,0x11,0x11,0x0f,0x09,0x00,0x00,0x00,0x00,
-0x10,0x10,0x0e,0x08,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0d,0x08,0x00,0x00,0x00,0x00,
-0x0e,0x0e,0x0c,0x07,0x00,0x00,0x00,0x00,0x0d,0x0d,0x0c,0x07,0x00,0x00,0x00,0x00,
-0x0d,0x0c,0x0b,0x06,0x00,0x00,0x00,0x00,0x0c,0x0c,0x0a,0x06,0x00,0x00,0x00,0x00,
-0x0b,0x0b,0x0a,0x06,0x00,0x00,0x00,0x00,0x0b,0x0a,0x09,0x05,0x00,0x00,0x00,0x00,
-0x0a,0x0a,0x09,0x05,0x00,0x00,0x00,0x00,0x0a,0x09,0x08,0x05,0x00,0x00,0x00,0x00,
-0x09,0x09,0x08,0x05,0x00,0x00,0x00,0x00,0x09,0x08,0x07,0x04,0x00,0x00,0x00,0x00,
-0x06,0x00,0x2a,0xb0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
-0x08,0x28,0x28,0x28,0x28,0x28,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
-0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0xa0,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
-0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
-0x04,0x04,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x41,0x41,0x41,0x41,0x41,0x41,0x01,
-0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
-0x01,0x01,0x01,0x10,0x10,0x10,0x10,0x10,0x10,0x42,0x42,0x42,0x42,0x42,0x42,0x02,
-0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
-0x02,0x02,0x02,0x10,0x10,0x10,0x10,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
-0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
-0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
-0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x10,
-0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
-0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x10,
-0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x19,0x77,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x26,0x72,0xb0,0x00,0x26,0x72,0xb0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-0x00,0x00,0x00,0x00,0x00,0x26,0x65,0x60,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x02,
-0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xf2,0x30,0xb8,0xff,0xff,0xff,0xff,
-};
-
u8 Rtl8192SUFwMainArray[MainArrayLength] = {
0x0, };
diff --git a/drivers/staging/rtl8192su/r8192SU_HWImg.h b/drivers/staging/rtl8192su/r8192SU_HWImg.h
index 96b15252ea8..36e84aff6ed 100644
--- a/drivers/staging/rtl8192su/r8192SU_HWImg.h
+++ b/drivers/staging/rtl8192su/r8192SU_HWImg.h
@@ -5,8 +5,6 @@
/*Created on 2009/ 3/ 6, 5:29*/
-#define ImgArrayLength 68368
-extern u8 Rtl8192SUFwImgArray[ImgArrayLength];
#define MainArrayLength 1
extern u8 Rtl8192SUFwMainArray[MainArrayLength];
#define DataArrayLength 1
diff --git a/drivers/staging/rtl8192su/r8192S_firmware.c b/drivers/staging/rtl8192su/r8192S_firmware.c
index 3561adf0468..752a3f1fb3f 100644
--- a/drivers/staging/rtl8192su/r8192S_firmware.c
+++ b/drivers/staging/rtl8192su/r8192S_firmware.c
@@ -360,117 +360,58 @@ bool FirmwareDownload92S(struct net_device *dev)
RT_TRACE(COMP_FIRMWARE, " --->FirmwareDownload92S()\n");
- //3//
- //3 //<1> Open Image file, and map file to contineous memory if open file success.
- //3 // or read image file from array. Default load from BIN file
- //3//
- priv->firmware_source = FW_SOURCE_IMG_FILE;// We should decided by Reg.
-
- switch( priv->firmware_source )
+/*
+* Load the firmware from RTL8192SU/rtl8192sfw.bin
+*/
+ if(pFirmware->szFwTmpBufferLen == 0)
{
- case FW_SOURCE_IMG_FILE:
- if(pFirmware->szFwTmpBufferLen == 0)
- {
-
- rc = request_firmware(&fw_entry, pFwImageFileName[ulInitStep],&priv->udev->dev);//===>1
- if(rc < 0 ) {
- RT_TRACE(COMP_ERR, "request firmware fail!\n");
- goto DownloadFirmware_Fail;
- }
-
- if(fw_entry->size > sizeof(pFirmware->szFwTmpBuffer))
- {
- RT_TRACE(COMP_ERR, "img file size exceed the container buffer fail!\n");
- release_firmware(fw_entry);
- goto DownloadFirmware_Fail;
- }
+ rc = request_firmware(&fw_entry, pFwImageFileName[ulInitStep],&priv->udev->dev);
+ if(rc < 0 ) {
+ RT_TRACE(COMP_ERR, "request firmware fail!\n");
+ goto DownloadFirmware_Fail;
+ }
- memcpy(pFirmware->szFwTmpBuffer,fw_entry->data,fw_entry->size);
- pFirmware->szFwTmpBufferLen = fw_entry->size;
+ if(fw_entry->size > sizeof(pFirmware->szFwTmpBuffer)) {
+ RT_TRACE(COMP_ERR, "img file size exceed the container buffer fail!\n");
release_firmware(fw_entry);
-
- pucMappedFile = pFirmware->szFwTmpBuffer;
- file_length = pFirmware->szFwTmpBufferLen;
-
- //Retrieve FW header.
- pFirmware->pFwHeader = (PRT_8192S_FIRMWARE_HDR) pucMappedFile;
- pFwHdr = pFirmware->pFwHeader;
- RT_TRACE(COMP_FIRMWARE,"signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n", \
- pFwHdr->Signature, pFwHdr->Version, pFwHdr->DMEMSize, \
- pFwHdr->IMG_IMEM_SIZE, pFwHdr->IMG_SRAM_SIZE);
- pFirmware->FirmwareVersion = byte(pFwHdr->Version ,0);
- if ((pFwHdr->IMG_IMEM_SIZE==0) || (pFwHdr->IMG_IMEM_SIZE > sizeof(pFirmware->FwIMEM)))
- {
- RT_TRACE(COMP_ERR, "%s: memory for data image is less than IMEM required\n",\
- __FUNCTION__);
- goto DownloadFirmware_Fail;
- } else {
- pucMappedFile+=FwHdrSize;
-
- //Retrieve IMEM image.
- memcpy(pFirmware->FwIMEM, pucMappedFile, pFwHdr->IMG_IMEM_SIZE);
- pFirmware->FwIMEMLen = pFwHdr->IMG_IMEM_SIZE;
- }
-
- if (pFwHdr->IMG_SRAM_SIZE > sizeof(pFirmware->FwEMEM))
- {
- RT_TRACE(COMP_ERR, "%s: memory for data image is less than EMEM required\n",\
- __FUNCTION__);
- goto DownloadFirmware_Fail;
- } else {
- pucMappedFile += pFirmware->FwIMEMLen;
-
- /* Retriecve EMEM image */
- memcpy(pFirmware->FwEMEM, pucMappedFile, pFwHdr->IMG_SRAM_SIZE);//===>6
- pFirmware->FwEMEMLen = pFwHdr->IMG_SRAM_SIZE;
- }
-
-
+ goto DownloadFirmware_Fail;
}
- break;
- case FW_SOURCE_HEADER_FILE:
-#if 1
-#define Rtl819XFwImageArray Rtl8192SUFwImgArray
- //2008.11.10 Add by tynli.
- pucMappedFile = Rtl819XFwImageArray;
- ulFileLength = ImgArrayLength;
+ memcpy(pFirmware->szFwTmpBuffer,fw_entry->data,fw_entry->size);
+ pFirmware->szFwTmpBufferLen = fw_entry->size;
+ release_firmware(fw_entry);
+
+ pucMappedFile = pFirmware->szFwTmpBuffer;
+ file_length = pFirmware->szFwTmpBufferLen;
- RT_TRACE(COMP_INIT,"Fw download from header.\n");
- /* Retrieve FW header*/
+ /* Retrieve FW header. */
pFirmware->pFwHeader = (PRT_8192S_FIRMWARE_HDR) pucMappedFile;
pFwHdr = pFirmware->pFwHeader;
RT_TRACE(COMP_FIRMWARE,"signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n", \
pFwHdr->Signature, pFwHdr->Version, pFwHdr->DMEMSize, \
pFwHdr->IMG_IMEM_SIZE, pFwHdr->IMG_SRAM_SIZE);
pFirmware->FirmwareVersion = byte(pFwHdr->Version ,0);
-
- if ((pFwHdr->IMG_IMEM_SIZE==0) || (pFwHdr->IMG_IMEM_SIZE > sizeof(pFirmware->FwIMEM)))
- {
- printk("FirmwareDownload92S(): memory for data image is less than IMEM required\n");
+ if ((pFwHdr->IMG_IMEM_SIZE==0) || (pFwHdr->IMG_IMEM_SIZE > sizeof(pFirmware->FwIMEM))) {
+ RT_TRACE(COMP_ERR, "%s: memory for data image is less than IMEM required\n",\
+ __FUNCTION__);
goto DownloadFirmware_Fail;
} else {
pucMappedFile+=FwHdrSize;
- //Retrieve IMEM image.
+ /* Retrieve IMEM image. */
memcpy(pFirmware->FwIMEM, pucMappedFile, pFwHdr->IMG_IMEM_SIZE);
pFirmware->FwIMEMLen = pFwHdr->IMG_IMEM_SIZE;
}
- if (pFwHdr->IMG_SRAM_SIZE > sizeof(pFirmware->FwEMEM))
- {
- printk(" FirmwareDownload92S(): memory for data image is less than EMEM required\n");
- goto DownloadFirmware_Fail;
- } else {
- pucMappedFile+= pFirmware->FwIMEMLen;
-
- //Retriecve EMEM image.
- memcpy(pFirmware->FwEMEM, pucMappedFile, pFwHdr->IMG_SRAM_SIZE);
- pFirmware->FwEMEMLen = pFwHdr->IMG_SRAM_SIZE;
- }
-#endif
- break;
- default:
- break;
+ if (pFwHdr->IMG_SRAM_SIZE > sizeof(pFirmware->FwEMEM)) {
+ RT_TRACE(COMP_ERR, "%s: memory for data image is less than EMEM required\n",\
+ __FUNCTION__);
+ goto DownloadFirmware_Fail;
+ } else {
+ pucMappedFile += pFirmware->FwIMEMLen;
+ /* Retriecve EMEM image */
+ memcpy(pFirmware->FwEMEM, pucMappedFile, pFwHdr->IMG_SRAM_SIZE);//===>6
+ pFirmware->FwEMEMLen = pFwHdr->IMG_SRAM_SIZE;
+ }
}
FwStatus = FirmwareGetNextStatus(pFirmware->FWStatus);
@@ -538,3 +479,4 @@ bool FirmwareDownload92S(struct net_device *dev)
return rtStatus;
}
+MODULE_FIRMWARE("RTL8192SU/rtl8192sfw.bin");
diff --git a/drivers/staging/rtl8192su/r8192S_firmware.h b/drivers/staging/rtl8192su/r8192S_firmware.h
index c525380e647..2c2cf8032de 100644
--- a/drivers/staging/rtl8192su/r8192S_firmware.h
+++ b/drivers/staging/rtl8192su/r8192S_firmware.h
@@ -59,12 +59,6 @@ typedef enum _desc_packet_type_e{
DESC_PACKET_TYPE_NORMAL = 1,
}desc_packet_type_e;
-typedef enum _firmware_source{
- FW_SOURCE_IMG_FILE = 0,
- FW_SOURCE_HEADER_FILE = 1,
-}firmware_source_e, *pfirmware_source_e;
-
-
typedef enum _opt_rst_type{
OPT_SYSTEM_RESET = 0,
OPT_FIRMWARE_RESET = 1,
@@ -185,7 +179,6 @@ typedef enum _FIRMWARE_8192S_STATUS{
#define RTL8190_MAX_FIRMWARE_CODE_SIZE 64000 //64k
typedef struct _rt_firmware{
- firmware_source_e eFWSource;
PRT_8192S_FIRMWARE_HDR pFwHeader;
FIRMWARE_8192S_STATUS FWStatus;
u16 FirmwareVersion;
diff --git a/drivers/staging/rtl8192su/r8192S_phy.c b/drivers/staging/rtl8192su/r8192S_phy.c
index 77ab026288d..63d4e5fd7b1 100644
--- a/drivers/staging/rtl8192su/r8192S_phy.c
+++ b/drivers/staging/rtl8192su/r8192S_phy.c
@@ -2407,8 +2407,8 @@ void PHY_SetBWModeCallback8192S(struct net_device *dev)
break;
default:
- RT_TRACE(COMP_DBG, "SetBWModeCallback8190Pci():\
- unknown Bandwidth: %#X\n",priv->CurrentChannelBW);
+ RT_TRACE(COMP_DBG, "SetBWModeCallback8190Pci(): unknown Bandwidth: %#X\n",
+ priv->CurrentChannelBW);
break;
}
@@ -3398,8 +3398,8 @@ void SwChnlCallback8192SUsb(struct net_device *dev)
u32 delay;
// bool ret;
- RT_TRACE(COMP_SCAN, "==>SwChnlCallback8190Pci(), switch to channel\
- %d\n", priv->chan);
+ RT_TRACE(COMP_SCAN, "==>SwChnlCallback8190Pci(), switch to channel %d\n",
+ priv->chan);
if(!priv->up)
@@ -3525,8 +3525,8 @@ void SetBWModeCallback8192SUsb(struct net_device *dev)
break;
default:
- RT_TRACE(COMP_DBG, "SetChannelBandwidth8190Pci():\
- unknown Bandwidth: %#X\n",priv->CurrentChannelBW);
+ RT_TRACE(COMP_DBG, "SetChannelBandwidth8190Pci(): unknown Bandwidth: %#X\n",
+ priv->CurrentChannelBW);
break;
}
@@ -3660,8 +3660,8 @@ void SetBWModeCallback8192SUsbWorkItem(struct net_device *dev)
break;
default:
- RT_TRACE(COMP_DBG, "SetBWModeCallback8192SUsbWorkItem():\
- unknown Bandwidth: %#X\n",priv->CurrentChannelBW);
+ RT_TRACE(COMP_DBG, "SetBWModeCallback8192SUsbWorkItem(): unknown Bandwidth: %#X\n",
+ priv->CurrentChannelBW);
break;
}
diff --git a/drivers/staging/rtl8192su/r8192U.h b/drivers/staging/rtl8192su/r8192U.h
index 2a11e0113d3..ba87623f32e 100644
--- a/drivers/staging/rtl8192su/r8192U.h
+++ b/drivers/staging/rtl8192su/r8192U.h
@@ -1258,7 +1258,6 @@ typedef struct r8192_priv
u8 Rf_Mode; //add for Firmware RF -R/W switch
prt_firmware pFirmware;
rtl819xUsb_loopback_e LoopbackMode;
- firmware_source_e firmware_source;
bool usb_error;
u16 EEPROMTxPowerDiff;
diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c
index 6f424fe8a23..7d0305cc210 100644
--- a/drivers/staging/rtl8192su/r8192U_core.c
+++ b/drivers/staging/rtl8192su/r8192U_core.c
@@ -110,7 +110,7 @@ u32 rt_global_debug_component = \
#define TOTAL_CAM_ENTRY 32
#define CAM_CONTENT_COUNT 8
-static struct usb_device_id rtl8192_usb_id_tbl[] = {
+static const struct usb_device_id rtl8192_usb_id_tbl[] = {
/* Realtek */
{USB_DEVICE(0x0bda, 0x8192)},
{USB_DEVICE(0x0bda, 0x8709)},
@@ -2340,25 +2340,24 @@ short rtl8192SU_tx(struct net_device *dev, struct sk_buff* skb)
skb->len, rtl8192_tx_isr, skb);
status = usb_submit_urb(tx_urb, GFP_ATOMIC);
- if (!status){
-//we need to send 0 byte packet whenever 512N bytes/64N(HIGN SPEED/NORMAL SPEED) bytes packet has been transmitted. Otherwise, it will be halt to wait for another packet. WB. 2008.08.27
+ if (!status) {
+ /*
+ * we need to send 0 byte packet whenever 512N bytes/64N(HIGN SPEED/NORMAL SPEED) bytes packet has been transmitted.
+ * Otherwise, it will be halt to wait for another packet. WB. 2008.08.27
+ */
bool bSend0Byte = false;
u8 zero = 0;
- if(udev->speed == USB_SPEED_HIGH)
- {
+ if(udev->speed == USB_SPEED_HIGH) {
if (skb->len > 0 && skb->len % 512 == 0)
bSend0Byte = true;
}
- else
- {
+ else {
if (skb->len > 0 && skb->len % 64 == 0)
bSend0Byte = true;
}
- if (bSend0Byte)
- {
-#if 1
+ if (bSend0Byte) {
tx_urb_zero = usb_alloc_urb(0,GFP_ATOMIC);
- if(!tx_urb_zero){
+ if(!tx_urb_zero) {
RT_TRACE(COMP_ERR, "can't alloc urb for zero byte\n");
return -ENOMEM;
}
@@ -2366,16 +2365,23 @@ short rtl8192SU_tx(struct net_device *dev, struct sk_buff* skb)
usb_sndbulkpipe(udev,idx_pipe), &zero,
0, tx_zero_isr, dev);
status = usb_submit_urb(tx_urb_zero, GFP_ATOMIC);
- if (status){
- RT_TRACE(COMP_ERR, "Error TX URB for zero byte %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]), status);
- return -1;
+ switch (status) {
+ case 0:
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ break;
+ default:
+ RT_TRACE(COMP_ERR, "Error TX URB for zero byte %d, error %d",
+ atomic_read(&priv->tx_pending[tcb_desc->queue_index]), status);
+ return -1;
}
-#endif
}
dev->trans_start = jiffies;
atomic_inc(&priv->tx_pending[tcb_desc->queue_index]);
return 0;
- }else{
+ } else {
RT_TRACE(COMP_ERR, "Error TX URB %d, error %d", atomic_read(&priv->tx_pending[tcb_desc->queue_index]),
status);
return -1;
@@ -2952,7 +2958,7 @@ void rtl8192_SetWirelessMode(struct net_device* dev, u8 wireless_mode)
wireless_mode = WIRELESS_MODE_B;
}
}
-#ifdef TO_DO_LIST //// TODO: this function doesn't work well at this time, we shoud wait for FPGA
+#ifdef TO_DO_LIST //// TODO: this function doesn't work well at this time, we should wait for FPGA
ActUpdateChannelAccessSetting( pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting );
#endif
//LZM 090306 usb crash here, mark it temp
@@ -3359,6 +3365,46 @@ u8 rtl8192SU_BoardTypeToRFtype(struct net_device* dev, u8 Boardtype)
return RFtype;
}
+void update_hal_variables(struct r8192_priv *priv)
+{
+ int rf_path;
+ int i;
+ u8 index;
+
+ for (rf_path = 0; rf_path < 2; rf_path++) {
+ for (i = 0; i < 3; i++) {
+ RT_TRACE((COMP_INIT), "CCK RF-%d CHan_Area-%d = 0x%x\n", rf_path, i, priv->RfCckChnlAreaTxPwr[rf_path][i]);
+ RT_TRACE((COMP_INIT), "OFDM-1T RF-%d CHan_Area-%d = 0x%x\n", rf_path, i, priv->RfOfdmChnlAreaTxPwr1T[rf_path][i]);
+ RT_TRACE((COMP_INIT), "OFDM-2T RF-%d CHan_Area-%d = 0x%x\n", rf_path, i, priv->RfOfdmChnlAreaTxPwr2T[rf_path][i]);
+ }
+ /* Assign dedicated channel tx power */
+ for(i = 0; i < 14; i++) {
+ /* channel 1-3 use the same Tx Power Level. */
+ if (i < 3) /* Channel 1-3 */
+ index = 0;
+ else if (i < 9) /* Channel 4-9 */
+ index = 1;
+ else /* Channel 10-14 */
+ index = 2;
+ /* Record A & B CCK /OFDM - 1T/2T Channel area tx power */
+ priv->RfTxPwrLevelCck[rf_path][i] = priv->RfCckChnlAreaTxPwr[rf_path][index];
+ priv->RfTxPwrLevelOfdm1T[rf_path][i] = priv->RfOfdmChnlAreaTxPwr1T[rf_path][index];
+ priv->RfTxPwrLevelOfdm2T[rf_path][i] = priv->RfOfdmChnlAreaTxPwr2T[rf_path][index];
+ if (rf_path == 0) {
+ priv->TxPowerLevelOFDM24G[i] = priv->RfTxPwrLevelOfdm1T[rf_path][i] ;
+ priv->TxPowerLevelCCK[i] = priv->RfTxPwrLevelCck[rf_path][i];
+ }
+ }
+ for(i = 0; i < 14; i++) {
+ RT_TRACE((COMP_INIT),
+ "Rf-%d TxPwr CH-%d CCK OFDM_1T OFDM_2T= 0x%x/0x%x/0x%x\n",
+ rf_path, i, priv->RfTxPwrLevelCck[rf_path][i],
+ priv->RfTxPwrLevelOfdm1T[rf_path][i] ,
+ priv->RfTxPwrLevelOfdm2T[rf_path][i] );
+ }
+ }
+}
+
//
// Description:
// Config HW adapter information into initial value.
@@ -3374,7 +3420,7 @@ rtl8192SU_ConfigAdapterInfo8192SForAutoLoadFail(struct net_device* dev)
struct r8192_priv *priv = ieee80211_priv(dev);
//u16 i,usValue;
//u8 sMacAddr[6] = {0x00, 0xE0, 0x4C, 0x81, 0x92, 0x00};
- u8 rf_path, index; // For EEPROM/EFUSE After V0.6_1117
+ u8 rf_path; // For EEPROM/EFUSE After V0.6_1117
int i;
RT_TRACE(COMP_INIT, "====> ConfigAdapterInfo8192SForAutoLoadFail\n");
@@ -3426,10 +3472,9 @@ rtl8192SU_ConfigAdapterInfo8192SForAutoLoadFail(struct net_device* dev)
write_nic_dword(dev, IDR0, ((u32*)dev->dev_addr)[0]);
write_nic_word(dev, IDR4, ((u16*)(dev->dev_addr + 4))[0]);
- RT_TRACE(COMP_INIT, "ReadAdapterInfo8192SEFuse(), Permanent Address = %02x-%02x-%02x-%02x-%02x-%02x\n",
- dev->dev_addr[0], dev->dev_addr[1],
- dev->dev_addr[2], dev->dev_addr[3],
- dev->dev_addr[4], dev->dev_addr[5]);
+ RT_TRACE(COMP_INIT,
+ "ReadAdapterInfo8192SEFuse(), Permanent Address = %pM\n",
+ dev->dev_addr);
priv->EEPROMBoardType = EEPROM_Default_BoardType;
priv->rf_type = RF_1T2R; //RF_2T2R
@@ -3455,42 +3500,7 @@ rtl8192SU_ConfigAdapterInfo8192SForAutoLoadFail(struct net_device* dev)
}
}
- for (i = 0; i < 3; i++)
- {
- //RT_TRACE((COMP_EFUSE), "CCK RF-%d CHan_Area-%d = 0x%x\n", rf_path, i,
- //priv->RfCckChnlAreaTxPwr[rf_path][i]);
- //RT_TRACE((COMP_EFUSE), "OFDM-1T RF-%d CHan_Area-%d = 0x%x\n", rf_path, i,
- //priv->RfOfdmChnlAreaTxPwr1T[rf_path][i]);
- //RT_TRACE((COMP_EFUSE), "OFDM-2T RF-%d CHan_Area-%d = 0x%x\n", rf_path, i,
- //priv->RfOfdmChnlAreaTxPwr2T[rf_path][i]);
- }
-
- // Assign dedicated channel tx power
- for(i=0; i<14; i++) // channel 1~3 use the same Tx Power Level.
- {
- if (i < 3) // Cjanel 1-3
- index = 0;
- else if (i < 9) // Channel 4-9
- index = 1;
- else // Channel 10-14
- index = 2;
-
- // Record A & B CCK /OFDM - 1T/2T Channel area tx power
- priv->RfTxPwrLevelCck[rf_path][i] =
- priv->RfCckChnlAreaTxPwr[rf_path][index];
- priv->RfTxPwrLevelOfdm1T[rf_path][i] =
- priv->RfOfdmChnlAreaTxPwr1T[rf_path][index];
- priv->RfTxPwrLevelOfdm2T[rf_path][i] =
- priv->RfOfdmChnlAreaTxPwr2T[rf_path][index];
- }
-
- for(i=0; i<14; i++)
- {
- //RT_TRACE((COMP_EFUSE), "Rf-%d TxPwr CH-%d CCK OFDM_1T OFDM_2T= 0x%x/0x%x/0x%x\n",
- //rf_path, i, priv->RfTxPwrLevelCck[0][i],
- //priv->RfTxPwrLevelOfdm1T[0][i] ,
- //priv->RfTxPwrLevelOfdm2T[0][i] );
- }
+ update_hal_variables(priv);
//
// Update remained HAL variables.
@@ -3767,10 +3777,9 @@ rtl8192SU_ReadAdapterInfo8192SUsb(struct net_device* dev)
write_nic_dword(dev, IDR0, ((u32*)dev->dev_addr)[0]);
write_nic_word(dev, IDR4, ((u16*)(dev->dev_addr + 4))[0]);
- RT_TRACE(COMP_INIT, "ReadAdapterInfo8192SEFuse(), Permanent Address = %02x-%02x-%02x-%02x-%02x-%02x\n",
- dev->dev_addr[0], dev->dev_addr[1],
- dev->dev_addr[2], dev->dev_addr[3],
- dev->dev_addr[4], dev->dev_addr[5]);
+ RT_TRACE(COMP_INIT,
+ "ReadAdapterInfo8192SEFuse(), Permanent Address = %pM\n",
+ dev->dev_addr);
//
// Get CustomerID(Boad Type)
@@ -3901,53 +3910,7 @@ rtl8192SU_ReadAdapterInfo8192SUsb(struct net_device* dev)
}
}
-//
- // Update Tx Power HAL variables.
-//
- for (rf_path = 0; rf_path < 2; rf_path++)
- {
- for (i = 0; i < 3; i++)
- {
- RT_TRACE((COMP_INIT), "CCK RF-%d CHan_Area-%d = 0x%x\n", rf_path, i,
- priv->RfCckChnlAreaTxPwr[rf_path][i]);
- RT_TRACE((COMP_INIT), "OFDM-1T RF-%d CHan_Area-%d = 0x%x\n", rf_path, i,
- priv->RfOfdmChnlAreaTxPwr1T[rf_path][i]);
- RT_TRACE((COMP_INIT), "OFDM-2T RF-%d CHan_Area-%d = 0x%x\n", rf_path, i, priv->RfOfdmChnlAreaTxPwr2T[rf_path][i]);
- }
-
- // Assign dedicated channel tx power
- for(i=0; i<14; i++) // channel 1~3 use the same Tx Power Level.
- {
- if (i < 3) // Cjanel 1-3
- index = 0;
- else if (i < 9) // Channel 4-9
- index = 1;
- else // Channel 10-14
- index = 2;
-
- // Record A & B CCK /OFDM - 1T/2T Channel area tx power
- priv->RfTxPwrLevelCck[rf_path][i] =
- priv->RfCckChnlAreaTxPwr[rf_path][index];
- priv->RfTxPwrLevelOfdm1T[rf_path][i] =
- priv->RfOfdmChnlAreaTxPwr1T[rf_path][index];
- priv->RfTxPwrLevelOfdm2T[rf_path][i] =
- priv->RfOfdmChnlAreaTxPwr2T[rf_path][index];
- if (rf_path == 0)
- {
- priv->TxPowerLevelOFDM24G[i] = priv->RfTxPwrLevelOfdm1T[rf_path][i] ;
- priv->TxPowerLevelCCK[i] = priv->RfTxPwrLevelCck[rf_path][i];
- }
- }
-
- for(i=0; i<14; i++)
- {
- RT_TRACE((COMP_INIT),
- "Rf-%d TxPwr CH-%d CCK OFDM_1T OFDM_2T= 0x%x/0x%x/0x%x\n",
- rf_path, i, priv->RfTxPwrLevelCck[rf_path][i],
- priv->RfTxPwrLevelOfdm1T[rf_path][i] ,
- priv->RfTxPwrLevelOfdm2T[rf_path][i] );
- }
- }
+ update_hal_variables(priv);
}
//
@@ -7677,7 +7640,7 @@ void setKey( struct net_device *dev,
if (EntryNo >= TOTAL_CAM_ENTRY)
RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
- RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr"MAC_FMT"\n", dev,EntryNo, KeyIndex, KeyType, MAC_ARG(MacAddr));
+ RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr%pM\n", dev,EntryNo, KeyIndex, KeyType, MacAddr);
if (DefaultKey)
usConfig |= BIT15 | (KeyType<<2);
diff --git a/drivers/staging/rtl8192su/r8192U_dm.c b/drivers/staging/rtl8192su/r8192U_dm.c
index 7891e964027..fa5e24416dd 100644
--- a/drivers/staging/rtl8192su/r8192U_dm.c
+++ b/drivers/staging/rtl8192su/r8192U_dm.c
@@ -2697,7 +2697,7 @@ static void dm_check_edca_turbo(
u8* peername[11] = {"unknown", "realtek", "realtek_92se", "broadcom", "ralink", "atheros", "cisco", "marvell", "92u_softap", "self_softap"};
static int wb_tmp = 0;
if (wb_tmp == 0){
- printk("%s():iot peer is %#x:%s, bssid:"MAC_FMT"\n",__FUNCTION__,pHTInfo->IOTPeer,peername[pHTInfo->IOTPeer], MAC_ARG(priv->ieee80211->current_network.bssid));
+ printk("%s():iot peer is %#x:%s, bssid:%pM\n",__FUNCTION__,pHTInfo->IOTPeer,peername[pHTInfo->IOTPeer], priv->ieee80211->current_network.bssid);
wb_tmp = 1;
}
}
diff --git a/drivers/staging/rtl8192u/Kconfig b/drivers/staging/rtl8192u/Kconfig
index 9913ab8fb35..0439c90b416 100644
--- a/drivers/staging/rtl8192u/Kconfig
+++ b/drivers/staging/rtl8192u/Kconfig
@@ -1,6 +1,7 @@
config RTL8192U
tristate "RealTek RTL8192U Wireless LAN NIC driver"
depends on PCI && WLAN && USB
- depends on WIRELESS_EXT
+ select WIRELESS_EXT
+ select WEXT_PRIV
default N
---help---
diff --git a/drivers/staging/rtl8192u/Makefile b/drivers/staging/rtl8192u/Makefile
index 2d59c4ef6c5..738f4a80ec6 100644
--- a/drivers/staging/rtl8192u/Makefile
+++ b/drivers/staging/rtl8192u/Makefile
@@ -3,7 +3,7 @@ NIC_SELECT = RTL8192U
EXTRA_CFLAGS += -std=gnu89
EXTRA_CFLAGS += -O2
-EXTRA_CFLAGS += -mhard-float -DCONFIG_FORCE_HARD_FLOAT=y
+EXTRA_CFLAGS += -DCONFIG_FORCE_HARD_FLOAT=y
EXTRA_CFLAGS += -DJACKSON_NEW_8187 -DJACKSON_NEW_RX
EXTRA_CFLAGS += -DTHOMAS_BEACON -DTHOMAS_TASKLET -DTHOMAS_SKB -DTHOMAS_TURBO
#EXTRA_CFLAGS += -DUSB_TX_DRIVER_AGGREGATION_ENABLE
diff --git a/drivers/staging/rtl8192u/ieee80211.h b/drivers/staging/rtl8192u/ieee80211.h
index 3a47f1213e8..9d05ed6791e 100644
--- a/drivers/staging/rtl8192u/ieee80211.h
+++ b/drivers/staging/rtl8192u/ieee80211.h
@@ -551,9 +551,6 @@ do { if (ieee80211_debug_level & (level)) \
/* debug macros not dependent on CONFIG_IEEE80211_DEBUG */
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]
-
/*
* To use the debug system;
*
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
index 10908e123b8..39847c81e29 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
@@ -30,6 +30,7 @@
#include <linux/jiffies.h>
#include <linux/timer.h>
#include <linux/sched.h>
+#include <linux/semaphore.h>
#include <linux/delay.h>
#include <linux/wireless.h>
@@ -551,9 +552,6 @@ do { if (ieee80211_debug_level & (level)) \
/* debug macros not dependent on CONFIG_IEEE80211_DEBUG */
-#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
-#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]
-
/*
* To use the debug system;
*
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c
index 0b33bf46332..0b57632bcff 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_ccmp.c
@@ -288,7 +288,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (!(keyidx & (1 << 5))) {
if (net_ratelimit()) {
printk(KERN_DEBUG "CCMP: received packet without ExtIV"
- " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
+ " flag from %pM\n", hdr->addr2);
}
key->dot11RSNAStatsCCMPFormatErrors++;
return -2;
@@ -301,9 +301,9 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
}
if (!key->key_set) {
if (net_ratelimit()) {
- printk(KERN_DEBUG "CCMP: received packet from " MAC_FMT
+ printk(KERN_DEBUG "CCMP: received packet from %pM"
" with keyid=%d that does not have a configured"
- " key\n", MAC_ARG(hdr->addr2), keyidx);
+ " key\n", hdr->addr2, keyidx);
}
return -3;
}
@@ -318,11 +318,9 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) {
if (net_ratelimit()) {
- printk(KERN_DEBUG "CCMP: replay detected: STA=" MAC_FMT
- " previous PN %02x%02x%02x%02x%02x%02x "
- "received PN %02x%02x%02x%02x%02x%02x\n",
- MAC_ARG(hdr->addr2), MAC_ARG(key->rx_pn),
- MAC_ARG(pn));
+ printk(KERN_DEBUG "CCMP: replay detected: STA=%pM"
+ " previous PN %pm received PN %pm\n",
+ hdr->addr2, key->rx_pn, pn);
}
key->dot11RSNAStatsCCMPReplays++;
return -4;
@@ -359,7 +357,7 @@ static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (memcmp(mic, a, CCMP_MIC_LEN) != 0) {
if (net_ratelimit()) {
printk(KERN_DEBUG "CCMP: decrypt failed: STA="
- MAC_FMT "\n", MAC_ARG(hdr->addr2));
+ "%pM\n", hdr->addr2);
}
key->dot11RSNAStatsCCMPDecryptErrors++;
return -5;
@@ -435,11 +433,10 @@ static char * ieee80211_ccmp_print_stats(char *p, void *priv)
{
struct ieee80211_ccmp_data *ccmp = priv;
p += sprintf(p, "key[%d] alg=CCMP key_set=%d "
- "tx_pn=%02x%02x%02x%02x%02x%02x "
- "rx_pn=%02x%02x%02x%02x%02x%02x "
+ "tx_pn=%pm rx_pn=%pm "
"format_errors=%d replays=%d decrypt_errors=%d\n",
ccmp->key_idx, ccmp->key_set,
- MAC_ARG(ccmp->tx_pn), MAC_ARG(ccmp->rx_pn),
+ ccmp->tx_pn, ccmp->rx_pn,
ccmp->dot11RSNAStatsCCMPFormatErrors,
ccmp->dot11RSNAStatsCCMPReplays,
ccmp->dot11RSNAStatsCCMPDecryptErrors);
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
index 841b99955b7..9510507d8d0 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_crypt_tkip.c
@@ -410,7 +410,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (!(keyidx & (1 << 5))) {
if (net_ratelimit()) {
printk(KERN_DEBUG "TKIP: received packet without ExtIV"
- " flag from " MAC_FMT "\n", MAC_ARG(hdr->addr2));
+ " flag from %pM\n", hdr->addr2);
}
return -2;
}
@@ -422,9 +422,9 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
}
if (!tkey->key_set) {
if (net_ratelimit()) {
- printk(KERN_DEBUG "TKIP: received packet from " MAC_FMT
+ printk(KERN_DEBUG "TKIP: received packet from %pM"
" with keyid=%d that does not have a configured"
- " key\n", MAC_ARG(hdr->addr2), keyidx);
+ " key\n", hdr->addr2, keyidx);
}
return -3;
}
@@ -437,9 +437,9 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (iv32 < tkey->rx_iv32 ||
(iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) {
if (net_ratelimit()) {
- printk(KERN_DEBUG "TKIP: replay detected: STA=" MAC_FMT
+ printk(KERN_DEBUG "TKIP: replay detected: STA=%pM"
" previous TSC %08x%04x received TSC "
- "%08x%04x\n", MAC_ARG(hdr->addr2),
+ "%08x%04x\n", hdr->addr2,
tkey->rx_iv32, tkey->rx_iv16, iv32, iv16);
}
tkey->dot11RSNAStatsTKIPReplays++;
@@ -460,8 +460,8 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) {
if (net_ratelimit()) {
printk(KERN_DEBUG ": TKIP: failed to decrypt "
- "received packet from " MAC_FMT "\n",
- MAC_ARG(hdr->addr2));
+ "received packet from %pM\n",
+ hdr->addr2);
}
return -7;
}
@@ -480,7 +480,7 @@ static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv)
}
if (net_ratelimit()) {
printk(KERN_DEBUG "TKIP: ICV error detected: STA="
- MAC_FMT "\n", MAC_ARG(hdr->addr2));
+ "%pM\n", hdr->addr2);
}
tkey->dot11RSNAStatsTKIPICVErrors++;
return -5;
@@ -635,8 +635,8 @@ static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx,
struct ieee80211_hdr_4addr *hdr;
hdr = (struct ieee80211_hdr_4addr *) skb->data;
printk(KERN_DEBUG "%s: Michael MIC verification failed for "
- "MSDU from " MAC_FMT " keyidx=%d\n",
- skb->dev ? skb->dev->name : "N/A", MAC_ARG(hdr->addr2),
+ "MSDU from %pM keyidx=%d\n",
+ skb->dev ? skb->dev->name : "N/A", hdr->addr2,
keyidx);
if (skb->dev)
ieee80211_michael_mic_failure(skb->dev, hdr, keyidx);
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
index 7a8690f449b..b752017a4d1 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_module.c
@@ -260,7 +260,7 @@ static int store_debug_level(struct file *file, const char *buffer,
unsigned long count, void *data)
{
char buf[] = "0x00000000";
- unsigned long len = min(sizeof(buf) - 1, count);
+ unsigned long len = min_t(unsigned long, sizeof(buf) - 1, count);
char *p = (char *)buf;
unsigned long val;
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
index 0e003c5bb00..7e9b367594a 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
@@ -360,8 +360,8 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
strcmp(crypt->ops->name, "TKIP") == 0) {
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
- "received packet from " MAC_FMT "\n",
- ieee->dev->name, MAC_ARG(hdr->addr2));
+ "received packet from %pM\n",
+ ieee->dev->name, hdr->addr2);
}
return -1;
}
@@ -372,8 +372,8 @@ ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb,
atomic_dec(&crypt->refcnt);
if (res < 0) {
IEEE80211_DEBUG_DROP(
- "decryption failed (SA=" MAC_FMT
- ") res=%d\n", MAC_ARG(hdr->addr2), res);
+ "decryption failed (SA=%pM"
+ ") res=%d\n", hdr->addr2, res);
if (res == -2)
IEEE80211_DEBUG_DROP("Decryption failed ICV "
"mismatch (key %d)\n",
@@ -410,8 +410,8 @@ ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device* ieee, struct sk_buff *s
atomic_dec(&crypt->refcnt);
if (res < 0) {
printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
- " (SA=" MAC_FMT " keyidx=%d)\n",
- ieee->dev->name, MAC_ARG(hdr->addr2), keyidx);
+ " (SA=%pM keyidx=%d)\n",
+ ieee->dev->name, hdr->addr2, keyidx);
return -1;
}
@@ -1016,8 +1016,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
* frames silently instead of filling system log with
* these reports. */
IEEE80211_DEBUG_DROP("Decryption failed (not set)"
- " (SA=" MAC_FMT ")\n",
- MAC_ARG(hdr->addr2));
+ " (SA=%pM)\n",
+ hdr->addr2);
ieee->ieee_stats.rx_discards_undecryptable++;
goto rx_dropped;
}
@@ -1256,8 +1256,8 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
} else {
IEEE80211_DEBUG_DROP(
"encryption configured, but RX "
- "frame not encrypted (SA=" MAC_FMT ")\n",
- MAC_ARG(hdr->addr2));
+ "frame not encrypted (SA=%pM)\n",
+ hdr->addr2);
goto rx_dropped;
}
}
@@ -1276,9 +1276,9 @@ int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
!ieee80211_is_eapol_frame(ieee, skb, hdrlen)) {
IEEE80211_DEBUG_DROP(
"dropped unencrypted RX data "
- "frame from " MAC_FMT
+ "frame from %pM"
" (drop_unencrypted=1)\n",
- MAC_ARG(hdr->addr2));
+ hdr->addr2);
goto rx_dropped;
}
/*
@@ -2260,11 +2260,11 @@ static inline int ieee80211_network_init(
}
if (network->mode == 0) {
- IEEE80211_DEBUG_SCAN("Filtered out '%s (" MAC_FMT ")' "
+ IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' "
"network.\n",
escape_essid(network->ssid,
network->ssid_len),
- MAC_ARG(network->bssid));
+ network->bssid);
return 1;
}
@@ -2439,9 +2439,9 @@ static inline void ieee80211_process_probe_response(
memset(&network, 0, sizeof(struct ieee80211_network));
IEEE80211_DEBUG_SCAN(
- "'%s' (" MAC_FMT "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
+ "'%s' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
escape_essid(info_element->data, info_element->len),
- MAC_ARG(beacon->header.addr3),
+ beacon->header.addr3,
(beacon->capability & (1<<0xf)) ? '1' : '0',
(beacon->capability & (1<<0xe)) ? '1' : '0',
(beacon->capability & (1<<0xd)) ? '1' : '0',
@@ -2460,10 +2460,10 @@ static inline void ieee80211_process_probe_response(
(beacon->capability & (1<<0x0)) ? '1' : '0');
if (ieee80211_network_init(ieee, beacon, &network, stats)) {
- IEEE80211_DEBUG_SCAN("Dropped '%s' (" MAC_FMT ") via %s.\n",
+ IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
escape_essid(info_element->data,
info_element->len),
- MAC_ARG(beacon->header.addr3),
+ beacon->header.addr3,
WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
IEEE80211_STYPE_PROBE_RESP ?
"PROBE RESPONSE" : "BEACON");
@@ -2574,11 +2574,11 @@ static inline void ieee80211_process_probe_response(
/* If there are no more slots, expire the oldest */
list_del(&oldest->list);
target = oldest;
- IEEE80211_DEBUG_SCAN("Expired '%s' (" MAC_FMT ") from "
+ IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from "
"network list.\n",
escape_essid(target->ssid,
target->ssid_len),
- MAC_ARG(target->bssid));
+ target->bssid);
} else {
/* Otherwise just pull from the free list */
target = list_entry(ieee->network_free_list.next,
@@ -2588,10 +2588,10 @@ static inline void ieee80211_process_probe_response(
#ifdef CONFIG_IEEE80211_DEBUG
- IEEE80211_DEBUG_SCAN("Adding '%s' (" MAC_FMT ") via %s.\n",
+ IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
escape_essid(network.ssid,
network.ssid_len),
- MAC_ARG(network.bssid),
+ network.bssid,
WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
IEEE80211_STYPE_PROBE_RESP ?
"PROBE RESPONSE" : "BEACON");
@@ -2601,10 +2601,10 @@ static inline void ieee80211_process_probe_response(
if(ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE)
ieee80211_softmac_new_net(ieee,&network);
} else {
- IEEE80211_DEBUG_SCAN("Updating '%s' (" MAC_FMT ") via %s.\n",
+ IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
escape_essid(target->ssid,
target->ssid_len),
- MAC_ARG(target->bssid),
+ target->bssid,
WLAN_FC_GET_STYPE(beacon->header.frame_ctl) ==
IEEE80211_STYPE_PROBE_RESP ?
"PROBE RESPONSE" : "BEACON");
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
index 8a86e93465c..27d925712cd 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
@@ -1731,7 +1731,7 @@ ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
ieee80211_resp_to_assoc_rq(ieee, dest);
}
- printk(KERN_INFO"New client associated: "MAC_FMT"\n", MAC_ARG(dest));
+ printk(KERN_INFO"New client associated: %pM\n", dest);
//FIXME
}
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
index b29c36bac37..48537d94894 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
@@ -200,8 +200,8 @@ int ieee80211_encrypt_fragment(
header = (struct ieee80211_hdr *) frag->data;
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
- "TX packet to " MAC_FMT "\n",
- ieee->dev->name, MAC_ARG(header->addr1));
+ "TX packet to %pM\n",
+ ieee->dev->name, header->addr1);
}
return -1;
}
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c
index 5f12d62658c..c0b2c02b0ac 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c
@@ -289,10 +289,10 @@ int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
else
IEEE80211_DEBUG_SCAN(
"Not showing network '%s ("
- MAC_FMT ")' due to age (%lums).\n",
+ "%pM)' due to age (%lums).\n",
escape_essid(network->ssid,
network->ssid_len),
- MAC_ARG(network->bssid),
+ network->bssid,
(jiffies - network->last_scanned) / (HZ / 100));
}
@@ -718,7 +718,7 @@ int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
} else
idx = ieee->tx_keyidx;
- if (!ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY &&
+ if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
ext->alg != IW_ENCODE_ALG_WEP)
if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
return -EINVAL;
diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c
index 512a57aebde..27d083a70eb 100644
--- a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c
+++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c
@@ -113,7 +113,7 @@ static struct sk_buff* ieee80211_ADDBA(struct ieee80211_device* ieee, u8* Dst, P
u16 tmp = 0;
u16 len = ieee->tx_headroom + 9;
//category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) + BA Timeout Value(2) + BA Start SeqCtrl(2)(or StatusCode(2))
- IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:"MAC_FMT", ieee->dev:%p\n", __FUNCTION__, type, MAC_ARG(Dst), ieee->dev);
+ IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __FUNCTION__, type, Dst, ieee->dev);
if (pBA == NULL||ieee == NULL)
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee);
@@ -201,7 +201,7 @@ static struct sk_buff* ieee80211_DELBA(
u16 len = 6 + ieee->tx_headroom;
if (net_ratelimit())
- IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:"MAC_FMT"\n", __FUNCTION__, ReasonCode, MAC_ARG(dst));
+ IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:%pM\n", __FUNCTION__, ReasonCode, dst);
memset(&DelbaParamSet, 0, 2);
@@ -355,7 +355,7 @@ int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb)
pBaTimeoutVal = (u16*)(tag + 5);
pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7);
- printk("====================>rx ADDBAREQ from :"MAC_FMT"\n", MAC_ARG(dst));
+ printk("====================>rx ADDBAREQ from :%pM\n", dst);
//some other capability is not ready now.
if( (ieee->current_network.qos_data.active == 0) ||
(ieee->pHTInfo->bCurrentHTSupport == false)) //||
diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c
index 2c4eb38c89a..50f4f5943e7 100644
--- a/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c
+++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c
@@ -41,7 +41,7 @@ static u8 AIRLINK_RALINK[3] = {0x00, 0x18, 0x02};
//static u8 DLINK_ATHEROS[3] = {0x00, 0x1c, 0xf0};
static u8 CISCO_BROADCOM[3] = {0x00, 0x17, 0x94};
-// 2008/04/01 MH For Cisco G mode RX TP We need to change FW duration. Shoud we put the
+// 2008/04/01 MH For Cisco G mode RX TP We need to change FW duration. Should we put the
// code in other place??
//static u8 WIFI_CISCO_G_AP[3] = {0x00, 0x40, 0x96};
/********************************************************************************************************************
@@ -1342,7 +1342,7 @@ void HTUseDefaultSetting(struct ieee80211_device* ieee)
pHTInfo->CurrentAMPDUFactor = pHTInfo->AMPDU_Factor;
- pHTInfo->CurrentMPDUDensity = pHTInfo->CurrentMPDUDensity;
+ pHTInfo->CurrentMPDUDensity = pHTInfo->MPDU_Density;
// Set BWOpMode register
diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c
index 5373d565af2..d1275e887f0 100644
--- a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c
+++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c
@@ -290,7 +290,7 @@ PTS_COMMON_INFO SearchAdmitTRStream(struct ieee80211_device *ieee, u8* Addr, u8
if(search_dir[dir] ==false )
continue;
list_for_each_entry(pRet, psearch_list, List){
- // IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:"MAC_FMT", TID:%d, dir:%d\n", MAC_ARG(pRet->Addr), pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection);
+ // IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:%pM, TID:%d, dir:%d\n", pRet->Addr, pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection);
if (memcmp(pRet->Addr, Addr, 6) == 0)
if (pRet->TSpec.f.TSInfo.field.ucTSID == TID)
if(pRet->TSpec.f.TSInfo.field.ucDirection == dir)
@@ -445,7 +445,7 @@ bool GetTs(
ResetRxTsEntry(tmp);
}
- IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:"MAC_FMT"\n", UP, Dir, MAC_ARG(Addr));
+ IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:%pM\n", UP, Dir, Addr);
// Prepare TS Info releated field
pTSInfo->field.ucTrafficType = 0; // Traffic type: WMM is reserved in this field
pTSInfo->field.ucTSID = UP; // TSID
@@ -531,7 +531,7 @@ void RemoveTsEntry(
void RemovePeerTS(struct ieee80211_device* ieee, u8* Addr)
{
PTS_COMMON_INFO pTS, pTmpTS;
- printk("===========>RemovePeerTS,"MAC_FMT"\n", MAC_ARG(Addr));
+ printk("===========>RemovePeerTS,%pM\n", Addr);
list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List)
{
if (memcmp(pTS->Addr, Addr, 6) == 0)
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index adade13e1e1..f1e085ba1cf 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -104,7 +104,7 @@ u32 rt_global_debug_component = \
#define TOTAL_CAM_ENTRY 32
#define CAM_CONTENT_COUNT 8
-static struct usb_device_id rtl8192_usb_id_tbl[] = {
+static const struct usb_device_id rtl8192_usb_id_tbl[] = {
/* Realtek */
{USB_DEVICE(0x0bda, 0x8192)},
{USB_DEVICE(0x0bda, 0x8709)},
@@ -2719,7 +2719,7 @@ void rtl8192_SetWirelessMode(struct net_device* dev, u8 wireless_mode)
wireless_mode = WIRELESS_MODE_B;
}
}
-#ifdef TO_DO_LIST //// TODO: this function doesn't work well at this time, we shoud wait for FPGA
+#ifdef TO_DO_LIST //// TODO: this function doesn't work well at this time, we should wait for FPGA
ActUpdateChannelAccessSetting( pAdapter, pHalData->CurrentWirelessMode, &pAdapter->MgntInfo.Info8185.ChannelAccessSetting );
#endif
priv->ieee80211->mode = wireless_mode;
@@ -2976,7 +2976,7 @@ static void rtl8192_read_eeprom_info(struct net_device* dev)
memcpy(dev->dev_addr, bMac_Tmp_Addr, 6);
//should I set IDR0 here?
}
- RT_TRACE(COMP_EPROM, "MAC addr:"MAC_FMT"\n", MAC_ARG(dev->dev_addr));
+ RT_TRACE(COMP_EPROM, "MAC addr:%pM\n", dev->dev_addr);
priv->rf_type = RTL819X_DEFAULT_RF_TYPE; //default 1T2R
priv->rf_chip = RF_8256;
@@ -6037,7 +6037,7 @@ void setKey( struct net_device *dev,
if (EntryNo >= TOTAL_CAM_ENTRY)
RT_TRACE(COMP_ERR, "cam entry exceeds in setKey()\n");
- RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr"MAC_FMT"\n", dev,EntryNo, KeyIndex, KeyType, MAC_ARG(MacAddr));
+ RT_TRACE(COMP_SEC, "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d, KeyType:%d, MacAddr%pM\n", dev,EntryNo, KeyIndex, KeyType, MacAddr);
if (DefaultKey)
usConfig |= BIT15 | (KeyType<<2);
diff --git a/drivers/staging/samsung-laptop/samsung-laptop.c b/drivers/staging/samsung-laptop/samsung-laptop.c
index 4877138a9f9..dd7ea4c075d 100644
--- a/drivers/staging/samsung-laptop/samsung-laptop.c
+++ b/drivers/staging/samsung-laptop/samsung-laptop.c
@@ -99,7 +99,8 @@ static struct rfkill *rfk;
static int force;
module_param(force, bool, 0);
-MODULE_PARM_DESC(force, "Disable the DMI check and forces the driver to be loaded");
+MODULE_PARM_DESC(force,
+ "Disable the DMI check and forces the driver to be loaded");
static int debug;
module_param(debug, bool, S_IRUGO | S_IWUSR);
@@ -370,7 +371,8 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
{
.ident = "N128",
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_SYS_VENDOR,
+ "SAMSUNG ELECTRONICS CO., LTD."),
DMI_MATCH(DMI_PRODUCT_NAME, "N128"),
DMI_MATCH(DMI_BOARD_NAME, "N128"),
},
@@ -379,7 +381,8 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
{
.ident = "N130",
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_SYS_VENDOR,
+ "SAMSUNG ELECTRONICS CO., LTD."),
DMI_MATCH(DMI_PRODUCT_NAME, "N130"),
DMI_MATCH(DMI_BOARD_NAME, "N130"),
},
diff --git a/drivers/staging/sep/sep_driver.c b/drivers/staging/sep/sep_driver.c
index e7bc9ec63a8..265de7949a7 100644
--- a/drivers/staging/sep/sep_driver.c
+++ b/drivers/staging/sep/sep_driver.c
@@ -35,6 +35,7 @@
#include <linux/cdev.h>
#include <linux/kdev_t.h>
#include <linux/mutex.h>
+#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/poll.h>
#include <linux/wait.h>
@@ -182,8 +183,8 @@ static DECLARE_WAIT_QUEUE_HEAD(sep_event);
static int sep_load_firmware(struct sep_device *sep)
{
const struct firmware *fw;
- char *cache_name = "cache.image.bin";
- char *res_name = "resident.image.bin";
+ char *cache_name = "sep/cache.image.bin";
+ char *res_name = "sep/resident.image.bin";
int error;
edbg("SEP Driver:rar_virtual is %p\n", sep->rar_addr);
@@ -222,6 +223,9 @@ static int sep_load_firmware(struct sep_device *sep)
return 0;
}
+MODULE_FIRMWARE("sep/cache.image.bin");
+MODULE_FIRMWARE("sep/resident.image.bin");
+
/**
* sep_map_and_alloc_shared_area - allocate shared block
* @sep: security processor
@@ -273,8 +277,8 @@ static dma_addr_t sep_shared_virt_to_bus(struct sep_device *sep,
void *virt_address)
{
dma_addr_t pa = sep->shared_bus + (virt_address - sep->shared_addr);
- edbg("sep: virt to bus b %08llx v %p\n",
- (unsigned long long)pa, virt_address);
+ edbg("sep: virt to bus b %08llx v %p\n", (unsigned long long) pa,
+ virt_address);
return pa;
}
@@ -380,8 +384,7 @@ static int sep_mmap(struct file *filp, struct vm_area_struct *vma)
shared area */
if ((vma->vm_end - vma->vm_start) > SEP_DRIVER_MMMAP_AREA_SIZE) {
edbg("SEP Driver mmap requested size is more than allowed\n");
- printk(KERN_WARNING "SEP Driver mmap requested size is more \
- than allowed\n");
+ printk(KERN_WARNING "SEP Driver mmap requested size is more than allowed\n");
printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n", vma->vm_end);
printk(KERN_WARNING "SEP Driver vma->vm_end is %08lx\n", vma->vm_start);
return -EAGAIN;
@@ -941,8 +944,9 @@ static int sep_lock_user_pages(struct sep_device *sep,
dbg("data_size is %lu\n", data_size);
while (1);
}
- edbg("lli_array[%lu].physical_address is %08lx, \
- lli_array[%lu].block_size is %lu\n", count, lli_array[count].physical_address, count, lli_array[count].block_size);
+ edbg("lli_array[%lu].physical_address is %08lx, lli_array[%lu].block_size is %lu\n",
+ count, lli_array[count].physical_address,
+ count, lli_array[count].block_size);
}
/* set output params */
@@ -1771,7 +1775,7 @@ static struct sep_flow_context_t *sep_find_flow_context(struct sep_device *sep,
static int sep_create_flow_dma_tables_handler(struct sep_device *sep,
unsigned long arg)
{
- int error;
+ int error = -ENOENT;
struct sep_driver_build_flow_table_t command_args;
/* first table - output */
struct sep_lli_entry_t first_table_data;
@@ -2232,7 +2236,7 @@ static int sep_set_flow_id_handler(struct sep_device *sep,
return error;
}
-static int sep_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+static long sep_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
int error = 0;
struct sep_device *sep = filp->private_data;
@@ -2586,7 +2590,7 @@ end_function:
return error;
}
-static struct pci_device_id sep_pci_id_tbl[] = {
+static const struct pci_device_id sep_pci_id_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080c)},
{0}
};
@@ -2607,7 +2611,7 @@ static dev_t sep_devno;
/* the files operations structure of the driver */
static struct file_operations sep_file_operations = {
.owner = THIS_MODULE,
- .ioctl = sep_ioctl,
+ .unlocked_ioctl = sep_ioctl,
.poll = sep_poll,
.open = sep_open,
.release = sep_release,
diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c
index 060e9de3b06..44f2d4eaf84 100644
--- a/drivers/staging/serqt_usb2/serqt_usb2.c
+++ b/drivers/staging/serqt_usb2/serqt_usb2.c
@@ -126,7 +126,7 @@ static int debug;
#define MODEM_CTRL 0x40
#define RS232_MODE 0x00
-static struct usb_device_id serqt_id_table[] = {
+static const struct usb_device_id serqt_id_table[] = {
{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU100)},
{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_SSU200)},
{USB_DEVICE(USB_VENDOR_ID_QUATECH, QUATECH_DSU100)},
@@ -1277,7 +1277,7 @@ static void qt_set_termios(struct tty_struct *tty,
if (cflag & CSTOPB)
new_LCR |= SERIAL_TWO_STOPB;
else
- new_LCR |= SERIAL_TWO_STOPB;
+ new_LCR |= SERIAL_ONE_STOPB;
dbg("%s - 4\n", __func__);
diff --git a/drivers/staging/slicoss/slic.h b/drivers/staging/slicoss/slic.h
index ccf7625b8bb..eb3a619c6a9 100644
--- a/drivers/staging/slicoss/slic.h
+++ b/drivers/staging/slicoss/slic.h
@@ -527,15 +527,6 @@ struct adapter {
(largestat) += ((newstat) - (oldstat)); \
}
-#define ETHER_EQ_ADDR(_AddrA, _AddrB, _Result) \
-{ \
- _Result = true; \
- if (*(u32 *)(_AddrA) != *(u32 *)(_AddrB)) \
- _Result = false; \
- if (*(u16 *)(&((_AddrA)[4])) != *(u16 *)(&((_AddrB)[4]))) \
- _Result = false; \
-}
-
#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
#define SLIC_GET_ADDR_LOW(_addr) (u32)((u64)(_addr) & \
0x00000000FFFFFFFF)
diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c
index f5cc01ba414..7daeced317c 100644
--- a/drivers/staging/slicoss/slicoss.c
+++ b/drivers/staging/slicoss/slicoss.c
@@ -101,7 +101,7 @@ static struct net_device_stats *slic_get_stats(struct net_device *dev);
static int slic_entry_open(struct net_device *dev);
static int slic_entry_halt(struct net_device *dev);
static int slic_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static int slic_xmit_start(struct sk_buff *skb, struct net_device *dev);
+static netdev_tx_t slic_xmit_start(struct sk_buff *skb, struct net_device *dev);
static void slic_xmit_fail(struct adapter *adapter, struct sk_buff *skb,
void *cmd, u32 skbtype, u32 status);
static void slic_config_pci(struct pci_dev *pcidev);
@@ -194,14 +194,10 @@ MODULE_PARM_DESC(dynamic_intagg, "Dynamic Interrupt Aggregation Setting");
module_param(intagg_delay, int, 0);
MODULE_PARM_DESC(intagg_delay, "uSec Interrupt Aggregation Delay");
-static struct pci_device_id slic_pci_tbl[] __devinitdata = {
- {PCI_VENDOR_ID_ALACRITECH,
- SLIC_1GB_DEVICE_ID,
- PCI_ANY_ID, PCI_ANY_ID,},
- {PCI_VENDOR_ID_ALACRITECH,
- SLIC_2GB_DEVICE_ID,
- PCI_ANY_ID, PCI_ANY_ID,},
- {0,}
+static DEFINE_PCI_DEVICE_TABLE(slic_pci_tbl) = {
+ { PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH, SLIC_1GB_DEVICE_ID) },
+ { PCI_DEVICE(PCI_VENDOR_ID_ALACRITECH, SLIC_2GB_DEVICE_ID) },
+ { 0 }
};
MODULE_DEVICE_TABLE(pci, slic_pci_tbl);
@@ -292,7 +288,7 @@ static void slic_init_adapter(struct net_device *netdev,
{
ushort index;
struct slic_handle *pslic_handle;
- struct adapter *adapter = (struct adapter *)netdev_priv(netdev);
+ struct adapter *adapter = netdev_priv(netdev);
/* adapter->pcidev = pcidev;*/
adapter->vendid = pci_tbl_entry->vendor;
@@ -370,6 +366,7 @@ static int __devinit slic_entry_probe(struct pci_dev *pcidev,
ulong mmio_start = 0;
ulong mmio_len = 0;
struct sliccard *card = NULL;
+ int pci_using_dac = 0;
slic_global.dynamic_intagg = dynamic_intagg;
@@ -383,16 +380,26 @@ static int __devinit slic_entry_probe(struct pci_dev *pcidev,
printk(KERN_DEBUG "%s\n", slic_proc_version);
}
- err = pci_set_dma_mask(pcidev, DMA_BIT_MASK(64));
- if (err) {
- err = pci_set_dma_mask(pcidev, DMA_BIT_MASK(32));
- if (err)
+ if (!pci_set_dma_mask(pcidev, DMA_BIT_MASK(64))) {
+ pci_using_dac = 1;
+ if (pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64))) {
+ dev_err(&pcidev->dev, "unable to obtain 64-bit DMA for "
+ "consistent allocations\n");
goto err_out_disable_pci;
+ }
+ } else if (pci_set_dma_mask(pcidev, DMA_BIT_MASK(32))) {
+ pci_using_dac = 0;
+ pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(32));
+ } else {
+ dev_err(&pcidev->dev, "no usable DMA configuration\n");
+ goto err_out_disable_pci;
}
err = pci_request_regions(pcidev, DRV_NAME);
- if (err)
+ if (err) {
+ dev_err(&pcidev->dev, "can't obtain PCI resources\n");
goto err_out_disable_pci;
+ }
pci_set_master(pcidev);
@@ -408,6 +415,8 @@ static int __devinit slic_entry_probe(struct pci_dev *pcidev,
adapter = netdev_priv(netdev);
adapter->netdev = netdev;
adapter->pcidev = pcidev;
+ if (pci_using_dac)
+ netdev->features |= NETIF_F_HIGHDMA;
mmio_start = pci_resource_start(pcidev, 0);
mmio_len = pci_resource_len(pcidev, 0);
@@ -484,7 +493,7 @@ err_out_disable_pci:
static int slic_entry_open(struct net_device *dev)
{
- struct adapter *adapter = (struct adapter *) netdev_priv(dev);
+ struct adapter *adapter = netdev_priv(dev);
struct sliccard *card = adapter->card;
u32 locked = 0;
int status;
@@ -534,7 +543,7 @@ static void __devexit slic_entry_remove(struct pci_dev *pcidev)
struct net_device *dev = pci_get_drvdata(pcidev);
u32 mmio_start = 0;
uint mmio_len = 0;
- struct adapter *adapter = (struct adapter *) netdev_priv(dev);
+ struct adapter *adapter = netdev_priv(dev);
struct sliccard *card;
struct mcast_address *mcaddr, *mlist;
@@ -581,7 +590,7 @@ static void __devexit slic_entry_remove(struct pci_dev *pcidev)
static int slic_entry_halt(struct net_device *dev)
{
- struct adapter *adapter = (struct adapter *)netdev_priv(dev);
+ struct adapter *adapter = netdev_priv(dev);
struct sliccard *card = adapter->card;
__iomem struct slic_regs *slic_regs = adapter->slic_regs;
@@ -624,7 +633,7 @@ static int slic_entry_halt(struct net_device *dev)
static int slic_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- struct adapter *adapter = (struct adapter *)netdev_priv(dev);
+ struct adapter *adapter = netdev_priv(dev);
struct ethtool_cmd edata;
struct ethtool_cmd ecmd;
u32 data[7];
@@ -649,8 +658,7 @@ static int slic_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if (copy_from_user(data, rq->ifr_data, 28)) {
PRINT_ERROR
- ("slic: copy_from_user FAILED getting \
- initial simba param\n");
+ ("slic: copy_from_user FAILED getting initial simba param\n");
return -EFAULT;
}
@@ -665,8 +673,7 @@ static int slic_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
(tracemon_request ==
SLIC_DUMP_IN_PROGRESS)) {
PRINT_ERROR
- ("ATK Diagnostic Trace Dump Requested but \
- already in progress... ignore\n");
+ ("ATK Diagnostic Trace Dump Requested but already in progress... ignore\n");
} else {
PRINT_ERROR
("ATK Diagnostic Trace Dump Requested\n");
@@ -784,10 +791,10 @@ static void slic_xmit_build_request(struct adapter *adapter,
#define NORMAL_ETHFRAME 0
-static int slic_xmit_start(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t slic_xmit_start(struct sk_buff *skb, struct net_device *dev)
{
struct sliccard *card;
- struct adapter *adapter = (struct adapter *)netdev_priv(dev);
+ struct adapter *adapter = netdev_priv(dev);
struct slic_hostcmd *hcmd = NULL;
u32 status = 0;
u32 skbtype = NORMAL_ETHFRAME;
@@ -1071,7 +1078,7 @@ static void slic_xmit_complete(struct adapter *adapter)
static irqreturn_t slic_interrupt(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
- struct adapter *adapter = (struct adapter *)netdev_priv(dev);
+ struct adapter *adapter = netdev_priv(dev);
u32 isr;
if ((adapter->pshmem) && (adapter->pshmem->isr)) {
@@ -1229,22 +1236,21 @@ static void slic_init_cleanup(struct adapter *adapter)
static struct net_device_stats *slic_get_stats(struct net_device *dev)
{
- struct adapter *adapter = (struct adapter *)netdev_priv(dev);
- struct net_device_stats *stats;
+ struct adapter *adapter = netdev_priv(dev);
ASSERT(adapter);
- stats = &adapter->stats;
- stats->collisions = adapter->slic_stats.iface.xmit_collisions;
- stats->rx_errors = adapter->slic_stats.iface.rcv_errors;
- stats->tx_errors = adapter->slic_stats.iface.xmt_errors;
- stats->rx_missed_errors = adapter->slic_stats.iface.rcv_discards;
- stats->tx_heartbeat_errors = 0;
- stats->tx_aborted_errors = 0;
- stats->tx_window_errors = 0;
- stats->tx_fifo_errors = 0;
- stats->rx_frame_errors = 0;
- stats->rx_length_errors = 0;
- return &adapter->stats;
+ dev->stats.collisions = adapter->slic_stats.iface.xmit_collisions;
+ dev->stats.rx_errors = adapter->slic_stats.iface.rcv_errors;
+ dev->stats.tx_errors = adapter->slic_stats.iface.xmt_errors;
+ dev->stats.rx_missed_errors = adapter->slic_stats.iface.rcv_discards;
+ dev->stats.tx_heartbeat_errors = 0;
+ dev->stats.tx_aborted_errors = 0;
+ dev->stats.tx_window_errors = 0;
+ dev->stats.tx_fifo_errors = 0;
+ dev->stats.rx_frame_errors = 0;
+ dev->stats.rx_length_errors = 0;
+
+ return &dev->stats;
}
/*
@@ -1254,13 +1260,11 @@ static struct net_device_stats *slic_get_stats(struct net_device *dev)
static int slic_mcast_add_list(struct adapter *adapter, char *address)
{
struct mcast_address *mcaddr, *mlist;
- bool equaladdr;
/* Check to see if it already exists */
mlist = adapter->mcastaddrs;
while (mlist) {
- ETHER_EQ_ADDR(mlist->address, address, equaladdr);
- if (equaladdr)
+ if (!compare_ether_addr(mlist->address, address))
return STATUS_SUCCESS;
mlist = mlist->next;
}
@@ -1360,7 +1364,7 @@ static void slic_mcast_set_bit(struct adapter *adapter, char *address)
static void slic_mcast_set_list(struct net_device *dev)
{
- struct adapter *adapter = (struct adapter *)netdev_priv(dev);
+ struct adapter *adapter = netdev_priv(dev);
int status = STATUS_SUCCESS;
char *addresses;
struct dev_mc_list *mc_list;
@@ -1852,6 +1856,9 @@ static int slic_card_download_gbrcv(struct adapter *adapter)
return 0;
}
+MODULE_FIRMWARE("slicoss/oasisrcvucode.sys");
+MODULE_FIRMWARE("slicoss/gbrcvucode.sys");
+
static int slic_card_download(struct adapter *adapter)
{
const struct firmware *fw;
@@ -1963,6 +1970,9 @@ static int slic_card_download(struct adapter *adapter)
return STATUS_SUCCESS;
}
+MODULE_FIRMWARE("slicoss/oasisdownload.sys");
+MODULE_FIRMWARE("slicoss/gbdownload.sys");
+
static void slic_adapter_set_hwaddr(struct adapter *adapter)
{
struct sliccard *card = adapter->card;
@@ -2466,7 +2476,6 @@ static bool slic_mac_filter(struct adapter *adapter,
u32 opts = adapter->macopts;
u32 *dhost4 = (u32 *)&ether_frame->ether_dhost[0];
u16 *dhost2 = (u16 *)&ether_frame->ether_dhost[4];
- bool equaladdr;
if (opts & MAC_PROMISC)
return true;
@@ -2490,10 +2499,8 @@ static bool slic_mac_filter(struct adapter *adapter,
struct mcast_address *mcaddr = adapter->mcastaddrs;
while (mcaddr) {
- ETHER_EQ_ADDR(mcaddr->address,
- ether_frame->ether_dhost,
- equaladdr);
- if (equaladdr) {
+ if (!compare_ether_addr(mcaddr->address,
+ ether_frame->ether_dhost)) {
adapter->rcv_multicasts++;
adapter->stats.multicast++;
return true;
@@ -2515,7 +2522,7 @@ static bool slic_mac_filter(struct adapter *adapter,
static int slic_mac_set_address(struct net_device *dev, void *ptr)
{
- struct adapter *adapter = (struct adapter *)netdev_priv(dev);
+ struct adapter *adapter = netdev_priv(dev);
struct sockaddr *addr = ptr;
if (netif_running(dev))
@@ -2523,6 +2530,9 @@ static int slic_mac_set_address(struct net_device *dev, void *ptr)
if (!adapter)
return -EBUSY;
+ if (!is_valid_ether_addr(addr->sa_data))
+ return -EINVAL;
+
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
memcpy(adapter->currmacaddr, addr->sa_data, dev->addr_len);
@@ -3960,10 +3970,8 @@ static void slic_debug_adapter_create(struct adapter *adapter)
static void slic_debug_adapter_destroy(struct adapter *adapter)
{
- if (adapter->debugfs_entry) {
- debugfs_remove(adapter->debugfs_entry);
- adapter->debugfs_entry = NULL;
- }
+ debugfs_remove(adapter->debugfs_entry);
+ adapter->debugfs_entry = NULL;
}
static void slic_debug_card_create(struct sliccard *card)
diff --git a/drivers/staging/sm7xx/Kconfig b/drivers/staging/sm7xx/Kconfig
index 204dbfc3c38..315102c7fed 100644
--- a/drivers/staging/sm7xx/Kconfig
+++ b/drivers/staging/sm7xx/Kconfig
@@ -6,10 +6,3 @@ config FB_SM7XX
select FB_CFB_IMAGEBLIT
help
Frame Buffer driver for the Silicon Motion SM7XX serial graphic card.
-
-config FB_SM7XX_ACCEL
- bool "Siliconmotion Acceleration functions (EXPERIMENTAL)"
- depends on FB_SM7XX && EXPERIMENTAL
- help
- This will compile the Trident frame buffer device with
- acceleration functions.
diff --git a/drivers/staging/sm7xx/TODO b/drivers/staging/sm7xx/TODO
index 1f61f5e11cf..a66d9e40649 100644
--- a/drivers/staging/sm7xx/TODO
+++ b/drivers/staging/sm7xx/TODO
@@ -1,5 +1,6 @@
TODO:
- Dual head support
+- 2D acceleration support
- use kernel coding style
- checkpatch.pl clean
- refine the code and remove unused code
diff --git a/drivers/staging/sm7xx/smtc2d.c b/drivers/staging/sm7xx/smtc2d.c
deleted file mode 100644
index 2fff0a0052d..00000000000
--- a/drivers/staging/sm7xx/smtc2d.c
+++ /dev/null
@@ -1,979 +0,0 @@
-/*
- * Silicon Motion SM7XX 2D drawing engine functions.
- *
- * Copyright (C) 2006 Silicon Motion Technology Corp.
- * Author: Boyod boyod.yang@siliconmotion.com.cn
- *
- * Copyright (C) 2009 Lemote, Inc.
- * Author: Wu Zhangjin, wuzhangjin@gmail.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.
- *
- * Version 0.10.26192.21.01
- * - Add PowerPC support
- * - Add 2D support for Lynx -
- * Verified on 2.6.19.2
- * Boyod.yang <boyod.yang@siliconmotion.com.cn>
- */
-
-unsigned char smtc_de_busy;
-
-void SMTC_write2Dreg(unsigned long nOffset, unsigned long nData)
-{
- writel(nData, smtc_2DBaseAddress + nOffset);
-}
-
-unsigned long SMTC_read2Dreg(unsigned long nOffset)
-{
- return readl(smtc_2DBaseAddress + nOffset);
-}
-
-void SMTC_write2Ddataport(unsigned long nOffset, unsigned long nData)
-{
- writel(nData, smtc_2Ddataport + nOffset);
-}
-
-/**********************************************************************
- *
- * deInit
- *
- * Purpose
- * Drawing engine initialization.
- *
- **********************************************************************/
-
-void deInit(unsigned int nModeWidth, unsigned int nModeHeight,
- unsigned int bpp)
-{
- /* Get current power configuration. */
- unsigned char clock;
- clock = smtc_seqr(0x21);
-
- /* initialize global 'mutex lock' variable */
- smtc_de_busy = 0;
-
- /* Enable 2D Drawing Engine */
- smtc_seqw(0x21, clock & 0xF8);
-
- SMTC_write2Dreg(DE_CLIP_TL,
- FIELD_VALUE(0, DE_CLIP_TL, TOP, 0) |
- FIELD_SET(0, DE_CLIP_TL, STATUS, DISABLE) |
- FIELD_SET(0, DE_CLIP_TL, INHIBIT, OUTSIDE) |
- FIELD_VALUE(0, DE_CLIP_TL, LEFT, 0));
-
- if (bpp >= 24) {
- SMTC_write2Dreg(DE_PITCH,
- FIELD_VALUE(0, DE_PITCH, DESTINATION,
- nModeWidth * 3) | FIELD_VALUE(0,
- DE_PITCH,
- SOURCE,
- nModeWidth
- * 3));
- } else {
- SMTC_write2Dreg(DE_PITCH,
- FIELD_VALUE(0, DE_PITCH, DESTINATION,
- nModeWidth) | FIELD_VALUE(0,
- DE_PITCH,
- SOURCE,
- nModeWidth));
- }
-
- SMTC_write2Dreg(DE_WINDOW_WIDTH,
- FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
- nModeWidth) | FIELD_VALUE(0,
- DE_WINDOW_WIDTH,
- SOURCE,
- nModeWidth));
-
- switch (bpp) {
- case 8:
- SMTC_write2Dreg(DE_STRETCH_FORMAT,
- FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY,
- NORMAL) | FIELD_VALUE(0,
- DE_STRETCH_FORMAT,
- PATTERN_Y,
- 0) |
- FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X,
- 0) | FIELD_SET(0, DE_STRETCH_FORMAT,
- PIXEL_FORMAT,
- 8) | FIELD_SET(0,
- DE_STRETCH_FORMAT,
- ADDRESSING,
- XY) |
- FIELD_VALUE(0, DE_STRETCH_FORMAT,
- SOURCE_HEIGHT, 3));
- break;
- case 24:
- SMTC_write2Dreg(DE_STRETCH_FORMAT,
- FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY,
- NORMAL) | FIELD_VALUE(0,
- DE_STRETCH_FORMAT,
- PATTERN_Y,
- 0) |
- FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X,
- 0) | FIELD_SET(0, DE_STRETCH_FORMAT,
- PIXEL_FORMAT,
- 24) | FIELD_SET(0,
- DE_STRETCH_FORMAT,
- ADDRESSING,
- XY) |
- FIELD_VALUE(0, DE_STRETCH_FORMAT,
- SOURCE_HEIGHT, 3));
- break;
- case 16:
- default:
- SMTC_write2Dreg(DE_STRETCH_FORMAT,
- FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY,
- NORMAL) | FIELD_VALUE(0,
- DE_STRETCH_FORMAT,
- PATTERN_Y,
- 0) |
- FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X,
- 0) | FIELD_SET(0, DE_STRETCH_FORMAT,
- PIXEL_FORMAT,
- 16) | FIELD_SET(0,
- DE_STRETCH_FORMAT,
- ADDRESSING,
- XY) |
- FIELD_VALUE(0, DE_STRETCH_FORMAT,
- SOURCE_HEIGHT, 3));
- break;
- }
-
- SMTC_write2Dreg(DE_MASKS,
- FIELD_VALUE(0, DE_MASKS, BYTE_MASK, 0xFFFF) |
- FIELD_VALUE(0, DE_MASKS, BIT_MASK, 0xFFFF));
- SMTC_write2Dreg(DE_COLOR_COMPARE_MASK,
- FIELD_VALUE(0, DE_COLOR_COMPARE_MASK, MASKS, \
- 0xFFFFFF));
- SMTC_write2Dreg(DE_COLOR_COMPARE,
- FIELD_VALUE(0, DE_COLOR_COMPARE, COLOR, 0xFFFFFF));
-}
-
-void deVerticalLine(unsigned long dst_base,
- unsigned long dst_pitch,
- unsigned long nX,
- unsigned long nY,
- unsigned long dst_height, unsigned long nColor)
-{
- deWaitForNotBusy();
-
- SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
- FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS,
- dst_base));
-
- SMTC_write2Dreg(DE_PITCH,
- FIELD_VALUE(0, DE_PITCH, DESTINATION, dst_pitch) |
- FIELD_VALUE(0, DE_PITCH, SOURCE, dst_pitch));
-
- SMTC_write2Dreg(DE_WINDOW_WIDTH,
- FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
- dst_pitch) | FIELD_VALUE(0, DE_WINDOW_WIDTH,
- SOURCE,
- dst_pitch));
-
- SMTC_write2Dreg(DE_FOREGROUND,
- FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
-
- SMTC_write2Dreg(DE_DESTINATION,
- FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
- FIELD_VALUE(0, DE_DESTINATION, X, nX) |
- FIELD_VALUE(0, DE_DESTINATION, Y, nY));
-
- SMTC_write2Dreg(DE_DIMENSION,
- FIELD_VALUE(0, DE_DIMENSION, X, 1) |
- FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height));
-
- SMTC_write2Dreg(DE_CONTROL,
- FIELD_SET(0, DE_CONTROL, STATUS, START) |
- FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) |
- FIELD_SET(0, DE_CONTROL, MAJOR, Y) |
- FIELD_SET(0, DE_CONTROL, STEP_X, NEGATIVE) |
- FIELD_SET(0, DE_CONTROL, STEP_Y, POSITIVE) |
- FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) |
- FIELD_SET(0, DE_CONTROL, COMMAND, SHORT_STROKE) |
- FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
- FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C));
-
- smtc_de_busy = 1;
-}
-
-void deHorizontalLine(unsigned long dst_base,
- unsigned long dst_pitch,
- unsigned long nX,
- unsigned long nY,
- unsigned long dst_width, unsigned long nColor)
-{
- deWaitForNotBusy();
-
- SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
- FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS,
- dst_base));
-
- SMTC_write2Dreg(DE_PITCH,
- FIELD_VALUE(0, DE_PITCH, DESTINATION, dst_pitch) |
- FIELD_VALUE(0, DE_PITCH, SOURCE, dst_pitch));
-
- SMTC_write2Dreg(DE_WINDOW_WIDTH,
- FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
- dst_pitch) | FIELD_VALUE(0, DE_WINDOW_WIDTH,
- SOURCE,
- dst_pitch));
- SMTC_write2Dreg(DE_FOREGROUND,
- FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
- SMTC_write2Dreg(DE_DESTINATION,
- FIELD_SET(0, DE_DESTINATION, WRAP,
- DISABLE) | FIELD_VALUE(0, DE_DESTINATION, X,
- nX) | FIELD_VALUE(0,
- DE_DESTINATION,
- Y,
- nY));
- SMTC_write2Dreg(DE_DIMENSION,
- FIELD_VALUE(0, DE_DIMENSION, X,
- dst_width) | FIELD_VALUE(0, DE_DIMENSION,
- Y_ET, 1));
- SMTC_write2Dreg(DE_CONTROL,
- FIELD_SET(0, DE_CONTROL, STATUS, START) | FIELD_SET(0,
- DE_CONTROL,
- DIRECTION,
- RIGHT_TO_LEFT)
- | FIELD_SET(0, DE_CONTROL, MAJOR, X) | FIELD_SET(0,
- DE_CONTROL,
- STEP_X,
- POSITIVE)
- | FIELD_SET(0, DE_CONTROL, STEP_Y,
- NEGATIVE) | FIELD_SET(0, DE_CONTROL,
- LAST_PIXEL,
- OFF) | FIELD_SET(0,
- DE_CONTROL,
- COMMAND,
- SHORT_STROKE)
- | FIELD_SET(0, DE_CONTROL, ROP_SELECT,
- ROP2) | FIELD_VALUE(0, DE_CONTROL, ROP,
- 0x0C));
-
- smtc_de_busy = 1;
-}
-
-void deLine(unsigned long dst_base,
- unsigned long dst_pitch,
- unsigned long nX1,
- unsigned long nY1,
- unsigned long nX2, unsigned long nY2, unsigned long nColor)
-{
- unsigned long nCommand =
- FIELD_SET(0, DE_CONTROL, STATUS, START) |
- FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) |
- FIELD_SET(0, DE_CONTROL, MAJOR, X) |
- FIELD_SET(0, DE_CONTROL, STEP_X, POSITIVE) |
- FIELD_SET(0, DE_CONTROL, STEP_Y, POSITIVE) |
- FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) |
- FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
- FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C);
- unsigned long DeltaX;
- unsigned long DeltaY;
-
- /* Calculate delta X */
- if (nX1 <= nX2)
- DeltaX = nX2 - nX1;
- else {
- DeltaX = nX1 - nX2;
- nCommand = FIELD_SET(nCommand, DE_CONTROL, STEP_X, NEGATIVE);
- }
-
- /* Calculate delta Y */
- if (nY1 <= nY2)
- DeltaY = nY2 - nY1;
- else {
- DeltaY = nY1 - nY2;
- nCommand = FIELD_SET(nCommand, DE_CONTROL, STEP_Y, NEGATIVE);
- }
-
- /* Determine the major axis */
- if (DeltaX < DeltaY)
- nCommand = FIELD_SET(nCommand, DE_CONTROL, MAJOR, Y);
-
- /* Vertical line? */
- if (nX1 == nX2)
- deVerticalLine(dst_base, dst_pitch, nX1, nY1, DeltaY, nColor);
-
- /* Horizontal line? */
- else if (nY1 == nY2)
- deHorizontalLine(dst_base, dst_pitch, nX1, nY1, \
- DeltaX, nColor);
-
- /* Diagonal line? */
- else if (DeltaX == DeltaY) {
- deWaitForNotBusy();
-
- SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
- FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE,
- ADDRESS, dst_base));
-
- SMTC_write2Dreg(DE_PITCH,
- FIELD_VALUE(0, DE_PITCH, DESTINATION,
- dst_pitch) | FIELD_VALUE(0,
- DE_PITCH,
- SOURCE,
- dst_pitch));
-
- SMTC_write2Dreg(DE_WINDOW_WIDTH,
- FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
- dst_pitch) | FIELD_VALUE(0,
- DE_WINDOW_WIDTH,
- SOURCE,
- dst_pitch));
-
- SMTC_write2Dreg(DE_FOREGROUND,
- FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
-
- SMTC_write2Dreg(DE_DESTINATION,
- FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
- FIELD_VALUE(0, DE_DESTINATION, X, 1) |
- FIELD_VALUE(0, DE_DESTINATION, Y, nY1));
-
- SMTC_write2Dreg(DE_DIMENSION,
- FIELD_VALUE(0, DE_DIMENSION, X, 1) |
- FIELD_VALUE(0, DE_DIMENSION, Y_ET, DeltaX));
-
- SMTC_write2Dreg(DE_CONTROL,
- FIELD_SET(nCommand, DE_CONTROL, COMMAND,
- SHORT_STROKE));
- }
-
- /* Generic line */
- else {
- unsigned int k1, k2, et, w;
- if (DeltaX < DeltaY) {
- k1 = 2 * DeltaX;
- et = k1 - DeltaY;
- k2 = et - DeltaY;
- w = DeltaY + 1;
- } else {
- k1 = 2 * DeltaY;
- et = k1 - DeltaX;
- k2 = et - DeltaX;
- w = DeltaX + 1;
- }
-
- deWaitForNotBusy();
-
- SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
- FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE,
- ADDRESS, dst_base));
-
- SMTC_write2Dreg(DE_PITCH,
- FIELD_VALUE(0, DE_PITCH, DESTINATION,
- dst_pitch) | FIELD_VALUE(0,
- DE_PITCH,
- SOURCE,
- dst_pitch));
-
- SMTC_write2Dreg(DE_WINDOW_WIDTH,
- FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
- dst_pitch) | FIELD_VALUE(0,
- DE_WINDOW_WIDTH,
- SOURCE,
- dst_pitch));
-
- SMTC_write2Dreg(DE_FOREGROUND,
- FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
-
- SMTC_write2Dreg(DE_SOURCE,
- FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
- FIELD_VALUE(0, DE_SOURCE, X_K1, k1) |
- FIELD_VALUE(0, DE_SOURCE, Y_K2, k2));
-
- SMTC_write2Dreg(DE_DESTINATION,
- FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
- FIELD_VALUE(0, DE_DESTINATION, X, nX1) |
- FIELD_VALUE(0, DE_DESTINATION, Y, nY1));
-
- SMTC_write2Dreg(DE_DIMENSION,
- FIELD_VALUE(0, DE_DIMENSION, X, w) |
- FIELD_VALUE(0, DE_DIMENSION, Y_ET, et));
-
- SMTC_write2Dreg(DE_CONTROL,
- FIELD_SET(nCommand, DE_CONTROL, COMMAND,
- LINE_DRAW));
- }
-
- smtc_de_busy = 1;
-}
-
-void deFillRect(unsigned long dst_base,
- unsigned long dst_pitch,
- unsigned long dst_X,
- unsigned long dst_Y,
- unsigned long dst_width,
- unsigned long dst_height, unsigned long nColor)
-{
- deWaitForNotBusy();
-
- SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
- FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS,
- dst_base));
-
- if (dst_pitch) {
- SMTC_write2Dreg(DE_PITCH,
- FIELD_VALUE(0, DE_PITCH, DESTINATION,
- dst_pitch) | FIELD_VALUE(0,
- DE_PITCH,
- SOURCE,
- dst_pitch));
-
- SMTC_write2Dreg(DE_WINDOW_WIDTH,
- FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
- dst_pitch) | FIELD_VALUE(0,
- DE_WINDOW_WIDTH,
- SOURCE,
- dst_pitch));
- }
-
- SMTC_write2Dreg(DE_FOREGROUND,
- FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor));
-
- SMTC_write2Dreg(DE_DESTINATION,
- FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
- FIELD_VALUE(0, DE_DESTINATION, X, dst_X) |
- FIELD_VALUE(0, DE_DESTINATION, Y, dst_Y));
-
- SMTC_write2Dreg(DE_DIMENSION,
- FIELD_VALUE(0, DE_DIMENSION, X, dst_width) |
- FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height));
-
- SMTC_write2Dreg(DE_CONTROL,
- FIELD_SET(0, DE_CONTROL, STATUS, START) |
- FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) |
- FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) |
- FIELD_SET(0, DE_CONTROL, COMMAND, RECTANGLE_FILL) |
- FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
- FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C));
-
- smtc_de_busy = 1;
-}
-
-/**********************************************************************
- *
- * deRotatePattern
- *
- * Purpose
- * Rotate the given pattern if necessary
- *
- * Parameters
- * [in]
- * pPattern - Pointer to DE_SURFACE structure containing
- * pattern attributes
- * patternX - X position (0-7) of pattern origin
- * patternY - Y position (0-7) of pattern origin
- *
- * [out]
- * pattern_dstaddr - Pointer to pre-allocated buffer containing
- * rotated pattern
- *
- **********************************************************************/
-void deRotatePattern(unsigned char *pattern_dstaddr,
- unsigned long pattern_src_addr,
- unsigned long pattern_BPP,
- unsigned long pattern_stride, int patternX, int patternY)
-{
- unsigned int i;
- unsigned long pattern[PATTERN_WIDTH * PATTERN_HEIGHT];
- unsigned int x, y;
- unsigned char *pjPatByte;
-
- if (pattern_dstaddr != NULL) {
- deWaitForNotBusy();
-
- if (patternX || patternY) {
- /* Rotate pattern */
- pjPatByte = (unsigned char *)pattern;
-
- switch (pattern_BPP) {
- case 8:
- {
- for (y = 0; y < 8; y++) {
- unsigned char *pjBuffer =
- pattern_dstaddr +
- ((patternY + y) & 7) * 8;
- for (x = 0; x < 8; x++) {
- pjBuffer[(patternX +
- x) & 7] =
- pjPatByte[x];
- }
- pjPatByte += pattern_stride;
- }
- break;
- }
-
- case 16:
- {
- for (y = 0; y < 8; y++) {
- unsigned short *pjBuffer =
- (unsigned short *)
- pattern_dstaddr +
- ((patternY + y) & 7) * 8;
- for (x = 0; x < 8; x++) {
- pjBuffer[(patternX +
- x) & 7] =
- ((unsigned short *)
- pjPatByte)[x];
- }
- pjPatByte += pattern_stride;
- }
- break;
- }
-
- case 32:
- {
- for (y = 0; y < 8; y++) {
- unsigned long *pjBuffer =
- (unsigned long *)
- pattern_dstaddr +
- ((patternY + y) & 7) * 8;
- for (x = 0; x < 8; x++) {
- pjBuffer[(patternX +
- x) & 7] =
- ((unsigned long *)
- pjPatByte)[x];
- }
- pjPatByte += pattern_stride;
- }
- break;
- }
- }
- } else {
- /*Don't rotate,just copy pattern into pattern_dstaddr*/
- for (i = 0; i < (pattern_BPP * 2); i++) {
- ((unsigned long *)pattern_dstaddr)[i] =
- pattern[i];
- }
- }
-
- }
-}
-
-/**********************************************************************
- *
- * deCopy
- *
- * Purpose
- * Copy a rectangular area of the source surface to a destination surface
- *
- * Remarks
- * Source bitmap must have the same color depth (BPP) as the destination
- * bitmap.
- *
-**********************************************************************/
-void deCopy(unsigned long dst_base,
- unsigned long dst_pitch,
- unsigned long dst_BPP,
- unsigned long dst_X,
- unsigned long dst_Y,
- unsigned long dst_width,
- unsigned long dst_height,
- unsigned long src_base,
- unsigned long src_pitch,
- unsigned long src_X,
- unsigned long src_Y, pTransparent pTransp, unsigned char nROP2)
-{
- unsigned long nDirection = 0;
- unsigned long nTransparent = 0;
- /* Direction of ROP2 operation:
- * 1 = Left to Right,
- * (-1) = Right to Left
- */
- unsigned long opSign = 1;
- /* xWidth is in pixels */
- unsigned long xWidth = 192 / (dst_BPP / 8);
- unsigned long de_ctrl = 0;
-
- deWaitForNotBusy();
-
- SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE,
- FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS,
- dst_base));
-
- SMTC_write2Dreg(DE_WINDOW_SOURCE_BASE,
- FIELD_VALUE(0, DE_WINDOW_SOURCE_BASE, ADDRESS,
- src_base));
-
- if (dst_pitch && src_pitch) {
- SMTC_write2Dreg(DE_PITCH,
- FIELD_VALUE(0, DE_PITCH, DESTINATION,
- dst_pitch) | FIELD_VALUE(0,
- DE_PITCH,
- SOURCE,
- src_pitch));
-
- SMTC_write2Dreg(DE_WINDOW_WIDTH,
- FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
- dst_pitch) | FIELD_VALUE(0,
- DE_WINDOW_WIDTH,
- SOURCE,
- src_pitch));
- }
-
- /* Set transparent bits if necessary */
- if (pTransp != NULL) {
- nTransparent =
- pTransp->match | pTransp->select | pTransp->control;
-
- /* Set color compare register */
- SMTC_write2Dreg(DE_COLOR_COMPARE,
- FIELD_VALUE(0, DE_COLOR_COMPARE, COLOR,
- pTransp->color));
- }
-
- /* Determine direction of operation */
- if (src_Y < dst_Y) {
- /* +----------+
- |S |
- | +----------+
- | | | |
- | | | |
- +---|------+ |
- | D |
- +----------+ */
-
- nDirection = BOTTOM_TO_TOP;
- } else if (src_Y > dst_Y) {
- /* +----------+
- |D |
- | +----------+
- | | | |
- | | | |
- +---|------+ |
- | S |
- +----------+ */
-
- nDirection = TOP_TO_BOTTOM;
- } else {
- /* src_Y == dst_Y */
-
- if (src_X <= dst_X) {
- /* +------+---+------+
- |S | | D|
- | | | |
- | | | |
- | | | |
- +------+---+------+ */
-
- nDirection = RIGHT_TO_LEFT;
- } else {
- /* src_X > dst_X */
-
- /* +------+---+------+
- |D | | S|
- | | | |
- | | | |
- | | | |
- +------+---+------+ */
-
- nDirection = LEFT_TO_RIGHT;
- }
- }
-
- if ((nDirection == BOTTOM_TO_TOP) || (nDirection == RIGHT_TO_LEFT)) {
- src_X += dst_width - 1;
- src_Y += dst_height - 1;
- dst_X += dst_width - 1;
- dst_Y += dst_height - 1;
- opSign = (-1);
- }
-
- if (dst_BPP >= 24) {
- src_X *= 3;
- src_Y *= 3;
- dst_X *= 3;
- dst_Y *= 3;
- dst_width *= 3;
- if ((nDirection == BOTTOM_TO_TOP)
- || (nDirection == RIGHT_TO_LEFT)) {
- src_X += 2;
- dst_X += 2;
- }
- }
-
- /* Workaround for 192 byte hw bug */
- if ((nROP2 != 0x0C) && ((dst_width * (dst_BPP / 8)) >= 192)) {
- /*
- * Perform the ROP2 operation in chunks of (xWidth *
- * dst_height)
- */
- while (1) {
- deWaitForNotBusy();
-
- SMTC_write2Dreg(DE_SOURCE,
- FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
- FIELD_VALUE(0, DE_SOURCE, X_K1, src_X) |
- FIELD_VALUE(0, DE_SOURCE, Y_K2, src_Y));
-
- SMTC_write2Dreg(DE_DESTINATION,
- FIELD_SET(0, DE_DESTINATION, WRAP,
- DISABLE) | FIELD_VALUE(0,
- DE_DESTINATION,
- X,
- dst_X)
- | FIELD_VALUE(0, DE_DESTINATION, Y,
- dst_Y));
-
- SMTC_write2Dreg(DE_DIMENSION,
- FIELD_VALUE(0, DE_DIMENSION, X,
- xWidth) | FIELD_VALUE(0,
- DE_DIMENSION,
- Y_ET,
- dst_height));
-
- de_ctrl =
- FIELD_VALUE(0, DE_CONTROL, ROP,
- nROP2) | nTransparent | FIELD_SET(0,
- DE_CONTROL,
- ROP_SELECT,
- ROP2)
- | FIELD_SET(0, DE_CONTROL, COMMAND,
- BITBLT) | ((nDirection ==
- 1) ? FIELD_SET(0,
- DE_CONTROL,
- DIRECTION,
- RIGHT_TO_LEFT)
- : FIELD_SET(0, DE_CONTROL,
- DIRECTION,
- LEFT_TO_RIGHT)) |
- FIELD_SET(0, DE_CONTROL, STATUS, START);
-
- SMTC_write2Dreg(DE_CONTROL, de_ctrl);
-
- src_X += (opSign * xWidth);
- dst_X += (opSign * xWidth);
- dst_width -= xWidth;
-
- if (dst_width <= 0) {
- /* ROP2 operation is complete */
- break;
- }
-
- if (xWidth > dst_width)
- xWidth = dst_width;
- }
- } else {
- deWaitForNotBusy();
- SMTC_write2Dreg(DE_SOURCE,
- FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
- FIELD_VALUE(0, DE_SOURCE, X_K1, src_X) |
- FIELD_VALUE(0, DE_SOURCE, Y_K2, src_Y));
-
- SMTC_write2Dreg(DE_DESTINATION,
- FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
- FIELD_VALUE(0, DE_DESTINATION, X, dst_X) |
- FIELD_VALUE(0, DE_DESTINATION, Y, dst_Y));
-
- SMTC_write2Dreg(DE_DIMENSION,
- FIELD_VALUE(0, DE_DIMENSION, X, dst_width) |
- FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height));
-
- de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, nROP2) |
- nTransparent |
- FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
- FIELD_SET(0, DE_CONTROL, COMMAND, BITBLT) |
- ((nDirection == 1) ? FIELD_SET(0, DE_CONTROL, DIRECTION,
- RIGHT_TO_LEFT)
- : FIELD_SET(0, DE_CONTROL, DIRECTION,
- LEFT_TO_RIGHT)) | FIELD_SET(0, DE_CONTROL,
- STATUS, START);
- SMTC_write2Dreg(DE_CONTROL, de_ctrl);
- }
-
- smtc_de_busy = 1;
-}
-
-/*
- * This function sets the pixel format that will apply to the 2D Engine.
- */
-void deSetPixelFormat(unsigned long bpp)
-{
- unsigned long de_format;
-
- de_format = SMTC_read2Dreg(DE_STRETCH_FORMAT);
-
- switch (bpp) {
- case 8:
- de_format =
- FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 8);
- break;
- default:
- case 16:
- de_format =
- FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 16);
- break;
- case 32:
- de_format =
- FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 32);
- break;
- }
-
- SMTC_write2Dreg(DE_STRETCH_FORMAT, de_format);
-}
-
-/*
- * System memory to Video memory monochrome expansion.
- *
- * Source is monochrome image in system memory. This function expands the
- * monochrome data to color image in video memory.
- */
-
-long deSystemMem2VideoMemMonoBlt(const char *pSrcbuf,
- long srcDelta,
- unsigned long startBit,
- unsigned long dBase,
- unsigned long dPitch,
- unsigned long bpp,
- unsigned long dx, unsigned long dy,
- unsigned long width, unsigned long height,
- unsigned long fColor,
- unsigned long bColor,
- unsigned long rop2) {
- unsigned long bytePerPixel;
- unsigned long ulBytesPerScan;
- unsigned long ul4BytesPerScan;
- unsigned long ulBytesRemain;
- unsigned long de_ctrl = 0;
- unsigned char ajRemain[4];
- long i, j;
-
- bytePerPixel = bpp / 8;
-
- /* Just make sure the start bit is within legal range */
- startBit &= 7;
-
- ulBytesPerScan = (width + startBit + 7) / 8;
- ul4BytesPerScan = ulBytesPerScan & ~3;
- ulBytesRemain = ulBytesPerScan & 3;
-
- if (smtc_de_busy)
- deWaitForNotBusy();
-
- /*
- * 2D Source Base. Use 0 for HOST Blt.
- */
-
- SMTC_write2Dreg(DE_WINDOW_SOURCE_BASE, 0);
-
- /*
- * 2D Destination Base.
- *
- * It is an address offset (128 bit aligned) from the beginning of
- * frame buffer.
- */
-
- SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE, dBase);
-
- if (dPitch) {
-
- /*
- * Program pitch (distance between the 1st points of two
- * adjacent lines).
- *
- * Note that input pitch is BYTE value, but the 2D Pitch
- * register uses pixel values. Need Byte to pixel convertion.
- */
-
- SMTC_write2Dreg(DE_PITCH,
- FIELD_VALUE(0, DE_PITCH, DESTINATION,
- dPitch /
- bytePerPixel) | FIELD_VALUE(0,
- DE_PITCH,
- SOURCE,
- dPitch /
- bytePerPixel));
-
- /* Screen Window width in Pixels.
- *
- * 2D engine uses this value to calculate the linear address in
- * frame buffer for a given point.
- */
-
- SMTC_write2Dreg(DE_WINDOW_WIDTH,
- FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION,
- (dPitch /
- bytePerPixel)) | FIELD_VALUE(0,
- DE_WINDOW_WIDTH,
- SOURCE,
- (dPitch
- /
- bytePerPixel)));
- }
- /* Note: For 2D Source in Host Write, only X_K1 field is needed, and
- * Y_K2 field is not used. For mono bitmap, use startBit for X_K1.
- */
-
- SMTC_write2Dreg(DE_SOURCE,
- FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
- FIELD_VALUE(0, DE_SOURCE, X_K1, startBit) |
- FIELD_VALUE(0, DE_SOURCE, Y_K2, 0));
-
- SMTC_write2Dreg(DE_DESTINATION,
- FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
- FIELD_VALUE(0, DE_DESTINATION, X, dx) |
- FIELD_VALUE(0, DE_DESTINATION, Y, dy));
-
- SMTC_write2Dreg(DE_DIMENSION,
- FIELD_VALUE(0, DE_DIMENSION, X, width) |
- FIELD_VALUE(0, DE_DIMENSION, Y_ET, height));
-
- SMTC_write2Dreg(DE_FOREGROUND, fColor);
- SMTC_write2Dreg(DE_BACKGROUND, bColor);
-
- if (bpp)
- deSetPixelFormat(bpp);
- /* Set the pixel format of the destination */
-
- de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, rop2) |
- FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
- FIELD_SET(0, DE_CONTROL, COMMAND, HOST_WRITE) |
- FIELD_SET(0, DE_CONTROL, HOST, MONO) |
- FIELD_SET(0, DE_CONTROL, STATUS, START);
-
- SMTC_write2Dreg(DE_CONTROL, de_ctrl | deGetTransparency());
-
- /* Write MONO data (line by line) to 2D Engine data port */
- for (i = 0; i < height; i++) {
- /* For each line, send the data in chunks of 4 bytes */
- for (j = 0; j < (ul4BytesPerScan / 4); j++)
- SMTC_write2Ddataport(0,
- *(unsigned long *)(pSrcbuf +
- (j * 4)));
-
- if (ulBytesRemain) {
- memcpy(ajRemain, pSrcbuf + ul4BytesPerScan,
- ulBytesRemain);
- SMTC_write2Ddataport(0, *(unsigned long *)ajRemain);
- }
-
- pSrcbuf += srcDelta;
- }
- smtc_de_busy = 1;
-
- return 0;
-}
-
-/*
- * This function gets the transparency status from DE_CONTROL register.
- * It returns a double word with the transparent fields properly set,
- * while other fields are 0.
- */
-unsigned long deGetTransparency(void)
-{
- unsigned long de_ctrl;
-
- de_ctrl = SMTC_read2Dreg(DE_CONTROL);
-
- de_ctrl &=
- FIELD_MASK(DE_CONTROL_TRANSPARENCY_MATCH) |
- FIELD_MASK(DE_CONTROL_TRANSPARENCY_SELECT) |
- FIELD_MASK(DE_CONTROL_TRANSPARENCY);
-
- return de_ctrl;
-}
diff --git a/drivers/staging/sm7xx/smtc2d.h b/drivers/staging/sm7xx/smtc2d.h
deleted file mode 100644
index 02b4fa29136..00000000000
--- a/drivers/staging/sm7xx/smtc2d.h
+++ /dev/null
@@ -1,530 +0,0 @@
-/*
- * Silicon Motion SM712 2D drawing engine functions.
- *
- * Copyright (C) 2006 Silicon Motion Technology Corp.
- * Author: Ge Wang, gewang@siliconmotion.com
- *
- * Copyright (C) 2009 Lemote, Inc.
- * Author: Wu Zhangjin, wuzhangjin@gmail.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.
- */
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-/* Internal macros */
-
-#define _F_START(f) (0 ? f)
-#define _F_END(f) (1 ? f)
-#define _F_SIZE(f) (1 + _F_END(f) - _F_START(f))
-#define _F_MASK(f) (((1ULL << _F_SIZE(f)) - 1) << _F_START(f))
-#define _F_NORMALIZE(v, f) (((v) & _F_MASK(f)) >> _F_START(f))
-#define _F_DENORMALIZE(v, f) (((v) << _F_START(f)) & _F_MASK(f))
-
-/* Global macros */
-
-#define FIELD_GET(x, reg, field) \
-( \
- _F_NORMALIZE((x), reg ## _ ## field) \
-)
-
-#define FIELD_SET(x, reg, field, value) \
-( \
- (x & ~_F_MASK(reg ## _ ## field)) \
- | _F_DENORMALIZE(reg ## _ ## field ## _ ## value, reg ## _ ## field) \
-)
-
-#define FIELD_VALUE(x, reg, field, value) \
-( \
- (x & ~_F_MASK(reg ## _ ## field)) \
- | _F_DENORMALIZE(value, reg ## _ ## field) \
-)
-
-#define FIELD_CLEAR(reg, field) \
-( \
- ~_F_MASK(reg ## _ ## field) \
-)
-
-/* Field Macros */
-
-#define FIELD_START(field) (0 ? field)
-#define FIELD_END(field) (1 ? field)
-#define FIELD_SIZE(field) \
- (1 + FIELD_END(field) - FIELD_START(field))
-
-#define FIELD_MASK(field) \
- (((1 << (FIELD_SIZE(field)-1)) \
- | ((1 << (FIELD_SIZE(field)-1)) - 1)) \
- << FIELD_START(field))
-
-#define FIELD_NORMALIZE(reg, field) \
- (((reg) & FIELD_MASK(field)) >> FIELD_START(field))
-
-#define FIELD_DENORMALIZE(field, value) \
- (((value) << FIELD_START(field)) & FIELD_MASK(field))
-
-#define FIELD_INIT(reg, field, value) \
- FIELD_DENORMALIZE(reg ## _ ## field, \
- reg ## _ ## field ## _ ## value)
-
-#define FIELD_INIT_VAL(reg, field, value) \
- (FIELD_DENORMALIZE(reg ## _ ## field, value))
-
-#define FIELD_VAL_SET(x, r, f, v) ({ \
- x = (x & ~FIELD_MASK(r ## _ ## f)) \
- | FIELD_DENORMALIZE(r ## _ ## f, r ## _ ## f ## _ ## v) \
-})
-
-#define RGB(r, g, b) ((unsigned long)(((r) << 16) | ((g) << 8) | (b)))
-
-/* Transparent info definition */
-typedef struct {
- unsigned long match; /* Matching pixel is OPAQUE/TRANSPARENT */
- unsigned long select; /* Transparency controlled by SRC/DST */
- unsigned long control; /* ENABLE/DISABLE transparency */
- unsigned long color; /* Transparent color */
-} Transparent, *pTransparent;
-
-#define PIXEL_DEPTH_1_BP 0 /* 1 bit per pixel */
-#define PIXEL_DEPTH_8_BPP 1 /* 8 bits per pixel */
-#define PIXEL_DEPTH_16_BPP 2 /* 16 bits per pixel */
-#define PIXEL_DEPTH_32_BPP 3 /* 32 bits per pixel */
-#define PIXEL_DEPTH_YUV422 8 /* 16 bits per pixel YUV422 */
-#define PIXEL_DEPTH_YUV420 9 /* 16 bits per pixel YUV420 */
-
-#define PATTERN_WIDTH 8
-#define PATTERN_HEIGHT 8
-
-#define TOP_TO_BOTTOM 0
-#define BOTTOM_TO_TOP 1
-#define RIGHT_TO_LEFT BOTTOM_TO_TOP
-#define LEFT_TO_RIGHT TOP_TO_BOTTOM
-
-/* Constants used in Transparent structure */
-#define MATCH_OPAQUE 0x00000000
-#define MATCH_TRANSPARENT 0x00000400
-#define SOURCE 0x00000000
-#define DESTINATION 0x00000200
-
-/* 2D registers. */
-
-#define DE_SOURCE 0x000000
-#define DE_SOURCE_WRAP 31 : 31
-#define DE_SOURCE_WRAP_DISABLE 0
-#define DE_SOURCE_WRAP_ENABLE 1
-#define DE_SOURCE_X_K1 29 : 16
-#define DE_SOURCE_Y_K2 15 : 0
-
-#define DE_DESTINATION 0x000004
-#define DE_DESTINATION_WRAP 31 : 31
-#define DE_DESTINATION_WRAP_DISABLE 0
-#define DE_DESTINATION_WRAP_ENABLE 1
-#define DE_DESTINATION_X 28 : 16
-#define DE_DESTINATION_Y 15 : 0
-
-#define DE_DIMENSION 0x000008
-#define DE_DIMENSION_X 28 : 16
-#define DE_DIMENSION_Y_ET 15 : 0
-
-#define DE_CONTROL 0x00000C
-#define DE_CONTROL_STATUS 31 : 31
-#define DE_CONTROL_STATUS_STOP 0
-#define DE_CONTROL_STATUS_START 1
-#define DE_CONTROL_PATTERN 30 : 30
-#define DE_CONTROL_PATTERN_MONO 0
-#define DE_CONTROL_PATTERN_COLOR 1
-#define DE_CONTROL_UPDATE_DESTINATION_X 29 : 29
-#define DE_CONTROL_UPDATE_DESTINATION_X_DISABLE 0
-#define DE_CONTROL_UPDATE_DESTINATION_X_ENABLE 1
-#define DE_CONTROL_QUICK_START 28 : 28
-#define DE_CONTROL_QUICK_START_DISABLE 0
-#define DE_CONTROL_QUICK_START_ENABLE 1
-#define DE_CONTROL_DIRECTION 27 : 27
-#define DE_CONTROL_DIRECTION_LEFT_TO_RIGHT 0
-#define DE_CONTROL_DIRECTION_RIGHT_TO_LEFT 1
-#define DE_CONTROL_MAJOR 26 : 26
-#define DE_CONTROL_MAJOR_X 0
-#define DE_CONTROL_MAJOR_Y 1
-#define DE_CONTROL_STEP_X 25 : 25
-#define DE_CONTROL_STEP_X_POSITIVE 1
-#define DE_CONTROL_STEP_X_NEGATIVE 0
-#define DE_CONTROL_STEP_Y 24 : 24
-#define DE_CONTROL_STEP_Y_POSITIVE 1
-#define DE_CONTROL_STEP_Y_NEGATIVE 0
-#define DE_CONTROL_STRETCH 23 : 23
-#define DE_CONTROL_STRETCH_DISABLE 0
-#define DE_CONTROL_STRETCH_ENABLE 1
-#define DE_CONTROL_HOST 22 : 22
-#define DE_CONTROL_HOST_COLOR 0
-#define DE_CONTROL_HOST_MONO 1
-#define DE_CONTROL_LAST_PIXEL 21 : 21
-#define DE_CONTROL_LAST_PIXEL_OFF 0
-#define DE_CONTROL_LAST_PIXEL_ON 1
-#define DE_CONTROL_COMMAND 20 : 16
-#define DE_CONTROL_COMMAND_BITBLT 0
-#define DE_CONTROL_COMMAND_RECTANGLE_FILL 1
-#define DE_CONTROL_COMMAND_DE_TILE 2
-#define DE_CONTROL_COMMAND_TRAPEZOID_FILL 3
-#define DE_CONTROL_COMMAND_ALPHA_BLEND 4
-#define DE_CONTROL_COMMAND_RLE_STRIP 5
-#define DE_CONTROL_COMMAND_SHORT_STROKE 6
-#define DE_CONTROL_COMMAND_LINE_DRAW 7
-#define DE_CONTROL_COMMAND_HOST_WRITE 8
-#define DE_CONTROL_COMMAND_HOST_READ 9
-#define DE_CONTROL_COMMAND_HOST_WRITE_BOTTOM_UP 10
-#define DE_CONTROL_COMMAND_ROTATE 11
-#define DE_CONTROL_COMMAND_FONT 12
-#define DE_CONTROL_COMMAND_TEXTURE_LOAD 15
-#define DE_CONTROL_ROP_SELECT 15 : 15
-#define DE_CONTROL_ROP_SELECT_ROP3 0
-#define DE_CONTROL_ROP_SELECT_ROP2 1
-#define DE_CONTROL_ROP2_SOURCE 14 : 14
-#define DE_CONTROL_ROP2_SOURCE_BITMAP 0
-#define DE_CONTROL_ROP2_SOURCE_PATTERN 1
-#define DE_CONTROL_MONO_DATA 13 : 12
-#define DE_CONTROL_MONO_DATA_NOT_PACKED 0
-#define DE_CONTROL_MONO_DATA_8_PACKED 1
-#define DE_CONTROL_MONO_DATA_16_PACKED 2
-#define DE_CONTROL_MONO_DATA_32_PACKED 3
-#define DE_CONTROL_REPEAT_ROTATE 11 : 11
-#define DE_CONTROL_REPEAT_ROTATE_DISABLE 0
-#define DE_CONTROL_REPEAT_ROTATE_ENABLE 1
-#define DE_CONTROL_TRANSPARENCY_MATCH 10 : 10
-#define DE_CONTROL_TRANSPARENCY_MATCH_OPAQUE 0
-#define DE_CONTROL_TRANSPARENCY_MATCH_TRANSPARENT 1
-#define DE_CONTROL_TRANSPARENCY_SELECT 9 : 9
-#define DE_CONTROL_TRANSPARENCY_SELECT_SOURCE 0
-#define DE_CONTROL_TRANSPARENCY_SELECT_DESTINATION 1
-#define DE_CONTROL_TRANSPARENCY 8 : 8
-#define DE_CONTROL_TRANSPARENCY_DISABLE 0
-#define DE_CONTROL_TRANSPARENCY_ENABLE 1
-#define DE_CONTROL_ROP 7 : 0
-
-/* Pseudo fields. */
-
-#define DE_CONTROL_SHORT_STROKE_DIR 27 : 24
-#define DE_CONTROL_SHORT_STROKE_DIR_225 0
-#define DE_CONTROL_SHORT_STROKE_DIR_135 1
-#define DE_CONTROL_SHORT_STROKE_DIR_315 2
-#define DE_CONTROL_SHORT_STROKE_DIR_45 3
-#define DE_CONTROL_SHORT_STROKE_DIR_270 4
-#define DE_CONTROL_SHORT_STROKE_DIR_90 5
-#define DE_CONTROL_SHORT_STROKE_DIR_180 8
-#define DE_CONTROL_SHORT_STROKE_DIR_0 10
-#define DE_CONTROL_ROTATION 25 : 24
-#define DE_CONTROL_ROTATION_0 0
-#define DE_CONTROL_ROTATION_270 1
-#define DE_CONTROL_ROTATION_90 2
-#define DE_CONTROL_ROTATION_180 3
-
-#define DE_PITCH 0x000010
-#define DE_PITCH_DESTINATION 28 : 16
-#define DE_PITCH_SOURCE 12 : 0
-
-#define DE_FOREGROUND 0x000014
-#define DE_FOREGROUND_COLOR 31 : 0
-
-#define DE_BACKGROUND 0x000018
-#define DE_BACKGROUND_COLOR 31 : 0
-
-#define DE_STRETCH_FORMAT 0x00001C
-#define DE_STRETCH_FORMAT_PATTERN_XY 30 : 30
-#define DE_STRETCH_FORMAT_PATTERN_XY_NORMAL 0
-#define DE_STRETCH_FORMAT_PATTERN_XY_OVERWRITE 1
-#define DE_STRETCH_FORMAT_PATTERN_Y 29 : 27
-#define DE_STRETCH_FORMAT_PATTERN_X 25 : 23
-#define DE_STRETCH_FORMAT_PIXEL_FORMAT 21 : 20
-#define DE_STRETCH_FORMAT_PIXEL_FORMAT_8 0
-#define DE_STRETCH_FORMAT_PIXEL_FORMAT_16 1
-#define DE_STRETCH_FORMAT_PIXEL_FORMAT_24 3
-#define DE_STRETCH_FORMAT_PIXEL_FORMAT_32 2
-#define DE_STRETCH_FORMAT_ADDRESSING 19 : 16
-#define DE_STRETCH_FORMAT_ADDRESSING_XY 0
-#define DE_STRETCH_FORMAT_ADDRESSING_LINEAR 15
-#define DE_STRETCH_FORMAT_SOURCE_HEIGHT 11 : 0
-
-#define DE_COLOR_COMPARE 0x000020
-#define DE_COLOR_COMPARE_COLOR 23 : 0
-
-#define DE_COLOR_COMPARE_MASK 0x000024
-#define DE_COLOR_COMPARE_MASK_MASKS 23 : 0
-
-#define DE_MASKS 0x000028
-#define DE_MASKS_BYTE_MASK 31 : 16
-#define DE_MASKS_BIT_MASK 15 : 0
-
-#define DE_CLIP_TL 0x00002C
-#define DE_CLIP_TL_TOP 31 : 16
-#define DE_CLIP_TL_STATUS 13 : 13
-#define DE_CLIP_TL_STATUS_DISABLE 0
-#define DE_CLIP_TL_STATUS_ENABLE 1
-#define DE_CLIP_TL_INHIBIT 12 : 12
-#define DE_CLIP_TL_INHIBIT_OUTSIDE 0
-#define DE_CLIP_TL_INHIBIT_INSIDE 1
-#define DE_CLIP_TL_LEFT 11 : 0
-
-#define DE_CLIP_BR 0x000030
-#define DE_CLIP_BR_BOTTOM 31 : 16
-#define DE_CLIP_BR_RIGHT 12 : 0
-
-#define DE_MONO_PATTERN_LOW 0x000034
-#define DE_MONO_PATTERN_LOW_PATTERN 31 : 0
-
-#define DE_MONO_PATTERN_HIGH 0x000038
-#define DE_MONO_PATTERN_HIGH_PATTERN 31 : 0
-
-#define DE_WINDOW_WIDTH 0x00003C
-#define DE_WINDOW_WIDTH_DESTINATION 28 : 16
-#define DE_WINDOW_WIDTH_SOURCE 12 : 0
-
-#define DE_WINDOW_SOURCE_BASE 0x000040
-#define DE_WINDOW_SOURCE_BASE_EXT 27 : 27
-#define DE_WINDOW_SOURCE_BASE_EXT_LOCAL 0
-#define DE_WINDOW_SOURCE_BASE_EXT_EXTERNAL 1
-#define DE_WINDOW_SOURCE_BASE_CS 26 : 26
-#define DE_WINDOW_SOURCE_BASE_CS_0 0
-#define DE_WINDOW_SOURCE_BASE_CS_1 1
-#define DE_WINDOW_SOURCE_BASE_ADDRESS 25 : 0
-
-#define DE_WINDOW_DESTINATION_BASE 0x000044
-#define DE_WINDOW_DESTINATION_BASE_EXT 27 : 27
-#define DE_WINDOW_DESTINATION_BASE_EXT_LOCAL 0
-#define DE_WINDOW_DESTINATION_BASE_EXT_EXTERNAL 1
-#define DE_WINDOW_DESTINATION_BASE_CS 26 : 26
-#define DE_WINDOW_DESTINATION_BASE_CS_0 0
-#define DE_WINDOW_DESTINATION_BASE_CS_1 1
-#define DE_WINDOW_DESTINATION_BASE_ADDRESS 25 : 0
-
-#define DE_ALPHA 0x000048
-#define DE_ALPHA_VALUE 7 : 0
-
-#define DE_WRAP 0x00004C
-#define DE_WRAP_X 31 : 16
-#define DE_WRAP_Y 15 : 0
-
-#define DE_STATUS 0x000050
-#define DE_STATUS_CSC 1 : 1
-#define DE_STATUS_CSC_CLEAR 0
-#define DE_STATUS_CSC_NOT_ACTIVE 0
-#define DE_STATUS_CSC_ACTIVE 1
-#define DE_STATUS_2D 0 : 0
-#define DE_STATUS_2D_CLEAR 0
-#define DE_STATUS_2D_NOT_ACTIVE 0
-#define DE_STATUS_2D_ACTIVE 1
-
-/* Color Space Conversion registers. */
-
-#define CSC_Y_SOURCE_BASE 0x0000C8
-#define CSC_Y_SOURCE_BASE_EXT 27 : 27
-#define CSC_Y_SOURCE_BASE_EXT_LOCAL 0
-#define CSC_Y_SOURCE_BASE_EXT_EXTERNAL 1
-#define CSC_Y_SOURCE_BASE_CS 26 : 26
-#define CSC_Y_SOURCE_BASE_CS_0 0
-#define CSC_Y_SOURCE_BASE_CS_1 1
-#define CSC_Y_SOURCE_BASE_ADDRESS 25 : 0
-
-#define CSC_CONSTANTS 0x0000CC
-#define CSC_CONSTANTS_Y 31 : 24
-#define CSC_CONSTANTS_R 23 : 16
-#define CSC_CONSTANTS_G 15 : 8
-#define CSC_CONSTANTS_B 7 : 0
-
-#define CSC_Y_SOURCE_X 0x0000D0
-#define CSC_Y_SOURCE_X_INTEGER 26 : 16
-#define CSC_Y_SOURCE_X_FRACTION 15 : 3
-
-#define CSC_Y_SOURCE_Y 0x0000D4
-#define CSC_Y_SOURCE_Y_INTEGER 27 : 16
-#define CSC_Y_SOURCE_Y_FRACTION 15 : 3
-
-#define CSC_U_SOURCE_BASE 0x0000D8
-#define CSC_U_SOURCE_BASE_EXT 27 : 27
-#define CSC_U_SOURCE_BASE_EXT_LOCAL 0
-#define CSC_U_SOURCE_BASE_EXT_EXTERNAL 1
-#define CSC_U_SOURCE_BASE_CS 26 : 26
-#define CSC_U_SOURCE_BASE_CS_0 0
-#define CSC_U_SOURCE_BASE_CS_1 1
-#define CSC_U_SOURCE_BASE_ADDRESS 25 : 0
-
-#define CSC_V_SOURCE_BASE 0x0000DC
-#define CSC_V_SOURCE_BASE_EXT 27 : 27
-#define CSC_V_SOURCE_BASE_EXT_LOCAL 0
-#define CSC_V_SOURCE_BASE_EXT_EXTERNAL 1
-#define CSC_V_SOURCE_BASE_CS 26 : 26
-#define CSC_V_SOURCE_BASE_CS_0 0
-#define CSC_V_SOURCE_BASE_CS_1 1
-#define CSC_V_SOURCE_BASE_ADDRESS 25 : 0
-
-#define CSC_SOURCE_DIMENSION 0x0000E0
-#define CSC_SOURCE_DIMENSION_X 31 : 16
-#define CSC_SOURCE_DIMENSION_Y 15 : 0
-
-#define CSC_SOURCE_PITCH 0x0000E4
-#define CSC_SOURCE_PITCH_Y 31 : 16
-#define CSC_SOURCE_PITCH_UV 15 : 0
-
-#define CSC_DESTINATION 0x0000E8
-#define CSC_DESTINATION_WRAP 31 : 31
-#define CSC_DESTINATION_WRAP_DISABLE 0
-#define CSC_DESTINATION_WRAP_ENABLE 1
-#define CSC_DESTINATION_X 27 : 16
-#define CSC_DESTINATION_Y 11 : 0
-
-#define CSC_DESTINATION_DIMENSION 0x0000EC
-#define CSC_DESTINATION_DIMENSION_X 31 : 16
-#define CSC_DESTINATION_DIMENSION_Y 15 : 0
-
-#define CSC_DESTINATION_PITCH 0x0000F0
-#define CSC_DESTINATION_PITCH_X 31 : 16
-#define CSC_DESTINATION_PITCH_Y 15 : 0
-
-#define CSC_SCALE_FACTOR 0x0000F4
-#define CSC_SCALE_FACTOR_HORIZONTAL 31 : 16
-#define CSC_SCALE_FACTOR_VERTICAL 15 : 0
-
-#define CSC_DESTINATION_BASE 0x0000F8
-#define CSC_DESTINATION_BASE_EXT 27 : 27
-#define CSC_DESTINATION_BASE_EXT_LOCAL 0
-#define CSC_DESTINATION_BASE_EXT_EXTERNAL 1
-#define CSC_DESTINATION_BASE_CS 26 : 26
-#define CSC_DESTINATION_BASE_CS_0 0
-#define CSC_DESTINATION_BASE_CS_1 1
-#define CSC_DESTINATION_BASE_ADDRESS 25 : 0
-
-#define CSC_CONTROL 0x0000FC
-#define CSC_CONTROL_STATUS 31 : 31
-#define CSC_CONTROL_STATUS_STOP 0
-#define CSC_CONTROL_STATUS_START 1
-#define CSC_CONTROL_SOURCE_FORMAT 30 : 28
-#define CSC_CONTROL_SOURCE_FORMAT_YUV422 0
-#define CSC_CONTROL_SOURCE_FORMAT_YUV420I 1
-#define CSC_CONTROL_SOURCE_FORMAT_YUV420 2
-#define CSC_CONTROL_SOURCE_FORMAT_YVU9 3
-#define CSC_CONTROL_SOURCE_FORMAT_IYU1 4
-#define CSC_CONTROL_SOURCE_FORMAT_IYU2 5
-#define CSC_CONTROL_SOURCE_FORMAT_RGB565 6
-#define CSC_CONTROL_SOURCE_FORMAT_RGB8888 7
-#define CSC_CONTROL_DESTINATION_FORMAT 27 : 26
-#define CSC_CONTROL_DESTINATION_FORMAT_RGB565 0
-#define CSC_CONTROL_DESTINATION_FORMAT_RGB8888 1
-#define CSC_CONTROL_HORIZONTAL_FILTER 25 : 25
-#define CSC_CONTROL_HORIZONTAL_FILTER_DISABLE 0
-#define CSC_CONTROL_HORIZONTAL_FILTER_ENABLE 1
-#define CSC_CONTROL_VERTICAL_FILTER 24 : 24
-#define CSC_CONTROL_VERTICAL_FILTER_DISABLE 0
-#define CSC_CONTROL_VERTICAL_FILTER_ENABLE 1
-#define CSC_CONTROL_BYTE_ORDER 23 : 23
-#define CSC_CONTROL_BYTE_ORDER_YUYV 0
-#define CSC_CONTROL_BYTE_ORDER_UYVY 1
-
-#define DE_DATA_PORT_501 0x110000
-#define DE_DATA_PORT_712 0x400000
-#define DE_DATA_PORT_722 0x6000
-
-/* point to virtual Memory Map IO starting address */
-extern char *smtc_RegBaseAddress;
-/* point to virtual video memory starting address */
-extern char *smtc_VRAMBaseAddress;
-extern unsigned char smtc_de_busy;
-
-extern unsigned long memRead32(unsigned long nOffset);
-extern void memWrite32(unsigned long nOffset, unsigned long nData);
-extern unsigned long SMTC_read2Dreg(unsigned long nOffset);
-
-/* 2D functions */
-extern void deInit(unsigned int nModeWidth, unsigned int nModeHeight,
- unsigned int bpp);
-
-extern void deWaitForNotBusy(void);
-
-extern void deVerticalLine(unsigned long dst_base,
- unsigned long dst_pitch,
- unsigned long nX,
- unsigned long nY,
- unsigned long dst_height,
- unsigned long nColor);
-
-extern void deHorizontalLine(unsigned long dst_base,
- unsigned long dst_pitch,
- unsigned long nX,
- unsigned long nY,
- unsigned long dst_width,
- unsigned long nColor);
-
-extern void deLine(unsigned long dst_base,
- unsigned long dst_pitch,
- unsigned long nX1,
- unsigned long nY1,
- unsigned long nX2,
- unsigned long nY2,
- unsigned long nColor);
-
-extern void deFillRect(unsigned long dst_base,
- unsigned long dst_pitch,
- unsigned long dst_X,
- unsigned long dst_Y,
- unsigned long dst_width,
- unsigned long dst_height,
- unsigned long nColor);
-
-extern void deRotatePattern(unsigned char *pattern_dstaddr,
- unsigned long pattern_src_addr,
- unsigned long pattern_BPP,
- unsigned long pattern_stride,
- int patternX,
- int patternY);
-
-extern void deCopy(unsigned long dst_base,
- unsigned long dst_pitch,
- unsigned long dst_BPP,
- unsigned long dst_X,
- unsigned long dst_Y,
- unsigned long dst_width,
- unsigned long dst_height,
- unsigned long src_base,
- unsigned long src_pitch,
- unsigned long src_X,
- unsigned long src_Y,
- pTransparent pTransp,
- unsigned char nROP2);
-
-/*
- * System memory to Video memory monochrome expansion.
- *
- * Source is monochrome image in system memory. This function expands the
- * monochrome data to color image in video memory.
- *
- * @pSrcbuf: pointer to start of source buffer in system memory
- * @srcDelta: Pitch value (in bytes) of the source buffer, +ive means top
- * down and -ive mean button up
- * @startBit: Mono data can start at any bit in a byte, this value should
- * be 0 to 7
- * @dBase: Address of destination : offset in frame buffer
- * @dPitch: Pitch value of destination surface in BYTE
- * @bpp: Color depth of destination surface
- * @dx, dy: Starting coordinate of destination surface
- * @width, height: width and height of rectange in pixel value
- * @fColor,bColor: Foreground, Background color (corresponding to a 1, 0 in
- * the monochrome data)
- * @rop2: ROP value
- */
-
-extern long deSystemMem2VideoMemMonoBlt(
- const char *pSrcbuf,
- long srcDelta,
- unsigned long startBit,
- unsigned long dBase,
- unsigned long dPitch,
- unsigned long bpp,
- unsigned long dx, unsigned long dy,
- unsigned long width, unsigned long height,
- unsigned long fColor,
- unsigned long bColor,
- unsigned long rop2);
-
-extern unsigned long deGetTransparency(void);
-extern void deSetPixelFormat(unsigned long bpp);
diff --git a/drivers/staging/sm7xx/smtcfb.c b/drivers/staging/sm7xx/smtcfb.c
index a4f6f49aef4..9c82a1a81cc 100644
--- a/drivers/staging/sm7xx/smtcfb.c
+++ b/drivers/staging/sm7xx/smtcfb.c
@@ -45,7 +45,6 @@
struct screen_info smtc_screen_info;
#include "smtcfb.h"
-#include "smtc2d.h"
#ifdef DEBUG
#define smdbg(format, arg...) printk(KERN_DEBUG format , ## arg)
@@ -120,10 +119,6 @@ static struct vesa_mode_table vesa_mode[] = {
char __iomem *smtc_RegBaseAddress; /* Memory Map IO starting address */
char __iomem *smtc_VRAMBaseAddress; /* video memory starting address */
-char *smtc_2DBaseAddress; /* 2D engine starting address */
-char *smtc_2Ddataport; /* 2D data port offset */
-short smtc_2Dacceleration;
-
static u32 colreg[17];
static struct par_info hw; /* hardware information */
@@ -135,16 +130,6 @@ u16 smtc_ChipIDs[] = {
#define numSMTCchipIDs (sizeof(smtc_ChipIDs) / sizeof(u16))
-void deWaitForNotBusy(void)
-{
- unsigned long i = 0x1000000;
- while (i--) {
- if ((smtc_seqr(0x16) & 0x18) == 0x10)
- break;
- }
- smtc_de_busy = 0;
-}
-
static void sm712_set_timing(struct smtcfb_info *sfb,
struct par_info *ppar_info)
{
@@ -324,7 +309,7 @@ static inline unsigned int chan_to_field(unsigned int chan,
return chan << bf->offset;
}
-static int smtcfb_blank(int blank_mode, struct fb_info *info)
+static int cfb_blank(int blank_mode, struct fb_info *info)
{
/* clear DPMS setting */
switch (blank_mode) {
@@ -622,93 +607,13 @@ smtcfb_write(struct fb_info *info, const char __user *buf, size_t count,
}
#endif /* ! __BIG_ENDIAN */
-#include "smtc2d.c"
-
-void smtcfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
-{
- struct par_info *p = (struct par_info *)info->par;
-
- if (smtc_2Dacceleration) {
- if (!area->width || !area->height)
- return;
-
- deCopy(p->BaseAddressInVRAM, 0, info->var.bits_per_pixel,
- area->dx, area->dy, area->width, area->height,
- p->BaseAddressInVRAM, 0, area->sx, area->sy, 0, 0xC);
-
- } else
- cfb_copyarea(info, area);
-}
-
-void smtcfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
- struct par_info *p = (struct par_info *)info->par;
-
- if (smtc_2Dacceleration) {
- if (!rect->width || !rect->height)
- return;
- if (info->var.bits_per_pixel >= 24)
- deFillRect(p->BaseAddressInVRAM, 0, rect->dx * 3,
- rect->dy * 3, rect->width * 3, rect->height,
- rect->color);
- else
- deFillRect(p->BaseAddressInVRAM, 0, rect->dx, rect->dy,
- rect->width, rect->height, rect->color);
- } else
- cfb_fillrect(info, rect);
-}
-
-void smtcfb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
- struct par_info *p = (struct par_info *)info->par;
- u32 bg_col = 0, fg_col = 0;
-
- if ((smtc_2Dacceleration) && (image->depth == 1)) {
- if (smtc_de_busy)
- deWaitForNotBusy();
-
- switch (info->var.bits_per_pixel) {
- case 8:
- bg_col = image->bg_color;
- fg_col = image->fg_color;
- break;
- case 16:
- bg_col =
- ((u32 *) (info->pseudo_palette))[image->bg_color];
- fg_col =
- ((u32 *) (info->pseudo_palette))[image->fg_color];
- break;
- case 32:
- bg_col =
- ((u32 *) (info->pseudo_palette))[image->bg_color];
- fg_col =
- ((u32 *) (info->pseudo_palette))[image->fg_color];
- break;
- }
-
- deSystemMem2VideoMemMonoBlt(
- image->data,
- image->width / 8,
- 0,
- p->BaseAddressInVRAM,
- 0,
- 0,
- image->dx, image->dy,
- image->width, image->height,
- fg_col, bg_col,
- 0x0C);
-
- } else
- cfb_imageblit(info, image);
-}
-
static struct fb_ops smtcfb_ops = {
.owner = THIS_MODULE,
.fb_setcolreg = smtc_setcolreg,
- .fb_blank = smtcfb_blank,
- .fb_fillrect = smtcfb_fillrect,
- .fb_imageblit = smtcfb_imageblit,
- .fb_copyarea = smtcfb_copyarea,
+ .fb_blank = cfb_blank,
+ .fb_fillrect = cfb_fillrect,
+ .fb_imageblit = cfb_imageblit,
+ .fb_copyarea = cfb_copyarea,
#ifdef __BIG_ENDIAN
.fb_read = smtcfb_read,
.fb_write = smtcfb_write,
@@ -772,12 +677,6 @@ void smtcfb_setmode(struct smtcfb_info *sfb)
hw.height = sfb->fb.var.yres;
hw.hz = 60;
smtc_set_timing(sfb, &hw);
- if (smtc_2Dacceleration) {
- printk("2D acceleration enabled!\n");
- /* Init smtc drawing engine */
- deInit(sfb->fb.var.xres, sfb->fb.var.yres,
- sfb->fb.var.bits_per_pixel);
- }
}
/*
@@ -1004,9 +903,7 @@ static int __init smtcfb_pci_probe(struct pci_dev *pdev,
#endif
hw.m_pMMIO = (smtc_RegBaseAddress =
smtc_VRAMBaseAddress + 0x00700000);
- smtc_2DBaseAddress = (hw.m_pDPR =
- smtc_VRAMBaseAddress + 0x00408000);
- smtc_2Ddataport = smtc_VRAMBaseAddress + DE_DATA_PORT_712;
+ hw.m_pDPR = smtc_VRAMBaseAddress + 0x00408000;
hw.m_pVPR = hw.m_pLFB + 0x0040c000;
#ifdef __BIG_ENDIAN
if (sfb->fb.var.bits_per_pixel == 32) {
@@ -1035,27 +932,21 @@ static int __init smtcfb_pci_probe(struct pci_dev *pdev,
if (sfb->fb.var.bits_per_pixel == 32)
smtc_seqw(0x17, 0x30);
#endif
-#ifdef CONFIG_FB_SM7XX_ACCEL
- smtc_2Dacceleration = 1;
-#endif
break;
case 0x720:
sfb->fb.fix.mmio_start = pFramebufferPhysical;
sfb->fb.fix.mmio_len = 0x00200000;
smem_size = SM722_VIDEOMEMORYSIZE;
- smtc_2DBaseAddress = (hw.m_pDPR =
- ioremap(pFramebufferPhysical, 0x00a00000));
+ hw.m_pDPR = ioremap(pFramebufferPhysical, 0x00a00000);
hw.m_pLFB = (smtc_VRAMBaseAddress =
- smtc_2DBaseAddress + 0x00200000);
+ hw.m_pDPR + 0x00200000);
hw.m_pMMIO = (smtc_RegBaseAddress =
- smtc_2DBaseAddress + 0x000c0000);
- smtc_2Ddataport = smtc_2DBaseAddress + DE_DATA_PORT_722;
- hw.m_pVPR = smtc_2DBaseAddress + 0x800;
+ hw.m_pDPR + 0x000c0000);
+ hw.m_pVPR = hw.m_pDPR + 0x800;
smtc_seqw(0x62, 0xff);
smtc_seqw(0x6a, 0x0d);
smtc_seqw(0x6b, 0x02);
- smtc_2Dacceleration = 0;
break;
default:
printk(KERN_INFO
@@ -1103,7 +994,7 @@ static int __init smtcfb_pci_probe(struct pci_dev *pdev,
/* Jason (08/11/2009) PCI_DRV wrapper essential structs */
-static struct pci_device_id smtcfb_pci_table[] = {
+static const struct pci_device_id smtcfb_pci_table[] = {
{0x126f, 0x710, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x126f, 0x712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x126f, 0x720, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
diff --git a/drivers/staging/udlfb/Kconfig b/drivers/staging/udlfb/Kconfig
index 641692da0e4..65bd5db4ca5 100644
--- a/drivers/staging/udlfb/Kconfig
+++ b/drivers/staging/udlfb/Kconfig
@@ -1,8 +1,14 @@
config FB_UDL
tristate "Displaylink USB Framebuffer support"
depends on FB && USB
+ select FB_MODE_HELPERS
+ select FB_SYS_FILLRECT
+ select FB_SYS_COPYAREA
+ select FB_SYS_IMAGEBLIT
+ select FB_SYS_FOPS
+ select FB_DEFERRED_IO
---help---
- This is an experimental driver for DisplayLink USB devices
- that provides a framebuffer device. A normal framebuffer can
- be used with this driver, or xorg can be run on the device
- using it.
+ This is a kernel framebuffer driver for DisplayLink USB devices.
+ Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and
+ mplayer -vo fbdev. Supports all USB 2.0 era DisplayLink devices.
+ To compile as a module, choose M here: the module name is udlfb.
diff --git a/drivers/staging/udlfb/udlfb.c b/drivers/staging/udlfb/udlfb.c
index f5416af1e90..8f6223c8303 100644
--- a/drivers/staging/udlfb/udlfb.c
+++ b/drivers/staging/udlfb/udlfb.c
@@ -1,17 +1,20 @@
-/*****************************************************************************
- * DLFB Kernel Driver *
- * Version 0.2 (udlfb) *
- * (C) 2009 Roberto De Ioris <roberto@unbit.it> *
- * *
- * This file is licensed under the GPLv2. See COPYING in the package. *
- * Based on the amazing work of Florian Echtler and libdlo 0.1 *
- * *
- * *
- * 10.06.09 release 0.2.3 (edid ioctl, fallback for unsupported modes) *
- * 05.06.09 release 0.2.2 (real screen blanking, rle compression, double buffer) *
- * 31.05.09 release 0.2 *
- * 22.05.09 First public (ugly) release *
- *****************************************************************************/
+/*
+ * udlfb.c -- Framebuffer driver for DisplayLink USB controller
+ *
+ * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it>
+ * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com>
+ * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
+ *
+ * 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.
+ *
+ * Layout is based on skeletonfb by James Simmons and Geert Uytterhoeven,
+ * usb-skeleton by GregKH.
+ *
+ * Device-specific portions based on information from Displaylink, with work
+ * from Florian Echtler, Henrik Bjerregaard Pedersen, and others.
+ */
#include <linux/module.h>
#include <linux/kernel.h>
@@ -20,606 +23,672 @@
#include <linux/uaccess.h>
#include <linux/mm.h>
#include <linux/fb.h>
-#include <linux/mutex.h>
#include <linux/vmalloc.h>
#include "udlfb.h"
-#define DRIVER_VERSION "DLFB 0.2"
+static struct fb_fix_screeninfo dlfb_fix = {
+ .id = "udlfb",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+ .xpanstep = 0,
+ .ypanstep = 0,
+ .ywrapstep = 0,
+ .accel = FB_ACCEL_NONE,
+};
-/* memory functions taken from vfb */
+static const u32 udlfb_info_flags = FBINFO_DEFAULT | FBINFO_READS_FAST |
+#ifdef FBINFO_VIRTFB
+ FBINFO_VIRTFB |
+#endif
+ FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_FILLRECT |
+ FBINFO_HWACCEL_COPYAREA | FBINFO_MISC_ALWAYS_SETPAR;
-static void *rvmalloc(unsigned long size)
-{
- void *mem;
- unsigned long adr;
+/*
+ * There are many DisplayLink-based products, all with unique PIDs. We are able
+ * to support all volume ones (circa 2009) with a single driver, so we match
+ * globally on VID. TODO: Probe() needs to detect when we might be running
+ * "future" chips, and bail on those, so a compatible driver can match.
+ */
+static struct usb_device_id id_table[] = {
+ {.idVendor = 0x17e9, .match_flags = USB_DEVICE_ID_MATCH_VENDOR,},
+ {},
+};
+MODULE_DEVICE_TABLE(usb, id_table);
- size = PAGE_ALIGN(size);
- mem = vmalloc_32(size);
- if (!mem)
- return NULL;
+#ifndef CONFIG_FB_DEFERRED_IO
+#warning message "kernel FB_DEFFERRED_IO option to support generic fbdev apps"
+#endif
- memset(mem, 0, size); /* Clear the ram out, no junk to the user */
- adr = (unsigned long)mem;
- while (size > 0) {
- SetPageReserved(vmalloc_to_page((void *)adr));
- adr += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
+#ifndef CONFIG_FB_SYS_IMAGEBLIT
+#ifndef CONFIG_FB_SYS_IMAGEBLIT_MODULE
+#warning message "FB_SYS_* in kernel or module option to support fb console"
+#endif
+#endif
- return mem;
-}
+#ifndef CONFIG_FB_MODE_HELPERS
+#warning message "kernel FB_MODE_HELPERS required. Expect build break"
+#endif
-static void rvfree(void *mem, unsigned long size)
-{
- unsigned long adr;
+/* dlfb keeps a list of urbs for efficient bulk transfers */
+static void dlfb_urb_completion(struct urb *urb);
+static struct urb *dlfb_get_urb(struct dlfb_data *dev);
+static int dlfb_submit_urb(struct dlfb_data *dev, struct urb * urb, size_t len);
+static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size);
+static void dlfb_free_urb_list(struct dlfb_data *dev);
- if (!mem)
- return;
+/* other symbols with dependents */
+#ifdef CONFIG_FB_DEFERRED_IO
+static struct fb_deferred_io dlfb_defio;
+#endif
- adr = (unsigned long)mem;
- while ((long)size > 0) {
- ClearPageReserved(vmalloc_to_page((void *)adr));
- adr += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
- vfree(mem);
+/*
+ * All DisplayLink bulk operations start with 0xAF, followed by specific code
+ * All operations are written to buffers which then later get sent to device
+ */
+static char *dlfb_set_register(char *buf, u8 reg, u8 val)
+{
+ *buf++ = 0xAF;
+ *buf++ = 0x20;
+ *buf++ = reg;
+ *buf++ = val;
+ return buf;
}
-static int dlfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+static char *dlfb_vidreg_lock(char *buf)
{
- unsigned long start = vma->vm_start;
- unsigned long size = vma->vm_end - vma->vm_start;
- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
- unsigned long page, pos;
-
- printk("MMAP: %lu %u\n", offset + size, info->fix.smem_len);
-
- if (offset + size > info->fix.smem_len)
- return -EINVAL;
-
- pos = (unsigned long)info->fix.smem_start + offset;
-
- while (size > 0) {
- page = vmalloc_to_pfn((void *)pos);
- if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
- return -EAGAIN;
-
- start += PAGE_SIZE;
- pos += PAGE_SIZE;
- if (size > PAGE_SIZE)
- size -= PAGE_SIZE;
- else
- size = 0;
- }
-
- vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
- return 0;
-
+ return dlfb_set_register(buf, 0xFF, 0x00);
}
-/* ioctl structure */
-struct dloarea {
- int x, y;
- int w, h;
- int x2, y2;
-};
+static char *dlfb_vidreg_unlock(char *buf)
+{
+ return dlfb_set_register(buf, 0xFF, 0xFF);
+}
/*
-static struct usb_device_id id_table [] = {
- { USB_DEVICE(0x17e9, 0x023d) },
- { }
-};
-*/
+ * On/Off for driving the DisplayLink framebuffer to the display
+ */
+static char *dlfb_enable_hvsync(char *buf, bool enable)
+{
+ if (enable)
+ return dlfb_set_register(buf, 0x1F, 0x00);
+ else
+ return dlfb_set_register(buf, 0x1F, 0x01);
+}
-static struct usb_device_id id_table[] = {
- {.idVendor = 0x17e9, .match_flags = USB_DEVICE_ID_MATCH_VENDOR,},
- {},
-};
-MODULE_DEVICE_TABLE(usb, id_table);
+static char *dlfb_set_color_depth(char *buf, u8 selection)
+{
+ return dlfb_set_register(buf, 0x00, selection);
+}
-static struct usb_driver dlfb_driver;
+static char *dlfb_set_base16bpp(char *wrptr, u32 base)
+{
+ /* the base pointer is 16 bits wide, 0x20 is hi byte. */
+ wrptr = dlfb_set_register(wrptr, 0x20, base >> 16);
+ wrptr = dlfb_set_register(wrptr, 0x21, base >> 8);
+ return dlfb_set_register(wrptr, 0x22, base);
+}
-// thanks to Henrik Bjerregaard Pedersen for this function
-static char *rle_compress16(uint16_t * src, char *dst, int rem)
+/*
+ * DisplayLink HW has separate 16bpp and 8bpp framebuffers.
+ * In 24bpp modes, the low 323 RGB bits go in the 8bpp framebuffer
+ */
+static char *dlfb_set_base8bpp(char *wrptr, u32 base)
{
+ wrptr = dlfb_set_register(wrptr, 0x26, base >> 16);
+ wrptr = dlfb_set_register(wrptr, 0x27, base >> 8);
+ return dlfb_set_register(wrptr, 0x28, base);
+}
- int rl;
- uint16_t pix0;
- char *end_if_raw = dst + 6 + 2 * rem;
+static char *dlfb_set_register_16(char *wrptr, u8 reg, u16 value)
+{
+ wrptr = dlfb_set_register(wrptr, reg, value >> 8);
+ return dlfb_set_register(wrptr, reg+1, value);
+}
- dst += 6; // header will be filled in if RLE is worth it
+/*
+ * This is kind of weird because the controller takes some
+ * register values in a different byte order than other registers.
+ */
+static char *dlfb_set_register_16be(char *wrptr, u8 reg, u16 value)
+{
+ wrptr = dlfb_set_register(wrptr, reg, value);
+ return dlfb_set_register(wrptr, reg+1, value >> 8);
+}
- while (rem && dst < end_if_raw) {
- char *start = (char *)src;
+/*
+ * LFSR is linear feedback shift register. The reason we have this is
+ * because the display controller needs to minimize the clock depth of
+ * various counters used in the display path. So this code reverses the
+ * provided value into the lfsr16 value by counting backwards to get
+ * the value that needs to be set in the hardware comparator to get the
+ * same actual count. This makes sense once you read above a couple of
+ * times and think about it from a hardware perspective.
+ */
+static u16 dlfb_lfsr16(u16 actual_count)
+{
+ u32 lv = 0xFFFF; /* This is the lfsr value that the hw starts with */
- pix0 = *src++;
- rl = 1;
- rem--;
- while (rem && *src == pix0)
- rem--, rl++, src++;
- *dst++ = rl;
- *dst++ = start[1];
- *dst++ = start[0];
+ while (actual_count--) {
+ lv = ((lv << 1) |
+ (((lv >> 15) ^ (lv >> 4) ^ (lv >> 2) ^ (lv >> 1)) & 1))
+ & 0xFFFF;
}
- return dst;
+ return (u16) lv;
}
/*
-Thanks to Henrik Bjerregaard Pedersen for rle implementation and code refactoring.
-Next step is huffman compression.
-*/
-
-static int
-image_blit(struct dlfb_data *dev_info, int x, int y, int width, int height,
- char *data)
+ * This does LFSR conversion on the value that is to be written.
+ * See LFSR explanation above for more detail.
+ */
+static char *dlfb_set_register_lfsr16(char *wrptr, u8 reg, u16 value)
{
+ return dlfb_set_register_16(wrptr, reg, dlfb_lfsr16(value));
+}
- int i, j, base;
- int rem = width;
- int ret;
-
- int firstdiff, thistime;
-
- char *bufptr;
-
- if (x + width > dev_info->info->var.xres)
- return -EINVAL;
-
- if (y + height > dev_info->info->var.yres)
- return -EINVAL;
+/*
+ * This takes a standard fbdev screeninfo struct and all of its monitor mode
+ * details and converts them into the DisplayLink equivalent register commands.
+ */
+static char *dlfb_set_vid_cmds(char *wrptr, struct fb_var_screeninfo *var)
+{
+ u16 xds, yds;
+ u16 xde, yde;
+ u16 yec;
- mutex_lock(&dev_info->bulk_mutex);
+ /* x display start */
+ xds = var->left_margin + var->hsync_len;
+ wrptr = dlfb_set_register_lfsr16(wrptr, 0x01, xds);
+ /* x display end */
+ xde = xds + var->xres;
+ wrptr = dlfb_set_register_lfsr16(wrptr, 0x03, xde);
- base =
- dev_info->base16 + ((dev_info->info->var.xres * 2 * y) + (x * 2));
+ /* y display start */
+ yds = var->upper_margin + var->vsync_len;
+ wrptr = dlfb_set_register_lfsr16(wrptr, 0x05, yds);
+ /* y display end */
+ yde = yds + var->yres;
+ wrptr = dlfb_set_register_lfsr16(wrptr, 0x07, yde);
- data += (dev_info->info->var.xres * 2 * y) + (x * 2);
+ /* x end count is active + blanking - 1 */
+ wrptr = dlfb_set_register_lfsr16(wrptr, 0x09,
+ xde + var->right_margin - 1);
- /* printk("IMAGE_BLIT\n"); */
+ /* libdlo hardcodes hsync start to 1 */
+ wrptr = dlfb_set_register_lfsr16(wrptr, 0x0B, 1);
- bufptr = dev_info->buf;
+ /* hsync end is width of sync pulse + 1 */
+ wrptr = dlfb_set_register_lfsr16(wrptr, 0x0D, var->hsync_len + 1);
- for (i = y; i < y + height; i++) {
+ /* hpixels is active pixels */
+ wrptr = dlfb_set_register_16(wrptr, 0x0F, var->xres);
- if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
- ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
- bufptr = dev_info->buf;
- }
+ /* yendcount is vertical active + vertical blanking */
+ yec = var->yres + var->upper_margin + var->lower_margin +
+ var->vsync_len;
+ wrptr = dlfb_set_register_lfsr16(wrptr, 0x11, yec);
- rem = width;
+ /* libdlo hardcodes vsync start to 0 */
+ wrptr = dlfb_set_register_lfsr16(wrptr, 0x13, 0);
- /* printk("WRITING LINE %d\n", i); */
+ /* vsync end is width of vsync pulse */
+ wrptr = dlfb_set_register_lfsr16(wrptr, 0x15, var->vsync_len);
- while (rem) {
+ /* vpixels is active pixels */
+ wrptr = dlfb_set_register_16(wrptr, 0x17, var->yres);
- if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
- ret =
- dlfb_bulk_msg(dev_info,
- bufptr - dev_info->buf);
- bufptr = dev_info->buf;
- }
- // number of pixels to consider this time
- thistime = rem;
- if (thistime > 255)
- thistime = 255;
-
- // find position of first pixel that has changed
- firstdiff = -1;
- for (j = 0; j < thistime * 2; j++) {
- if (dev_info->backing_buffer
- [base - dev_info->base16 + j] != data[j]) {
- firstdiff = j / 2;
- break;
- }
- }
+ /* convert picoseconds to 5kHz multiple for pclk5k = x * 1E12/5k */
+ wrptr = dlfb_set_register_16be(wrptr, 0x1B,
+ 200*1000*1000/var->pixclock);
- if (firstdiff >= 0) {
- char *end_of_rle;
-
- end_of_rle =
- rle_compress16((uint16_t *) (data +
- firstdiff * 2),
- bufptr,
- thistime - firstdiff);
-
- if (end_of_rle <
- bufptr + 6 + 2 * (thistime - firstdiff)) {
- bufptr[0] = 0xAF;
- bufptr[1] = 0x69;
-
- bufptr[2] =
- (char)((base +
- firstdiff * 2) >> 16);
- bufptr[3] =
- (char)((base + firstdiff * 2) >> 8);
- bufptr[4] =
- (char)(base + firstdiff * 2);
- bufptr[5] = thistime - firstdiff;
-
- bufptr = end_of_rle;
-
- } else {
- // fallback to raw (or some other encoding?)
- *bufptr++ = 0xAF;
- *bufptr++ = 0x68;
-
- *bufptr++ =
- (char)((base +
- firstdiff * 2) >> 16);
- *bufptr++ =
- (char)((base + firstdiff * 2) >> 8);
- *bufptr++ =
- (char)(base + firstdiff * 2);
- *bufptr++ = thistime - firstdiff;
- // PUT COMPRESSION HERE
- for (j = firstdiff * 2;
- j < thistime * 2; j += 2) {
- *bufptr++ = data[j + 1];
- *bufptr++ = data[j];
- }
- }
- }
+ return wrptr;
+}
- base += thistime * 2;
- data += thistime * 2;
- rem -= thistime;
- }
+/*
+ * This takes a standard fbdev screeninfo struct that was fetched or prepared
+ * and then generates the appropriate command sequence that then drives the
+ * display controller.
+ */
+static int dlfb_set_video_mode(struct dlfb_data *dev,
+ struct fb_var_screeninfo *var)
+{
+ char *buf;
+ char *wrptr;
+ int retval = 0;
+ int writesize;
+ struct urb *urb;
- memcpy(dev_info->backing_buffer + (base - dev_info->base16) -
- (width * 2), data - (width * 2), width * 2);
+ if (!atomic_read(&dev->usb_active))
+ return -EPERM;
- base += (dev_info->info->var.xres * 2) - (width * 2);
- data += (dev_info->info->var.xres * 2) - (width * 2);
+ urb = dlfb_get_urb(dev);
+ if (!urb)
+ return -ENOMEM;
+ buf = (char *) urb->transfer_buffer;
- }
+ /*
+ * This first section has to do with setting the base address on the
+ * controller * associated with the display. There are 2 base
+ * pointers, currently, we only * use the 16 bpp segment.
+ */
+ wrptr = dlfb_vidreg_lock(buf);
+ wrptr = dlfb_set_color_depth(wrptr, 0x00);
+ /* set base for 16bpp segment to 0 */
+ wrptr = dlfb_set_base16bpp(wrptr, 0);
+ /* set base for 8bpp segment to end of fb */
+ wrptr = dlfb_set_base8bpp(wrptr, dev->info->fix.smem_len);
- if (bufptr > dev_info->buf) {
- ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
- }
+ wrptr = dlfb_set_vid_cmds(wrptr, var);
+ wrptr = dlfb_enable_hvsync(wrptr, true);
+ wrptr = dlfb_vidreg_unlock(wrptr);
- mutex_unlock(&dev_info->bulk_mutex);
+ writesize = wrptr - buf;
- return base;
+ retval = dlfb_submit_urb(dev, urb, writesize);
+ return retval;
}
-static int
-draw_rect(struct dlfb_data *dev_info, int x, int y, int width, int height,
- unsigned char red, unsigned char green, unsigned char blue)
+static int dlfb_ops_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
+ unsigned long start = vma->vm_start;
+ unsigned long size = vma->vm_end - vma->vm_start;
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ unsigned long page, pos;
+ struct dlfb_data *dev = info->par;
- int i, j, base;
- int ret;
- unsigned short col =
- (((((red) & 0xF8) | ((green) >> 5)) & 0xFF) << 8) +
- (((((green) & 0x1C) << 3) | ((blue) >> 3)) & 0xFF);
- int rem = width;
-
- char *bufptr;
+ dl_notice("MMAP: %lu %u\n", offset + size, info->fix.smem_len);
- if (x + width > dev_info->info->var.xres)
+ if (offset + size > info->fix.smem_len)
return -EINVAL;
- if (y + height > dev_info->info->var.yres)
- return -EINVAL;
+ pos = (unsigned long)info->fix.smem_start + offset;
- mutex_lock(&dev_info->bulk_mutex);
+ while (size > 0) {
+ page = vmalloc_to_pfn((void *)pos);
+ if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
+ return -EAGAIN;
- base = dev_info->base16 + (dev_info->info->var.xres * 2 * y) + (x * 2);
+ start += PAGE_SIZE;
+ pos += PAGE_SIZE;
+ if (size > PAGE_SIZE)
+ size -= PAGE_SIZE;
+ else
+ size = 0;
+ }
- bufptr = dev_info->buf;
+ vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */
+ return 0;
- for (i = y; i < y + height; i++) {
+}
- for (j = 0; j < width * 2; j += 2) {
- dev_info->backing_buffer[base - dev_info->base16 + j] =
- (char)(col >> 8);
- dev_info->backing_buffer[base - dev_info->base16 + j +
- 1] = (char)(col);
- }
- if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
- ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
- bufptr = dev_info->buf;
+/*
+ * Trims identical data from front and back of line
+ * Sets new front buffer address and width
+ * And returns byte count of identical pixels
+ * Assumes CPU natural alignment (unsigned long)
+ * for back and front buffer ptrs and width
+ */
+static int dlfb_trim_hline(const u8 *bback, const u8 **bfront, int *width_bytes)
+{
+ int j, k;
+ const unsigned long *back = (const unsigned long *) bback;
+ const unsigned long *front = (const unsigned long *) *bfront;
+ const int width = *width_bytes / sizeof(unsigned long);
+ int identical = width;
+ int start = width;
+ int end = width;
+
+ prefetch((void *) front);
+ prefetch((void *) back);
+
+ for (j = 0; j < width; j++) {
+ if (back[j] != front[j]) {
+ start = j;
+ break;
}
+ }
- rem = width;
-
- while (rem) {
-
- if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
- ret =
- dlfb_bulk_msg(dev_info,
- bufptr - dev_info->buf);
- bufptr = dev_info->buf;
- }
-
- *bufptr++ = 0xAF;
- *bufptr++ = 0x69;
-
- *bufptr++ = (char)(base >> 16);
- *bufptr++ = (char)(base >> 8);
- *bufptr++ = (char)(base);
-
- if (rem > 255) {
- *bufptr++ = 255;
- *bufptr++ = 255;
- rem -= 255;
- base += 255 * 2;
- } else {
- *bufptr++ = rem;
- *bufptr++ = rem;
- base += rem * 2;
- rem = 0;
- }
-
- *bufptr++ = (char)(col >> 8);
- *bufptr++ = (char)(col);
-
+ for (k = width - 1; k > j; k--) {
+ if (back[k] != front[k]) {
+ end = k+1;
+ break;
}
-
- base += (dev_info->info->var.xres * 2) - (width * 2);
-
}
- if (bufptr > dev_info->buf)
- ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
+ identical = start + (width - end);
+ *bfront = (u8 *) &front[start];
+ *width_bytes = (end - start) * sizeof(unsigned long);
- mutex_unlock(&dev_info->bulk_mutex);
-
- return 1;
+ return identical * sizeof(unsigned long);
}
-static void swapfb(struct dlfb_data *dev_info)
+/*
+Render a command stream for an encoded horizontal line segment of pixels.
+
+A command buffer holds several commands.
+It always begins with a fresh command header
+(the protocol doesn't require this, but we enforce it to allow
+multiple buffers to be potentially encoded and sent in parallel).
+A single command encodes one contiguous horizontal line of pixels
+
+The function relies on the client to do all allocation, so that
+rendering can be done directly to output buffers (e.g. USB URBs).
+The function fills the supplied command buffer, providing information
+on where it left off, so the client may call in again with additional
+buffers if the line will take several buffers to complete.
+
+A single command can transmit a maximum of 256 pixels,
+regardless of the compression ratio (protocol design limit).
+To the hardware, 0 for a size byte means 256
+
+Rather than 256 pixel commands which are either rl or raw encoded,
+the rlx command simply assumes alternating raw and rl spans within one cmd.
+This has a slightly larger header overhead, but produces more even results.
+It also processes all data (read and write) in a single pass.
+Performance benchmarks of common cases show it having just slightly better
+compression than 256 pixel raw -or- rle commands, with similar CPU consumpion.
+But for very rl friendly data, will compress not quite as well.
+*/
+static void dlfb_compress_hline(
+ const uint16_t **pixel_start_ptr,
+ const uint16_t *const pixel_end,
+ uint32_t *device_address_ptr,
+ uint8_t **command_buffer_ptr,
+ const uint8_t *const cmd_buffer_end)
{
+ const uint16_t *pixel = *pixel_start_ptr;
+ uint32_t dev_addr = *device_address_ptr;
+ uint8_t *cmd = *command_buffer_ptr;
+ const int bpp = 2;
+
+ while ((pixel_end > pixel) &&
+ (cmd_buffer_end - MIN_RLX_CMD_BYTES > cmd)) {
+ uint8_t *raw_pixels_count_byte = 0;
+ uint8_t *cmd_pixels_count_byte = 0;
+ const uint16_t *raw_pixel_start = 0;
+ const uint16_t *cmd_pixel_start, *cmd_pixel_end = 0;
+ const uint32_t be_dev_addr = cpu_to_be32(dev_addr);
+
+ prefetchw((void *) cmd); /* pull in one cache line at least */
+
+ *cmd++ = 0xAF;
+ *cmd++ = 0x6B;
+ *cmd++ = (uint8_t) ((be_dev_addr >> 8) & 0xFF);
+ *cmd++ = (uint8_t) ((be_dev_addr >> 16) & 0xFF);
+ *cmd++ = (uint8_t) ((be_dev_addr >> 24) & 0xFF);
+
+ cmd_pixels_count_byte = cmd++; /* we'll know this later */
+ cmd_pixel_start = pixel;
+
+ raw_pixels_count_byte = cmd++; /* we'll know this later */
+ raw_pixel_start = pixel;
+
+ cmd_pixel_end = pixel + min(MAX_CMD_PIXELS + 1,
+ min((int)(pixel_end - pixel),
+ (int)(cmd_buffer_end - cmd) / bpp));
+
+ prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * bpp);
+
+ while (pixel < cmd_pixel_end) {
+ const uint16_t * const repeating_pixel = pixel;
+
+ *(uint16_t *)cmd = cpu_to_be16p(pixel);
+ cmd += 2;
+ pixel++;
+
+ if (unlikely((pixel < cmd_pixel_end) &&
+ (*pixel == *repeating_pixel))) {
+ /* go back and fill in raw pixel count */
+ *raw_pixels_count_byte = ((repeating_pixel -
+ raw_pixel_start) + 1) & 0xFF;
+
+ while ((pixel < cmd_pixel_end)
+ && (*pixel == *repeating_pixel)) {
+ pixel++;
+ }
- int tmpbase;
- char *bufptr;
-
- mutex_lock(&dev_info->bulk_mutex);
-
- tmpbase = dev_info->base16;
-
- dev_info->base16 = dev_info->base16d;
- dev_info->base16d = tmpbase;
+ /* immediately after raw data is repeat byte */
+ *cmd++ = ((pixel - repeating_pixel) - 1) & 0xFF;
- bufptr = dev_info->buf;
+ /* Then start another raw pixel span */
+ raw_pixel_start = pixel;
+ raw_pixels_count_byte = cmd++;
+ }
+ }
- bufptr = dlfb_set_register(bufptr, 0xFF, 0x00);
+ if (pixel > raw_pixel_start) {
+ /* finalize last RAW span */
+ *raw_pixels_count_byte = (pixel-raw_pixel_start) & 0xFF;
+ }
- // set addresses
- bufptr =
- dlfb_set_register(bufptr, 0x20, (char)(dev_info->base16 >> 16));
- bufptr = dlfb_set_register(bufptr, 0x21, (char)(dev_info->base16 >> 8));
- bufptr = dlfb_set_register(bufptr, 0x22, (char)(dev_info->base16));
+ *cmd_pixels_count_byte = (pixel - cmd_pixel_start) & 0xFF;
+ dev_addr += (pixel - cmd_pixel_start) * bpp;
+ }
- bufptr = dlfb_set_register(bufptr, 0xFF, 0x00);
+ if (cmd_buffer_end <= MIN_RLX_CMD_BYTES + cmd) {
+ /* Fill leftover bytes with no-ops */
+ if (cmd_buffer_end > cmd)
+ memset(cmd, 0xAF, cmd_buffer_end - cmd);
+ cmd = (uint8_t *) cmd_buffer_end;
+ }
- dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
+ *command_buffer_ptr = cmd;
+ *pixel_start_ptr = pixel;
+ *device_address_ptr = dev_addr;
- mutex_unlock(&dev_info->bulk_mutex);
+ return;
}
-static int copyfb(struct dlfb_data *dev_info)
+/*
+ * There are 3 copies of every pixel: The front buffer that the fbdev
+ * client renders to, the actual framebuffer across the USB bus in hardware
+ * (that we can only write to, slowly, and can never read), and (optionally)
+ * our shadow copy that tracks what's been sent to that hardware buffer.
+ */
+static void dlfb_render_hline(struct dlfb_data *dev, struct urb **urb_ptr,
+ const char *front, char **urb_buf_ptr,
+ u32 byte_offset, u32 byte_width,
+ int *ident_ptr, int *sent_ptr)
{
- int base;
- int source;
- int rem;
- int i, ret;
-
- char *bufptr;
-
- base = dev_info->base16d;
-
- mutex_lock(&dev_info->bulk_mutex);
-
- source = dev_info->base16;
-
- bufptr = dev_info->buf;
-
- for (i = 0; i < dev_info->info->var.yres; i++) {
-
- if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
- ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
- bufptr = dev_info->buf;
- }
-
- rem = dev_info->info->var.xres;
-
- while (rem) {
-
- if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
- ret =
- dlfb_bulk_msg(dev_info,
- bufptr - dev_info->buf);
- bufptr = dev_info->buf;
-
- }
-
- *bufptr++ = 0xAF;
- *bufptr++ = 0x6A;
-
- *bufptr++ = (char)(base >> 16);
- *bufptr++ = (char)(base >> 8);
- *bufptr++ = (char)(base);
-
- if (rem > 255) {
- *bufptr++ = 255;
- *bufptr++ = (char)(source >> 16);
- *bufptr++ = (char)(source >> 8);
- *bufptr++ = (char)(source);
-
- rem -= 255;
- base += 255 * 2;
- source += 255 * 2;
-
- } else {
- *bufptr++ = rem;
- *bufptr++ = (char)(source >> 16);
- *bufptr++ = (char)(source >> 8);
- *bufptr++ = (char)(source);
+ const u8 *line_start, *line_end, *next_pixel;
+ u32 dev_addr = dev->base16 + byte_offset;
+ struct urb *urb = *urb_ptr;
+ u8 *cmd = *urb_buf_ptr;
+ u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length;
+
+ line_start = (u8 *) (front + byte_offset);
+ next_pixel = line_start;
+ line_end = next_pixel + byte_width;
+
+ if (dev->backing_buffer) {
+ int offset;
+ const u8 *back_start = (u8 *) (dev->backing_buffer
+ + byte_offset);
+
+ *ident_ptr += dlfb_trim_hline(back_start, &next_pixel,
+ &byte_width);
+
+ offset = next_pixel - line_start;
+ line_end = next_pixel + byte_width;
+ dev_addr += offset;
+ back_start += offset;
+ line_start += offset;
+
+ memcpy((char *)back_start, (char *) line_start,
+ byte_width);
+ }
- base += rem * 2;
- source += rem * 2;
- rem = 0;
- }
+ while (next_pixel < line_end) {
+
+ dlfb_compress_hline((const uint16_t **) &next_pixel,
+ (const uint16_t *) line_end, &dev_addr,
+ (u8 **) &cmd, (u8 *) cmd_end);
+
+ if (cmd >= cmd_end) {
+ int len = cmd - (u8 *) urb->transfer_buffer;
+ if (dlfb_submit_urb(dev, urb, len))
+ return; /* lost pixels is set */
+ *sent_ptr += len;
+ urb = dlfb_get_urb(dev);
+ if (!urb)
+ return; /* lost_pixels is set */
+ *urb_ptr = urb;
+ cmd = urb->transfer_buffer;
+ cmd_end = &cmd[urb->transfer_buffer_length];
}
}
- if (bufptr > dev_info->buf)
- ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
-
- mutex_unlock(&dev_info->bulk_mutex);
-
- return 1;
-
+ *urb_buf_ptr = cmd;
}
-static int
-copyarea(struct dlfb_data *dev_info, int dx, int dy, int sx, int sy,
- int width, int height)
+int dlfb_handle_damage(struct dlfb_data *dev, int x, int y,
+ int width, int height, char *data)
{
- int base;
- int source;
- int rem;
int i, ret;
-
- char *bufptr;
-
- if (dx + width > dev_info->info->var.xres)
+ char *cmd;
+ cycles_t start_cycles, end_cycles;
+ int bytes_sent = 0;
+ int bytes_identical = 0;
+ struct urb *urb;
+ int aligned_x;
+
+ start_cycles = get_cycles();
+
+ aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long));
+ width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long));
+ x = aligned_x;
+
+ if ((width <= 0) ||
+ (x + width > dev->info->var.xres) ||
+ (y + height > dev->info->var.yres))
return -EINVAL;
- if (dy + height > dev_info->info->var.yres)
- return -EINVAL;
-
- mutex_lock(&dev_info->bulk_mutex);
+ if (!atomic_read(&dev->usb_active))
+ return 0;
- base =
- dev_info->base16 + (dev_info->info->var.xres * 2 * dy) + (dx * 2);
- source = (dev_info->info->var.xres * 2 * sy) + (sx * 2);
+ urb = dlfb_get_urb(dev);
+ if (!urb)
+ return 0;
+ cmd = urb->transfer_buffer;
- bufptr = dev_info->buf;
+ for (i = y; i < y + height ; i++) {
+ const int line_offset = dev->info->fix.line_length * i;
+ const int byte_offset = line_offset + (x * BPP);
- for (i = sy; i < sy + height; i++) {
+ dlfb_render_hline(dev, &urb, (char *) dev->info->fix.smem_start,
+ &cmd, byte_offset, width * BPP,
+ &bytes_identical, &bytes_sent);
+ }
- memcpy(dev_info->backing_buffer + base - dev_info->base16,
- dev_info->backing_buffer + source, width * 2);
+ if (cmd > (char *) urb->transfer_buffer) {
+ /* Send partial buffer remaining before exiting */
+ int len = cmd - (char *) urb->transfer_buffer;
+ ret = dlfb_submit_urb(dev, urb, len);
+ bytes_sent += len;
+ } else
+ dlfb_urb_completion(urb);
+
+ atomic_add(bytes_sent, &dev->bytes_sent);
+ atomic_add(bytes_identical, &dev->bytes_identical);
+ atomic_add(width*height*2, &dev->bytes_rendered);
+ end_cycles = get_cycles();
+ atomic_add(((unsigned int) ((end_cycles - start_cycles)
+ >> 10)), /* Kcycles */
+ &dev->cpu_kcycles_used);
- if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
- ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
- bufptr = dev_info->buf;
- }
-
- rem = width;
+ return 0;
+}
- while (rem) {
+/* hardware has native COPY command (see libdlo), but not worth it for fbcon */
+static void dlfb_ops_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area)
+{
- if (dev_info->bufend - bufptr < BUF_HIGH_WATER_MARK) {
- ret =
- dlfb_bulk_msg(dev_info,
- bufptr - dev_info->buf);
- bufptr = dev_info->buf;
- }
+ struct dlfb_data *dev = info->par;
- *bufptr++ = 0xAF;
- *bufptr++ = 0x6A;
+#if defined CONFIG_FB_SYS_COPYAREA || defined CONFIG_FB_SYS_COPYAREA_MODULE
- *bufptr++ = (char)(base >> 16);
- *bufptr++ = (char)(base >> 8);
- *bufptr++ = (char)(base);
+ sys_copyarea(info, area);
- if (rem > 255) {
- *bufptr++ = 255;
- *bufptr++ = (char)(source >> 16);
- *bufptr++ = (char)(source >> 8);
- *bufptr++ = (char)(source);
+ dlfb_handle_damage(dev, area->dx, area->dy,
+ area->width, area->height, info->screen_base);
+#endif
+ atomic_inc(&dev->copy_count);
- rem -= 255;
- base += 255 * 2;
- source += 255 * 2;
+}
- } else {
- *bufptr++ = rem;
- *bufptr++ = (char)(source >> 16);
- *bufptr++ = (char)(source >> 8);
- *bufptr++ = (char)(source);
+static void dlfb_ops_imageblit(struct fb_info *info,
+ const struct fb_image *image)
+{
+ struct dlfb_data *dev = info->par;
- base += rem * 2;
- source += rem * 2;
- rem = 0;
- }
- }
+#if defined CONFIG_FB_SYS_IMAGEBLIT || defined CONFIG_FB_SYS_IMAGEBLIT_MODULE
- base += (dev_info->info->var.xres * 2) - (width * 2);
- source += (dev_info->info->var.xres * 2) - (width * 2);
- }
+ sys_imageblit(info, image);
- if (bufptr > dev_info->buf)
- ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
+ dlfb_handle_damage(dev, image->dx, image->dy,
+ image->width, image->height, info->screen_base);
- mutex_unlock(&dev_info->bulk_mutex);
+#endif
- return 1;
+ atomic_inc(&dev->blit_count);
}
-static void dlfb_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+static void dlfb_ops_fillrect(struct fb_info *info,
+ const struct fb_fillrect *rect)
{
-
struct dlfb_data *dev = info->par;
- copyarea(dev, area->dx, area->dy, area->sx, area->sy, area->width,
- area->height);
+#if defined CONFIG_FB_SYS_FILLRECT || defined CONFIG_FB_SYS_FILLRECT_MODULE
- /* printk("COPY AREA %d %d %d %d %d %d !!!\n", area->dx, area->dy, area->sx, area->sy, area->width, area->height); */
+ sys_fillrect(info, rect);
-}
+ dlfb_handle_damage(dev, rect->dx, rect->dy, rect->width,
+ rect->height, info->screen_base);
+#endif
-static void dlfb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
+ atomic_inc(&dev->fill_count);
- int ret;
- struct dlfb_data *dev = info->par;
- /* printk("IMAGE BLIT (1) %d %d %d %d DEPTH %d {%p}!!!\n", image->dx, image->dy, image->width, image->height, image->depth, dev->udev); */
- cfb_imageblit(info, image);
- ret =
- image_blit(dev, image->dx, image->dy, image->width, image->height,
- info->screen_base);
- /* printk("IMAGE BLIT (2) %d %d %d %d DEPTH %d {%p} %d!!!\n", image->dx, image->dy, image->width, image->height, image->depth, dev->udev, ret); */
}
-static void dlfb_fillrect(struct fb_info *info,
- const struct fb_fillrect *region)
+static void dlfb_get_edid(struct dlfb_data *dev)
{
-
- unsigned char red, green, blue;
- struct dlfb_data *dev = info->par;
-
- memcpy(&red, &region->color, 1);
- memcpy(&green, &region->color + 1, 1);
- memcpy(&blue, &region->color + 2, 1);
- draw_rect(dev, region->dx, region->dy, region->width, region->height,
- red, green, blue);
- /* printk("FILL RECT %d %d !!!\n", region->dx, region->dy); */
-
+ int i;
+ int ret;
+ char rbuf[2];
+
+ for (i = 0; i < sizeof(dev->edid); i++) {
+ ret = usb_control_msg(dev->udev,
+ usb_rcvctrlpipe(dev->udev, 0), (0x02),
+ (0x80 | (0x02 << 5)), i << 8, 0xA1, rbuf, 2,
+ 0);
+ dev->edid[i] = rbuf[1];
+ }
}
-static int dlfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+static int dlfb_ops_ioctl(struct fb_info *info, unsigned int cmd,
+ unsigned long arg)
{
- struct dlfb_data *dev_info = info->par;
+ struct dlfb_data *dev = info->par;
struct dloarea *area = NULL;
- if (cmd == 0xAD) {
+ if (!atomic_read(&dev->usb_active))
+ return 0;
+
+ /* TODO: Update X server to get this from sysfs instead */
+ if (cmd == DLFB_IOCTL_RETURN_EDID) {
char *edid = (char *)arg;
- dlfb_edid(dev_info);
- if (copy_to_user(edid, dev_info->edid, 128)) {
+ dlfb_get_edid(dev);
+ if (copy_to_user(edid, dev->edid, sizeof(dev->edid)))
return -EFAULT;
- }
return 0;
}
- if (cmd == 0xAA || cmd == 0xAB || cmd == 0xAC) {
+ /* TODO: Help propose a standard fb.h ioctl to report mmap damage */
+ if (cmd == DLFB_IOCTL_REPORT_DAMAGE) {
area = (struct dloarea *)arg;
@@ -634,36 +703,20 @@ static int dlfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
if (area->y > info->var.yres)
area->y = info->var.yres;
- }
- if (cmd == 0xAA) {
- image_blit(dev_info, area->x, area->y, area->w, area->h,
+ atomic_set(&dev->use_defio, 0);
+
+ dlfb_handle_damage(dev, area->x, area->y, area->w, area->h,
info->screen_base);
+ atomic_inc(&dev->damage_count);
}
- if (cmd == 0xAC) {
- copyfb(dev_info);
- image_blit(dev_info, area->x, area->y, area->w, area->h,
- info->screen_base);
- swapfb(dev_info);
- } else if (cmd == 0xAB) {
-
- if (area->x2 < 0)
- area->x2 = 0;
-
- if (area->y2 < 0)
- area->y2 = 0;
- copyarea(dev_info,
- area->x2, area->y2, area->x, area->y, area->w,
- area->h);
- }
return 0;
}
/* taken from vesafb */
-
static int
-dlfb_setcolreg(unsigned regno, unsigned red, unsigned green,
+dlfb_ops_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp, struct fb_info *info)
{
int err = 0;
@@ -688,234 +741,698 @@ dlfb_setcolreg(unsigned regno, unsigned red, unsigned green,
return err;
}
-static int dlfb_release(struct fb_info *info, int user)
+/*
+ * It's common for several clients to have framebuffer open simultaneously.
+ * e.g. both fbcon and X. Makes things interesting.
+ */
+static int dlfb_ops_open(struct fb_info *info, int user)
+{
+ struct dlfb_data *dev = info->par;
+
+/* if (user == 0)
+ * We could special case kernel mode clients (fbcon) here
+ */
+
+ mutex_lock(&dev->fb_open_lock);
+
+ dev->fb_count++;
+
+#ifdef CONFIG_FB_DEFERRED_IO
+ if ((atomic_read(&dev->use_defio)) && (info->fbdefio == NULL)) {
+ /* enable defio */
+ info->fbdefio = &dlfb_defio;
+ fb_deferred_io_init(info);
+ }
+#endif
+
+ dl_notice("open /dev/fb%d user=%d fb_info=%p count=%d\n",
+ info->node, user, info, dev->fb_count);
+
+ mutex_unlock(&dev->fb_open_lock);
+
+ return 0;
+}
+
+static int dlfb_ops_release(struct fb_info *info, int user)
+{
+ struct dlfb_data *dev = info->par;
+
+ mutex_lock(&dev->fb_open_lock);
+
+ dev->fb_count--;
+
+#ifdef CONFIG_FB_DEFERRED_IO
+ if ((dev->fb_count == 0) && (info->fbdefio)) {
+ fb_deferred_io_cleanup(info);
+ info->fbdefio = NULL;
+ info->fbops->fb_mmap = dlfb_ops_mmap;
+ }
+#endif
+
+ dl_notice("release /dev/fb%d user=%d count=%d\n",
+ info->node, user, dev->fb_count);
+
+ mutex_unlock(&dev->fb_open_lock);
+
+ return 0;
+}
+
+/*
+ * Called when all client interfaces to start transactions have been disabled,
+ * and all references to our device instance (dlfb_data) are released.
+ * Every transaction must have a reference, so we know are fully spun down
+ */
+static void dlfb_delete(struct kref *kref)
+{
+ struct dlfb_data *dev = container_of(kref, struct dlfb_data, kref);
+
+ if (dev->backing_buffer)
+ vfree(dev->backing_buffer);
+
+ mutex_destroy(&dev->fb_open_lock);
+
+ kfree(dev);
+}
+
+/*
+ * Called by fbdev as last part of unregister_framebuffer() process
+ * No new clients can open connections. Deallocate everything fb_info.
+ */
+static void dlfb_ops_destroy(struct fb_info *info)
+{
+ struct dlfb_data *dev = info->par;
+
+ if (info->cmap.len != 0)
+ fb_dealloc_cmap(&info->cmap);
+ if (info->monspecs.modedb)
+ fb_destroy_modedb(info->monspecs.modedb);
+ if (info->screen_base)
+ vfree(info->screen_base);
+
+ fb_destroy_modelist(&info->modelist);
+
+ framebuffer_release(info);
+
+ /* ref taken before register_framebuffer() for dlfb_data clients */
+ kref_put(&dev->kref, dlfb_delete);
+}
+
+/*
+ * Check whether a video mode is supported by the DisplayLink chip
+ * We start from monitor's modes, so don't need to filter that here
+ */
+static int dlfb_is_valid_mode(struct fb_videomode *mode,
+ struct fb_info *info)
+{
+ struct dlfb_data *dev = info->par;
+
+ if (mode->xres * mode->yres > dev->sku_pixel_limit)
+ return 0;
+
+ return 1;
+}
+
+static void dlfb_var_color_format(struct fb_var_screeninfo *var)
+{
+ const struct fb_bitfield red = { 11, 5, 0 };
+ const struct fb_bitfield green = { 5, 6, 0 };
+ const struct fb_bitfield blue = { 0, 5, 0 };
+
+ var->bits_per_pixel = 16;
+ var->red = red;
+ var->green = green;
+ var->blue = blue;
+}
+
+static int dlfb_ops_check_var(struct fb_var_screeninfo *var,
+ struct fb_info *info)
{
- struct dlfb_data *dev_info = info->par;
- image_blit(dev_info, 0, 0, info->var.xres, info->var.yres,
- info->screen_base);
+ struct fb_videomode mode;
+
+ /* TODO: support dynamically changing framebuffer size */
+ if ((var->xres * var->yres * 2) > info->fix.smem_len)
+ return -EINVAL;
+
+ /* set device-specific elements of var unrelated to mode */
+ dlfb_var_color_format(var);
+
+ fb_var_to_videomode(&mode, var);
+
+ if (!dlfb_is_valid_mode(&mode, info))
+ return -EINVAL;
+
return 0;
}
-static int dlfb_blank(int blank_mode, struct fb_info *info)
+static int dlfb_ops_set_par(struct fb_info *info)
{
- struct dlfb_data *dev_info = info->par;
- char *bufptr = dev_info->buf;
+ struct dlfb_data *dev = info->par;
+
+ dl_notice("set_par mode %dx%d\n", info->var.xres, info->var.yres);
- bufptr = dlfb_set_register(bufptr, 0xFF, 0x00);
+ return dlfb_set_video_mode(dev, &info->var);
+}
+
+static int dlfb_ops_blank(int blank_mode, struct fb_info *info)
+{
+ struct dlfb_data *dev = info->par;
+ char *bufptr;
+ struct urb *urb;
+
+ urb = dlfb_get_urb(dev);
+ if (!urb)
+ return 0;
+ bufptr = (char *) urb->transfer_buffer;
+
+ /* overloading usb_active. UNBLANK can conflict with teardown */
+
+ bufptr = dlfb_vidreg_lock(bufptr);
if (blank_mode != FB_BLANK_UNBLANK) {
- bufptr = dlfb_set_register(bufptr, 0x1F, 0x01);
+ atomic_set(&dev->usb_active, 0);
+ bufptr = dlfb_enable_hvsync(bufptr, false);
} else {
- bufptr = dlfb_set_register(bufptr, 0x1F, 0x00);
+ atomic_set(&dev->usb_active, 1);
+ bufptr = dlfb_enable_hvsync(bufptr, true);
}
- bufptr = dlfb_set_register(bufptr, 0xFF, 0xFF);
+ bufptr = dlfb_vidreg_unlock(bufptr);
- dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
+ dlfb_submit_urb(dev, urb, bufptr - (char *) urb->transfer_buffer);
return 0;
}
static struct fb_ops dlfb_ops = {
- .fb_setcolreg = dlfb_setcolreg,
- .fb_fillrect = dlfb_fillrect,
- .fb_copyarea = dlfb_copyarea,
- .fb_imageblit = dlfb_imageblit,
- .fb_mmap = dlfb_mmap,
- .fb_ioctl = dlfb_ioctl,
- .fb_release = dlfb_release,
- .fb_blank = dlfb_blank,
+ .owner = THIS_MODULE,
+ .fb_setcolreg = dlfb_ops_setcolreg,
+ .fb_fillrect = dlfb_ops_fillrect,
+ .fb_copyarea = dlfb_ops_copyarea,
+ .fb_imageblit = dlfb_ops_imageblit,
+ .fb_mmap = dlfb_ops_mmap,
+ .fb_ioctl = dlfb_ops_ioctl,
+ .fb_open = dlfb_ops_open,
+ .fb_release = dlfb_ops_release,
+ .fb_blank = dlfb_ops_blank,
+ .fb_check_var = dlfb_ops_check_var,
+ .fb_set_par = dlfb_ops_set_par,
};
-static int
-dlfb_probe(struct usb_interface *interface, const struct usb_device_id *id)
+/*
+ * Calls dlfb_get_edid() to query the EDID of attached monitor via usb cmds
+ * Then parses EDID into three places used by various parts of fbdev:
+ * fb_var_screeninfo contains the timing of the monitor's preferred mode
+ * fb_info.monspecs is full parsed EDID info, including monspecs.modedb
+ * fb_info.modelist is a linked list of all monitor & VESA modes which work
+ *
+ * If EDID is not readable/valid, then modelist is all VESA modes,
+ * monspecs is NULL, and fb_var_screeninfo is set to safe VESA mode
+ * Returns 0 if EDID parses successfully
+ */
+static int dlfb_parse_edid(struct dlfb_data *dev,
+ struct fb_var_screeninfo *var,
+ struct fb_info *info)
{
- struct dlfb_data *dev_info;
- struct fb_info *info;
+ int i;
+ const struct fb_videomode *default_vmode = NULL;
+ int result = 0;
- int ret;
- char rbuf[4];
+ fb_destroy_modelist(&info->modelist);
+ memset(&info->monspecs, 0, sizeof(info->monspecs));
- dev_info = kzalloc(sizeof(*dev_info), GFP_KERNEL);
- if (dev_info == NULL) {
- printk("cannot allocate dev_info structure.\n");
- return -ENOMEM;
+ dlfb_get_edid(dev);
+ fb_edid_to_monspecs(dev->edid, &info->monspecs);
+
+ if (info->monspecs.modedb_len > 0) {
+
+ for (i = 0; i < info->monspecs.modedb_len; i++) {
+ if (dlfb_is_valid_mode(&info->monspecs.modedb[i], info))
+ fb_add_videomode(&info->monspecs.modedb[i],
+ &info->modelist);
+ }
+
+ default_vmode = fb_find_best_display(&info->monspecs,
+ &info->modelist);
+ } else {
+ struct fb_videomode fb_vmode = {0};
+
+ dl_err("Unable to get valid EDID from device/display\n");
+ result = 1;
+
+ /*
+ * Add the standard VESA modes to our modelist
+ * Since we don't have EDID, there may be modes that
+ * overspec monitor and/or are incorrect aspect ratio, etc.
+ * But at least the user has a chance to choose
+ */
+ for (i = 0; i < VESA_MODEDB_SIZE; i++) {
+ if (dlfb_is_valid_mode((struct fb_videomode *)
+ &vesa_modes[i], info))
+ fb_add_videomode(&vesa_modes[i],
+ &info->modelist);
+ }
+
+ /*
+ * default to resolution safe for projectors
+ * (since they are most common case without EDID)
+ */
+ fb_vmode.xres = 800;
+ fb_vmode.yres = 600;
+ fb_vmode.refresh = 60;
+ default_vmode = fb_find_nearest_mode(&fb_vmode,
+ &info->modelist);
}
- mutex_init(&dev_info->bulk_mutex);
+ fb_videomode_to_var(var, default_vmode);
+ dlfb_var_color_format(var);
- dev_info->udev = usb_get_dev(interface_to_usbdev(interface));
- dev_info->interface = interface;
+ return result;
+}
- printk("DisplayLink device attached\n");
+static ssize_t metrics_bytes_rendered_show(struct device *fbdev,
+ struct device_attribute *a, char *buf) {
+ struct fb_info *fb_info = dev_get_drvdata(fbdev);
+ struct dlfb_data *dev = fb_info->par;
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ atomic_read(&dev->bytes_rendered));
+}
- /* add framebuffer info to usb interface */
- usb_set_intfdata(interface, dev_info);
+static ssize_t metrics_bytes_identical_show(struct device *fbdev,
+ struct device_attribute *a, char *buf) {
+ struct fb_info *fb_info = dev_get_drvdata(fbdev);
+ struct dlfb_data *dev = fb_info->par;
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ atomic_read(&dev->bytes_identical));
+}
- dev_info->buf = kmalloc(BUF_SIZE, GFP_KERNEL);
- /* usb_buffer_alloc(dev_info->udev, BUF_SIZE , GFP_KERNEL, &dev_info->tx_urb->transfer_dma); */
+static ssize_t metrics_bytes_sent_show(struct device *fbdev,
+ struct device_attribute *a, char *buf) {
+ struct fb_info *fb_info = dev_get_drvdata(fbdev);
+ struct dlfb_data *dev = fb_info->par;
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ atomic_read(&dev->bytes_sent));
+}
- if (dev_info->buf == NULL) {
- printk("unable to allocate memory for dlfb commands\n");
- goto out;
- }
- dev_info->bufend = dev_info->buf + BUF_SIZE;
+static ssize_t metrics_cpu_kcycles_used_show(struct device *fbdev,
+ struct device_attribute *a, char *buf) {
+ struct fb_info *fb_info = dev_get_drvdata(fbdev);
+ struct dlfb_data *dev = fb_info->par;
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ atomic_read(&dev->cpu_kcycles_used));
+}
- dev_info->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
- usb_fill_bulk_urb(dev_info->tx_urb, dev_info->udev,
- usb_sndbulkpipe(dev_info->udev, 1), dev_info->buf, 0,
- dlfb_bulk_callback, dev_info);
+static ssize_t metrics_misc_show(struct device *fbdev,
+ struct device_attribute *a, char *buf) {
+ struct fb_info *fb_info = dev_get_drvdata(fbdev);
+ struct dlfb_data *dev = fb_info->par;
+ return snprintf(buf, PAGE_SIZE,
+ "Calls to\ndamage: %u\nblit: %u\n"
+ "defio faults: %u\ncopy: %u\n"
+ "fill: %u\n\n"
+ "active framebuffer clients: %d\n"
+ "urbs available %d(%d)\n"
+ "Shadow framebuffer in use? %s\n"
+ "Any lost pixels? %s\n",
+ atomic_read(&dev->damage_count),
+ atomic_read(&dev->blit_count),
+ atomic_read(&dev->defio_fault_count),
+ atomic_read(&dev->copy_count),
+ atomic_read(&dev->fill_count),
+ dev->fb_count,
+ dev->urbs.available, dev->urbs.limit_sem.count,
+ (dev->backing_buffer) ? "yes" : "no",
+ atomic_read(&dev->lost_pixels) ? "yes" : "no");
+}
- ret =
- usb_control_msg(dev_info->udev, usb_rcvctrlpipe(dev_info->udev, 0),
- (0x06), (0x80 | (0x02 << 5)), 0, 0, rbuf, 4, 0);
- printk("ret control msg 0: %d %x%x%x%x\n", ret, rbuf[0], rbuf[1],
- rbuf[2], rbuf[3]);
+static ssize_t edid_show(struct kobject *kobj, struct bin_attribute *a,
+ char *buf, loff_t off, size_t count) {
+ struct device *fbdev = container_of(kobj, struct device, kobj);
+ struct fb_info *fb_info = dev_get_drvdata(fbdev);
+ struct dlfb_data *dev = fb_info->par;
+ char *edid = &dev->edid[0];
+ const size_t size = sizeof(dev->edid);
- dlfb_edid(dev_info);
+ if (dlfb_parse_edid(dev, &fb_info->var, fb_info))
+ return 0;
- info = framebuffer_alloc(sizeof(u32) * 256, &dev_info->udev->dev);
+ if (off >= size)
+ return 0;
- if (!info) {
- printk("non posso allocare il framebuffer displaylink");
- goto out;
- }
+ if (off + count > size)
+ count = size - off;
+ memcpy(buf, edid + off, count);
- fb_parse_edid(dev_info->edid, &info->var);
+ return count;
+}
- printk("EDID XRES %d YRES %d\n", info->var.xres, info->var.yres);
- if (dlfb_set_video_mode(dev_info, info->var.xres, info->var.yres) != 0) {
- info->var.xres = 1280;
- info->var.yres = 1024;
- if (dlfb_set_video_mode
- (dev_info, info->var.xres, info->var.yres) != 0) {
- goto out;
- }
+static ssize_t metrics_reset_store(struct device *fbdev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fb_info *fb_info = dev_get_drvdata(fbdev);
+ struct dlfb_data *dev = fb_info->par;
+
+ atomic_set(&dev->bytes_rendered, 0);
+ atomic_set(&dev->bytes_identical, 0);
+ atomic_set(&dev->bytes_sent, 0);
+ atomic_set(&dev->cpu_kcycles_used, 0);
+ atomic_set(&dev->blit_count, 0);
+ atomic_set(&dev->copy_count, 0);
+ atomic_set(&dev->fill_count, 0);
+ atomic_set(&dev->defio_fault_count, 0);
+ atomic_set(&dev->damage_count, 0);
+
+ return count;
+}
+
+static ssize_t use_defio_show(struct device *fbdev,
+ struct device_attribute *a, char *buf) {
+ struct fb_info *fb_info = dev_get_drvdata(fbdev);
+ struct dlfb_data *dev = fb_info->par;
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ atomic_read(&dev->use_defio));
+}
+
+static ssize_t use_defio_store(struct device *fbdev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct fb_info *fb_info = dev_get_drvdata(fbdev);
+ struct dlfb_data *dev = fb_info->par;
+
+ if (count > 0) {
+ if (buf[0] == '0')
+ atomic_set(&dev->use_defio, 0);
+ if (buf[0] == '1')
+ atomic_set(&dev->use_defio, 1);
}
+ return count;
+}
- printk("found valid mode...%d\n", info->var.pixclock);
+static struct bin_attribute edid_attr = {
+ .attr.name = "edid",
+ .attr.mode = 0444,
+ .size = 128,
+ .read = edid_show,
+};
- info->pseudo_palette = info->par;
- info->par = dev_info;
+static struct device_attribute fb_device_attrs[] = {
+ __ATTR_RO(metrics_bytes_rendered),
+ __ATTR_RO(metrics_bytes_identical),
+ __ATTR_RO(metrics_bytes_sent),
+ __ATTR_RO(metrics_cpu_kcycles_used),
+ __ATTR_RO(metrics_misc),
+ __ATTR(metrics_reset, S_IWUGO, NULL, metrics_reset_store),
+ __ATTR_RW(use_defio),
+};
- dev_info->info = info;
+#ifdef CONFIG_FB_DEFERRED_IO
+static void dlfb_dpy_deferred_io(struct fb_info *info,
+ struct list_head *pagelist)
+{
+ struct page *cur;
+ struct fb_deferred_io *fbdefio = info->fbdefio;
+ struct dlfb_data *dev = info->par;
+ struct urb *urb;
+ char *cmd;
+ cycles_t start_cycles, end_cycles;
+ int bytes_sent = 0;
+ int bytes_identical = 0;
+ int bytes_rendered = 0;
+ int fault_count = 0;
+
+ if (!atomic_read(&dev->use_defio))
+ return;
- info->flags =
- FBINFO_DEFAULT | FBINFO_READS_FAST | FBINFO_HWACCEL_IMAGEBLIT |
- FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
- info->fbops = &dlfb_ops;
- info->screen_base = rvmalloc(dev_info->screen_size);
+ if (!atomic_read(&dev->usb_active))
+ return;
+
+ start_cycles = get_cycles();
- if (info->screen_base == NULL) {
- printk
- ("cannot allocate framebuffer virtual memory of %d bytes\n",
- dev_info->screen_size);
- goto out0;
+ urb = dlfb_get_urb(dev);
+ if (!urb)
+ return;
+ cmd = urb->transfer_buffer;
+
+ /* walk the written page list and render each to device */
+ list_for_each_entry(cur, &fbdefio->pagelist, lru) {
+ dlfb_render_hline(dev, &urb, (char *) info->fix.smem_start,
+ &cmd, cur->index << PAGE_SHIFT,
+ PAGE_SIZE, &bytes_identical, &bytes_sent);
+ bytes_rendered += PAGE_SIZE;
+ fault_count++;
}
- printk("screen base allocated !!!\n");
+ if (cmd > (char *) urb->transfer_buffer) {
+ /* Send partial buffer remaining before exiting */
+ int len = cmd - (char *) urb->transfer_buffer;
+ dlfb_submit_urb(dev, urb, len);
+ bytes_sent += len;
+ } else
+ dlfb_urb_completion(urb);
+
+ atomic_add(fault_count, &dev->defio_fault_count);
+ atomic_add(bytes_sent, &dev->bytes_sent);
+ atomic_add(bytes_identical, &dev->bytes_identical);
+ atomic_add(bytes_rendered, &dev->bytes_rendered);
+ end_cycles = get_cycles();
+ atomic_add(((unsigned int) ((end_cycles - start_cycles)
+ >> 10)), /* Kcycles */
+ &dev->cpu_kcycles_used);
+}
- dev_info->backing_buffer = kzalloc(dev_info->screen_size, GFP_KERNEL);
+static struct fb_deferred_io dlfb_defio = {
+ .delay = 5,
+ .deferred_io = dlfb_dpy_deferred_io,
+};
- if (!dev_info->backing_buffer)
- printk("non posso allocare il backing buffer\n");
+#endif
- /* info->var = dev_info->si; */
+/*
+ * This is necessary before we can communicate with the display controller.
+ */
+static int dlfb_select_std_channel(struct dlfb_data *dev)
+{
+ int ret;
+ u8 set_def_chn[] = { 0x57, 0xCD, 0xDC, 0xA7,
+ 0x1C, 0x88, 0x5E, 0x15,
+ 0x60, 0xFE, 0xC6, 0x97,
+ 0x16, 0x3D, 0x47, 0xF2 };
+
+ ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+ NR_USB_REQUEST_CHANNEL,
+ (USB_DIR_OUT | USB_TYPE_VENDOR), 0, 0,
+ set_def_chn, sizeof(set_def_chn), USB_CTRL_SET_TIMEOUT);
+ return ret;
+}
- info->var.bits_per_pixel = 16;
- info->var.activate = FB_ACTIVATE_TEST;
- info->var.vmode = FB_VMODE_NONINTERLACED;
- info->var.red.offset = 11;
- info->var.red.length = 5;
- info->var.red.msb_right = 0;
+static int dlfb_usb_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ struct usb_device *usbdev;
+ struct dlfb_data *dev;
+ struct fb_info *info;
+ int videomemorysize;
+ int i;
+ unsigned char *videomemory;
+ int retval = -ENOMEM;
+ struct fb_var_screeninfo *var;
+ int registered = 0;
+ u16 *pix_framebuffer;
+
+ /* usb initialization */
+
+ usbdev = interface_to_usbdev(interface);
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (dev == NULL) {
+ err("dlfb_usb_probe: failed alloc of dev struct\n");
+ goto error;
+ }
- info->var.green.offset = 5;
- info->var.green.length = 6;
- info->var.green.msb_right = 0;
+ /* we need to wait for both usb and fbdev to spin down on disconnect */
+ kref_init(&dev->kref); /* matching kref_put in usb .disconnect fn */
+ kref_get(&dev->kref); /* matching kref_put in .fb_destroy function*/
- info->var.blue.offset = 0;
- info->var.blue.length = 5;
- info->var.blue.msb_right = 0;
+ dev->udev = usbdev;
+ dev->gdev = &usbdev->dev; /* our generic struct device * */
+ usb_set_intfdata(interface, dev);
- /* info->var.pixclock = (10000000 / FB_W * 1000 / FB_H)/2 ; */
+ if (!dlfb_alloc_urb_list(dev, WRITES_IN_FLIGHT, MAX_TRANSFER)) {
+ retval = -ENOMEM;
+ dl_err("dlfb_alloc_urb_list failed\n");
+ goto error;
+ }
- info->fix.smem_start = (unsigned long)info->screen_base;
- info->fix.smem_len = PAGE_ALIGN(dev_info->screen_size);
- if (strlen(dev_info->udev->product) > 15) {
- memcpy(info->fix.id, dev_info->udev->product, 15);
- } else {
- memcpy(info->fix.id, dev_info->udev->product,
- strlen(dev_info->udev->product));
+ mutex_init(&dev->fb_open_lock);
+
+ /* We don't register a new USB class. Our client interface is fbdev */
+
+ /* allocates framebuffer driver structure, not framebuffer memory */
+ info = framebuffer_alloc(0, &usbdev->dev);
+ if (!info) {
+ retval = -ENOMEM;
+ dl_err("framebuffer_alloc failed\n");
+ goto error;
+ }
+ dev->info = info;
+ info->par = dev;
+ info->pseudo_palette = dev->pseudo_palette;
+ info->fbops = &dlfb_ops;
+
+ var = &info->var;
+
+ /* TODO set limit based on actual SKU detection */
+ dev->sku_pixel_limit = 2048 * 1152;
+
+ INIT_LIST_HEAD(&info->modelist);
+ dlfb_parse_edid(dev, var, info);
+
+ /*
+ * ok, now that we've got the size info, we can alloc our framebuffer.
+ */
+ info->fix = dlfb_fix;
+ info->fix.line_length = var->xres * (var->bits_per_pixel / 8);
+ videomemorysize = info->fix.line_length * var->yres;
+
+ /*
+ * The big chunk of system memory we use as a virtual framebuffer.
+ * TODO: Handle fbcon cursor code calling blit in interrupt context
+ */
+ videomemory = vmalloc(videomemorysize);
+ if (!videomemory) {
+ retval = -ENOMEM;
+ dl_err("Virtual framebuffer alloc failed\n");
+ goto error;
}
- info->fix.type = FB_TYPE_PACKED_PIXELS;
- info->fix.visual = FB_VISUAL_TRUECOLOR;
- info->fix.accel = info->flags;
- info->fix.line_length = dev_info->line_length;
- if (fb_alloc_cmap(&info->cmap, 256, 0) < 0)
- goto out1;
+ info->screen_base = videomemory;
+ info->fix.smem_len = PAGE_ALIGN(videomemorysize);
+ info->fix.smem_start = (unsigned long) videomemory;
+ info->flags = udlfb_info_flags;
+
+
+ /*
+ * Second framebuffer copy, mirroring the state of the framebuffer
+ * on the physical USB device. We can function without this.
+ * But with imperfect damage info we may end up sending pixels over USB
+ * that were, in fact, unchanged -- wasting limited USB bandwidth
+ */
+ dev->backing_buffer = vmalloc(videomemorysize);
+ if (!dev->backing_buffer)
+ dl_warn("No shadow/backing buffer allcoated\n");
+ else
+ memset(dev->backing_buffer, 0, videomemorysize);
+
+ retval = fb_alloc_cmap(&info->cmap, 256, 0);
+ if (retval < 0) {
+ dl_err("fb_alloc_cmap failed %x\n", retval);
+ goto error;
+ }
+
+ /* ready to begin using device */
+
+#ifdef CONFIG_FB_DEFERRED_IO
+ atomic_set(&dev->use_defio, 1);
+#endif
+ atomic_set(&dev->usb_active, 1);
+ dlfb_select_std_channel(dev);
+
+ dlfb_ops_check_var(var, info);
+ dlfb_ops_set_par(info);
+
+ /* paint greenscreen */
+ pix_framebuffer = (u16 *) videomemory;
+ for (i = 0; i < videomemorysize / 2; i++)
+ pix_framebuffer[i] = 0x37e6;
+
+ dlfb_handle_damage(dev, 0, 0, info->var.xres, info->var.yres,
+ videomemory);
- printk("colormap allocated\n");
- if (register_framebuffer(info) < 0)
- goto out2;
+ retval = register_framebuffer(info);
+ if (retval < 0) {
+ dl_err("register_framebuffer failed %d\n", retval);
+ goto error;
+ }
+ registered = 1;
+
+ for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
+ device_create_file(info->dev, &fb_device_attrs[i]);
- draw_rect(dev_info, 0, 0, dev_info->info->var.xres,
- dev_info->info->var.yres, 0x30, 0xff, 0x30);
+ device_create_bin_file(info->dev, &edid_attr);
+ dl_err("DisplayLink USB device /dev/fb%d attached. %dx%d resolution."
+ " Using %dK framebuffer memory\n", info->node,
+ var->xres, var->yres,
+ ((dev->backing_buffer) ?
+ videomemorysize * 2 : videomemorysize) >> 10);
return 0;
-out2:
- fb_dealloc_cmap(&info->cmap);
-out1:
- rvfree(info->screen_base, dev_info->screen_size);
-out0:
- framebuffer_release(info);
-out:
- usb_set_intfdata(interface, NULL);
- usb_put_dev(dev_info->udev);
- kfree(dev_info);
- return -ENOMEM;
+error:
+ if (dev) {
+ if (registered) {
+ unregister_framebuffer(info);
+ dlfb_ops_destroy(info);
+ } else
+ kref_put(&dev->kref, dlfb_delete);
+
+ if (dev->urbs.count > 0)
+ dlfb_free_urb_list(dev);
+ kref_put(&dev->kref, dlfb_delete); /* last ref from kref_init */
+
+ /* dev has been deallocated. Do not dereference */
+ }
+ return retval;
}
-static void dlfb_disconnect(struct usb_interface *interface)
+static void dlfb_usb_disconnect(struct usb_interface *interface)
{
- struct dlfb_data *dev_info = usb_get_intfdata(interface);
+ struct dlfb_data *dev;
+ struct fb_info *info;
+ int i;
+
+ dev = usb_get_intfdata(interface);
+ info = dev->info;
- mutex_unlock(&dev_info->bulk_mutex);
+ /* when non-active we'll update virtual framebuffer, but no new urbs */
+ atomic_set(&dev->usb_active, 0);
- usb_kill_urb(dev_info->tx_urb);
- usb_free_urb(dev_info->tx_urb);
usb_set_intfdata(interface, NULL);
- usb_put_dev(dev_info->udev);
- if (dev_info->info) {
- unregister_framebuffer(dev_info->info);
- fb_dealloc_cmap(&dev_info->info->cmap);
- rvfree(dev_info->info->screen_base, dev_info->screen_size);
- kfree(dev_info->backing_buffer);
- framebuffer_release(dev_info->info);
+ for (i = 0; i < ARRAY_SIZE(fb_device_attrs); i++)
+ device_remove_file(info->dev, &fb_device_attrs[i]);
+
+ device_remove_bin_file(info->dev, &edid_attr);
+ /* this function will wait for all in-flight urbs to complete */
+ dlfb_free_urb_list(dev);
+
+ if (info) {
+ dl_notice("Detaching /dev/fb%d\n", info->node);
+ unregister_framebuffer(info);
+ dlfb_ops_destroy(info);
}
- kfree(dev_info);
+ /* release reference taken by kref_init in probe() */
+ kref_put(&dev->kref, dlfb_delete);
+
+ /* consider dlfb_data freed */
- printk("DisplayLink device disconnected\n");
+ return;
}
static struct usb_driver dlfb_driver = {
.name = "udlfb",
- .probe = dlfb_probe,
- .disconnect = dlfb_disconnect,
+ .probe = dlfb_usb_probe,
+ .disconnect = dlfb_usb_disconnect,
.id_table = id_table,
};
-static int __init dlfb_init(void)
+static int __init dlfb_module_init(void)
{
int res;
- dlfb_init_modes();
-
res = usb_register(&dlfb_driver);
if (res)
err("usb_register failed. Error number %d", res);
@@ -925,14 +1442,186 @@ static int __init dlfb_init(void)
return res;
}
-static void __exit dlfb_exit(void)
+static void __exit dlfb_module_exit(void)
{
usb_deregister(&dlfb_driver);
}
-module_init(dlfb_init);
-module_exit(dlfb_exit);
+module_init(dlfb_module_init);
+module_exit(dlfb_module_exit);
-MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>");
-MODULE_DESCRIPTION(DRIVER_VERSION);
+static void dlfb_urb_completion(struct urb *urb)
+{
+ struct urb_node *unode = urb->context;
+ struct dlfb_data *dev = unode->dev;
+ unsigned long flags;
+
+ /* sync/async unlink faults aren't errors */
+ if (urb->status) {
+ if (!(urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -ESHUTDOWN)) {
+ dl_err("%s - nonzero write bulk status received: %d\n",
+ __func__, urb->status);
+ atomic_set(&dev->lost_pixels, 1);
+ }
+ }
+
+ urb->transfer_buffer_length = dev->urbs.size; /* reset to actual */
+
+ spin_lock_irqsave(&dev->urbs.lock, flags);
+ list_add_tail(&unode->entry, &dev->urbs.list);
+ dev->urbs.available++;
+ spin_unlock_irqrestore(&dev->urbs.lock, flags);
+
+ up(&dev->urbs.limit_sem);
+}
+
+static void dlfb_free_urb_list(struct dlfb_data *dev)
+{
+ int count = dev->urbs.count;
+ struct list_head *node;
+ struct urb_node *unode;
+ struct urb *urb;
+ int ret;
+ unsigned long flags;
+
+ dl_notice("Waiting for completes and freeing all render urbs\n");
+
+ /* keep waiting and freeing, until we've got 'em all */
+ while (count--) {
+ /* Timeout means a memory leak and/or fault */
+ ret = down_timeout(&dev->urbs.limit_sem, FREE_URB_TIMEOUT);
+ if (ret) {
+ BUG_ON(ret);
+ break;
+ }
+ spin_lock_irqsave(&dev->urbs.lock, flags);
+
+ node = dev->urbs.list.next; /* have reserved one with sem */
+ list_del_init(node);
+
+ spin_unlock_irqrestore(&dev->urbs.lock, flags);
+
+ unode = list_entry(node, struct urb_node, entry);
+ urb = unode->urb;
+
+ /* Free each separately allocated piece */
+ usb_buffer_free(urb->dev, dev->urbs.size,
+ urb->transfer_buffer, urb->transfer_dma);
+ usb_free_urb(urb);
+ kfree(node);
+ }
+
+ kref_put(&dev->kref, dlfb_delete);
+
+}
+
+static int dlfb_alloc_urb_list(struct dlfb_data *dev, int count, size_t size)
+{
+ int i = 0;
+ struct urb *urb;
+ struct urb_node *unode;
+ char *buf;
+
+ spin_lock_init(&dev->urbs.lock);
+
+ dev->urbs.size = size;
+ INIT_LIST_HEAD(&dev->urbs.list);
+
+ while (i < count) {
+ unode = kzalloc(sizeof(struct urb_node), GFP_KERNEL);
+ if (!unode)
+ break;
+ unode->dev = dev;
+
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb) {
+ kfree(unode);
+ break;
+ }
+ unode->urb = urb;
+
+ buf = usb_buffer_alloc(dev->udev, MAX_TRANSFER, GFP_KERNEL,
+ &urb->transfer_dma);
+ if (!buf) {
+ kfree(unode);
+ usb_free_urb(urb);
+ break;
+ }
+
+ /* urb->transfer_buffer_length set to actual before submit */
+ usb_fill_bulk_urb(urb, dev->udev, usb_sndbulkpipe(dev->udev, 1),
+ buf, size, dlfb_urb_completion, unode);
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ list_add_tail(&unode->entry, &dev->urbs.list);
+
+ i++;
+ }
+
+ sema_init(&dev->urbs.limit_sem, i);
+ dev->urbs.count = i;
+ dev->urbs.available = i;
+
+ kref_get(&dev->kref); /* released in free_render_urbs() */
+
+ dl_notice("allocated %d %d byte urbs \n", i, (int) size);
+
+ return i;
+}
+
+static struct urb *dlfb_get_urb(struct dlfb_data *dev)
+{
+ int ret = 0;
+ struct list_head *entry;
+ struct urb_node *unode;
+ struct urb *urb = NULL;
+ unsigned long flags;
+
+ /* Wait for an in-flight buffer to complete and get re-queued */
+ ret = down_timeout(&dev->urbs.limit_sem, GET_URB_TIMEOUT);
+ if (ret) {
+ atomic_set(&dev->lost_pixels, 1);
+ dl_err("wait for urb interrupted: %x\n", ret);
+ goto error;
+ }
+
+ spin_lock_irqsave(&dev->urbs.lock, flags);
+
+ BUG_ON(list_empty(&dev->urbs.list)); /* reserved one with limit_sem */
+ entry = dev->urbs.list.next;
+ list_del_init(entry);
+ dev->urbs.available--;
+
+ spin_unlock_irqrestore(&dev->urbs.lock, flags);
+
+ unode = list_entry(entry, struct urb_node, entry);
+ urb = unode->urb;
+
+error:
+ return urb;
+}
+
+static int dlfb_submit_urb(struct dlfb_data *dev, struct urb *urb, size_t len)
+{
+ int ret;
+
+ BUG_ON(len > dev->urbs.size);
+
+ urb->transfer_buffer_length = len; /* set to actual payload len */
+ ret = usb_submit_urb(urb, GFP_KERNEL);
+ if (ret) {
+ dlfb_urb_completion(urb); /* because no one else will */
+ atomic_set(&dev->lost_pixels, 1);
+ dl_err("usb_submit_urb error %x\n", ret);
+ }
+ return ret;
+}
+
+MODULE_AUTHOR("Roberto De Ioris <roberto@unbit.it>, "
+ "Jaya Kumar <jayakumar.lkml@gmail.com>, "
+ "Bernie Thompson <bernie@plugable.com>");
+MODULE_DESCRIPTION("DisplayLink kernel framebuffer driver");
MODULE_LICENSE("GPL");
+
diff --git a/drivers/staging/udlfb/udlfb.h b/drivers/staging/udlfb/udlfb.h
index 40ad85ea8e6..b07a69371f1 100644
--- a/drivers/staging/udlfb/udlfb.h
+++ b/drivers/staging/udlfb/udlfb.h
@@ -1,225 +1,106 @@
#ifndef UDLFB_H
#define UDLFB_H
-#define MAX_VMODES 4
-#define FB_BPP 16
+/*
+ * TODO: Propose standard fb.h ioctl for reporting damage,
+ * using _IOWR() and one of the existing area structs from fb.h
+ * Consider these ioctls deprecated, but they're still used by the
+ * DisplayLink X server as yet - need both to be modified in tandem
+ * when new ioctl(s) are ready.
+ */
+#define DLFB_IOCTL_RETURN_EDID 0xAD
+#define DLFB_IOCTL_REPORT_DAMAGE 0xAA
+struct dloarea {
+ int x, y;
+ int w, h;
+ int x2, y2;
+};
-#define STD_CHANNEL "\x57\xCD\xDC\xA7\x1C\x88\x5E\x15" \
- "\x60\xFE\xC6\x97\x16\x3D\x47\xF2"
+struct urb_node {
+ struct list_head entry;
+ struct dlfb_data *dev;
+ struct urb *urb;
+};
-/* as libdlo */
-#define BUF_HIGH_WATER_MARK 1024
-#define BUF_SIZE (64*1024)
+struct urb_list {
+ struct list_head list;
+ spinlock_t lock;
+ struct semaphore limit_sem;
+ int available;
+ int count;
+ size_t size;
+};
struct dlfb_data {
struct usb_device *udev;
- struct usb_interface *interface;
- struct urb *tx_urb, *ctrl_urb;
- struct usb_ctrlrequest dr;
+ struct device *gdev; /* &udev->dev */
struct fb_info *info;
- char *buf;
- char *bufend;
+ struct urb_list urbs;
+ struct kref kref;
char *backing_buffer;
- struct mutex bulk_mutex;
+ struct delayed_work deferred_work;
+ struct mutex fb_open_lock;
+ int fb_count;
+ atomic_t usb_active; /* 0 = update virtual buffer, but no usb traffic */
+ atomic_t lost_pixels; /* 1 = a render op failed. Need screen refresh */
+ atomic_t use_defio; /* 0 = rely on ioctls and blit/copy/fill rects */
char edid[128];
- int screen_size;
- int line_length;
- struct completion done;
+ int sku_pixel_limit;
int base16;
- int base16d;
int base8;
- int base8d;
+ u32 pseudo_palette[256];
+ /* blit-only rendering path metrics, exposed through sysfs */
+ atomic_t bytes_rendered; /* raw pixel-bytes driver asked to render */
+ atomic_t bytes_identical; /* saved effort with backbuffer comparison */
+ atomic_t bytes_sent; /* to usb, after compression including overhead */
+ atomic_t cpu_kcycles_used; /* transpired during pixel processing */
+ /* interface usage metrics. Clients can call driver via several */
+ atomic_t blit_count;
+ atomic_t copy_count;
+ atomic_t fill_count;
+ atomic_t damage_count;
+ atomic_t defio_fault_count;
};
-struct dlfb_video_mode {
- uint8_t col;
- uint32_t hclock;
- uint32_t vclock;
- uint8_t unknown1[6];
- uint16_t xres;
- uint8_t unknown2[6];
- uint16_t yres;
- uint8_t unknown3[4];
-} __attribute__ ((__packed__));
-
-static struct dlfb_video_mode dlfb_video_modes[MAX_VMODES];
-
-static void dlfb_bulk_callback(struct urb *urb)
-{
- struct dlfb_data *dev_info = urb->context;
- complete(&dev_info->done);
-}
-
-static void dlfb_edid(struct dlfb_data *dev_info)
-{
- int i;
- int ret;
- char rbuf[2];
-
- for (i = 0; i < 128; i++) {
- ret =
- usb_control_msg(dev_info->udev,
- usb_rcvctrlpipe(dev_info->udev, 0), (0x02),
- (0x80 | (0x02 << 5)), i << 8, 0xA1, rbuf, 2,
- 0);
- /*printk("ret control msg edid %d: %d [%d]\n",i, ret, rbuf[1]); */
- dev_info->edid[i] = rbuf[1];
- }
-
-}
-
-static int dlfb_bulk_msg(struct dlfb_data *dev_info, int len)
-{
- int ret;
-
- init_completion(&dev_info->done);
-
- dev_info->tx_urb->actual_length = 0;
- dev_info->tx_urb->transfer_buffer_length = len;
-
- ret = usb_submit_urb(dev_info->tx_urb, GFP_KERNEL);
- if (!wait_for_completion_timeout(&dev_info->done, 1000)) {
- usb_kill_urb(dev_info->tx_urb);
- printk("usb timeout !!!\n");
- }
-
- return dev_info->tx_urb->actual_length;
-}
-
-static void dlfb_init_modes(void)
-{
- dlfb_video_modes[0].col = 0;
- memcpy(&dlfb_video_modes[0].hclock, "\x20\x3C\x7A\xC9", 4);
- memcpy(&dlfb_video_modes[0].vclock, "\xF2\x6C\x48\xF9", 4);
- memcpy(&dlfb_video_modes[0].unknown1, "\x70\x53\xFF\xFF\x21\x27", 6);
- dlfb_video_modes[0].xres = 800;
- memcpy(&dlfb_video_modes[0].unknown2, "\x91\xF3\xFF\xFF\xFF\xF9", 6);
- dlfb_video_modes[0].yres = 480;
- memcpy(&dlfb_video_modes[0].unknown3, "\x01\x02\xC8\x19", 4);
-
- dlfb_video_modes[1].col = 0;
- memcpy(&dlfb_video_modes[1].hclock, "\x36\x18\xD5\x10", 4);
- memcpy(&dlfb_video_modes[1].vclock, "\x60\xA9\x7B\x33", 4);
- memcpy(&dlfb_video_modes[1].unknown1, "\xA1\x2B\x27\x32\xFF\xFF", 6);
- dlfb_video_modes[1].xres = 1024;
- memcpy(&dlfb_video_modes[1].unknown2, "\xD9\x9A\xFF\xCA\xFF\xFF", 6);
- dlfb_video_modes[1].yres = 768;
- memcpy(&dlfb_video_modes[1].unknown3, "\x04\x03\xC8\x32", 4);
-
- dlfb_video_modes[2].col = 0;
- memcpy(&dlfb_video_modes[2].hclock, "\x98\xF8\x0D\x57", 4);
- memcpy(&dlfb_video_modes[2].vclock, "\x2A\x55\x4D\x54", 4);
- memcpy(&dlfb_video_modes[2].unknown1, "\xCA\x0D\xFF\xFF\x94\x43", 6);
- dlfb_video_modes[2].xres = 1280;
- memcpy(&dlfb_video_modes[2].unknown2, "\x9A\xA8\xFF\xFF\xFF\xF9", 6);
- dlfb_video_modes[2].yres = 1024;
- memcpy(&dlfb_video_modes[2].unknown3, "\x04\x02\x60\x54", 4);
-
- dlfb_video_modes[3].col = 0;
- memcpy(&dlfb_video_modes[3].hclock, "\x42\x24\x38\x36", 4);
- memcpy(&dlfb_video_modes[3].vclock, "\xC1\x52\xD9\x29", 4);
- memcpy(&dlfb_video_modes[3].unknown1, "\xEA\xB8\x32\x60\xFF\xFF", 6);
- dlfb_video_modes[3].xres = 1400;
- memcpy(&dlfb_video_modes[3].unknown2, "\xC9\x4E\xFF\xFF\xFF\xF2", 6);
- dlfb_video_modes[3].yres = 1050;
- memcpy(&dlfb_video_modes[3].unknown3, "\x04\x02\x1E\x5F", 4);
-}
-
-static char *dlfb_set_register(char *bufptr, uint8_t reg, uint8_t val)
-{
- *bufptr++ = 0xAF;
- *bufptr++ = 0x20;
- *bufptr++ = reg;
- *bufptr++ = val;
-
- return bufptr;
-}
-
-static int dlfb_set_video_mode(struct dlfb_data *dev_info, int width, int height)
-{
- int i, ret;
- unsigned char j;
- char *bufptr = dev_info->buf;
- uint8_t *vdata;
-
- for (i = 0; i < MAX_VMODES; i++) {
- printk("INIT VIDEO %d %d %d\n", i, dlfb_video_modes[i].xres,
- dlfb_video_modes[i].yres);
- if (dlfb_video_modes[i].xres == width
- && dlfb_video_modes[i].yres == height) {
-
- dev_info->base16 = 0;
- dev_info->base16d = width * height * (FB_BPP / 8);
-
- //dev_info->base8 = width * height * (FB_BPP / 8);
-
- dev_info->base8 = dev_info->base16;
- dev_info->base8d = dev_info->base16d;
-
- /* set encryption key (null) */
- memcpy(dev_info->buf, STD_CHANNEL, 16);
- ret =
- usb_control_msg(dev_info->udev,
- usb_sndctrlpipe(dev_info->udev, 0),
- 0x12, (0x02 << 5), 0, 0,
- dev_info->buf, 16, 0);
- printk("ret control msg 1 (STD_CHANNEL): %d\n", ret);
-
- /* set registers */
- bufptr = dlfb_set_register(bufptr, 0xFF, 0x00);
-
- /* set color depth */
- bufptr = dlfb_set_register(bufptr, 0x00, 0x00);
-
- /* set addresses */
- bufptr =
- dlfb_set_register(bufptr, 0x20,
- (char)(dev_info->base16 >> 16));
- bufptr =
- dlfb_set_register(bufptr, 0x21,
- (char)(dev_info->base16 >> 8));
- bufptr =
- dlfb_set_register(bufptr, 0x22,
- (char)(dev_info->base16));
-
- bufptr =
- dlfb_set_register(bufptr, 0x26,
- (char)(dev_info->base8 >> 16));
- bufptr =
- dlfb_set_register(bufptr, 0x27,
- (char)(dev_info->base8 >> 8));
- bufptr =
- dlfb_set_register(bufptr, 0x28,
- (char)(dev_info->base8));
+#define NR_USB_REQUEST_I2C_SUB_IO 0x02
+#define NR_USB_REQUEST_CHANNEL 0x12
- /* set video mode */
- vdata = (uint8_t *)&dlfb_video_modes[i];
- for (j = 0; j < 29; j++)
- bufptr = dlfb_set_register(bufptr, j, vdata[j]);
+/* -BULK_SIZE as per usb-skeleton. Can we get full page and avoid overhead? */
+#define BULK_SIZE 512
+#define MAX_TRANSFER (PAGE_SIZE*16 - BULK_SIZE)
+#define WRITES_IN_FLIGHT (4)
- /* blank */
- bufptr = dlfb_set_register(bufptr, 0x1F, 0x00);
+#define GET_URB_TIMEOUT HZ
+#define FREE_URB_TIMEOUT (HZ*2)
- /* end registers */
- bufptr = dlfb_set_register(bufptr, 0xFF, 0xFF);
+#define BPP 2
+#define MAX_CMD_PIXELS 255
- /* send */
- ret = dlfb_bulk_msg(dev_info, bufptr - dev_info->buf);
- printk("ret bulk 2: %d %td\n", ret,
- bufptr - dev_info->buf);
+#define RLX_HEADER_BYTES 7
+#define MIN_RLX_PIX_BYTES 4
+#define MIN_RLX_CMD_BYTES (RLX_HEADER_BYTES + MIN_RLX_PIX_BYTES)
- /* flush */
- ret = dlfb_bulk_msg(dev_info, 0);
- printk("ret bulk 3: %d\n", ret);
+#define RLE_HEADER_BYTES 6
+#define MIN_RLE_PIX_BYTES 3
+#define MIN_RLE_CMD_BYTES (RLE_HEADER_BYTES + MIN_RLE_PIX_BYTES)
- dev_info->screen_size = width * height * (FB_BPP / 8);
- dev_info->line_length = width * (FB_BPP / 8);
+#define RAW_HEADER_BYTES 6
+#define MIN_RAW_PIX_BYTES 2
+#define MIN_RAW_CMD_BYTES (RAW_HEADER_BYTES + MIN_RAW_PIX_BYTES)
- return 0;
- }
- }
+/* remove these once align.h patch is taken into kernel */
+#define DL_ALIGN_UP(x, a) ALIGN(x, a)
+#define DL_ALIGN_DOWN(x, a) ALIGN(x-(a-1), a)
- return -1;
-}
+/* remove once this gets added to sysfs.h */
+#define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store)
+#define dl_err(format, arg...) \
+ dev_err(dev->gdev, "dlfb: " format, ## arg)
+#define dl_warn(format, arg...) \
+ dev_warn(dev->gdev, "dlfb: " format, ## arg)
+#define dl_notice(format, arg...) \
+ dev_notice(dev->gdev, "dlfb: " format, ## arg)
+#define dl_info(format, arg...) \
+ dev_info(dev->gdev, "dlfb: " format, ## arg)
#endif
diff --git a/drivers/staging/usbip/Kconfig b/drivers/staging/usbip/Kconfig
index 350d5d65ccf..2c1d10acb8b 100644
--- a/drivers/staging/usbip/Kconfig
+++ b/drivers/staging/usbip/Kconfig
@@ -34,3 +34,10 @@ config USB_IP_HOST
To compile this driver as a module, choose M here: the
module will be called usbip.
+
+config USB_IP_DEBUG_ENABLE
+ bool "USB-IP Debug Enable"
+ depends on USB_IP_COMMON
+ default N
+ ---help---
+ This enables the debug messages from the USB-IP drivers.
diff --git a/drivers/staging/usbip/Makefile b/drivers/staging/usbip/Makefile
index 179f4211f96..6f2916b1807 100644
--- a/drivers/staging/usbip/Makefile
+++ b/drivers/staging/usbip/Makefile
@@ -7,6 +7,6 @@ vhci-hcd-objs := vhci_sysfs.o vhci_tx.o vhci_rx.o vhci_hcd.o
obj-$(CONFIG_USB_IP_HOST) += usbip.o
usbip-objs := stub_dev.o stub_main.o stub_rx.o stub_tx.o
-ifeq ($(CONFIG_USB_DEBUG),y)
+ifeq ($(CONFIG_USB_IP_DEBUG_ENABLE),y)
EXTRA_CFLAGS += -DDEBUG
endif
diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c
index ddb6f5fd04d..7a45da8f956 100644
--- a/drivers/staging/usbip/usbip_common.c
+++ b/drivers/staging/usbip/usbip_common.c
@@ -33,7 +33,7 @@
/*-------------------------------------------------------------------------*/
/* debug routines */
-#ifdef CONFIG_USB_DEBUG
+#ifdef CONFIG_USB_IP_DEBUG_ENABLE
unsigned long usbip_debug_flag = 0xffffffff;
#else
unsigned long usbip_debug_flag;
@@ -55,10 +55,7 @@ static ssize_t show_flag(struct device *dev, struct device_attribute *attr,
static ssize_t store_flag(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- unsigned long flag;
-
- sscanf(buf, "%lx", &flag);
- usbip_debug_flag = flag;
+ sscanf(buf, "%lx", &usbip_debug_flag);
return count;
}
@@ -66,33 +63,8 @@ DEVICE_ATTR(usbip_debug, (S_IRUGO | S_IWUSR), show_flag, store_flag);
static void usbip_dump_buffer(char *buff, int bufflen)
{
- int i;
-
- if (bufflen > 128) {
- for (i = 0; i < 128; i++) {
- if (i%24 == 0)
- printk(KERN_DEBUG " ");
- printk(KERN_DEBUG "%02x ", (unsigned char) buff[i]);
- if (i%4 == 3)
- printk(KERN_DEBUG "| ");
- if (i%24 == 23)
- printk(KERN_DEBUG "\n");
- }
- printk(KERN_DEBUG "... (%d byte)\n", bufflen);
- return;
- }
-
- for (i = 0; i < bufflen; i++) {
- if (i%24 == 0)
- printk(KERN_DEBUG " ");
- printk(KERN_DEBUG "%02x ", (unsigned char) buff[i]);
- if (i%4 == 3)
- printk(KERN_DEBUG "| ");
- if (i%24 == 23)
- printk(KERN_DEBUG "\n");
- }
- printk(KERN_DEBUG "\n");
-
+ print_hex_dump(KERN_DEBUG, "usb-ip", DUMP_PREFIX_OFFSET, 16, 4,
+ buff, bufflen, false);
}
static void usbip_dump_pipe(unsigned int p)
@@ -558,60 +530,6 @@ err:
}
EXPORT_SYMBOL_GPL(usbip_xmit);
-
-/* now a usrland utility should set options. */
-#if 0
-int setquickack(struct socket *socket)
-{
- mm_segment_t oldfs;
- int val = 1;
- int ret;
-
- oldfs = get_fs();
- set_fs(get_ds());
- ret = socket->ops->setsockopt(socket, SOL_TCP, TCP_QUICKACK,
- (char __user *) &val, sizeof(ret));
- set_fs(oldfs);
-
- return ret;
-}
-
-int setnodelay(struct socket *socket)
-{
- mm_segment_t oldfs;
- int val = 1;
- int ret;
-
- oldfs = get_fs();
- set_fs(get_ds());
- ret = socket->ops->setsockopt(socket, SOL_TCP, TCP_NODELAY,
- (char __user *) &val, sizeof(ret));
- set_fs(oldfs);
-
- return ret;
-}
-
-int setkeepalive(struct socket *socket)
-{
- mm_segment_t oldfs;
- int val = 1;
- int ret;
-
- oldfs = get_fs();
- set_fs(get_ds());
- ret = socket->ops->setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE,
- (char __user *) &val, sizeof(ret));
- set_fs(oldfs);
-
- return ret;
-}
-
-void setreuse(struct socket *socket)
-{
- socket->sk->sk_reuse = 1;
-}
-#endif
-
struct socket *sockfd_to_socket(unsigned int sockfd)
{
struct socket *socket;
diff --git a/drivers/staging/usbip/usbip_common.h b/drivers/staging/usbip/usbip_common.h
index 1ca3eab8af1..6f1dcb197d1 100644
--- a/drivers/staging/usbip/usbip_common.h
+++ b/drivers/staging/usbip/usbip_common.h
@@ -33,12 +33,12 @@
*/
/**
- * usbip_udbg - print debug messages if CONFIG_USB_DEBUG is defined
+ * usbip_udbg - print debug messages if CONFIG_USB_IP_DEBUG_ENABLE is defined
* @fmt:
* @args:
*/
-#ifdef CONFIG_USB_DEBUG
+#ifdef CONFIG_USB_IP_DEBUG_ENABLE
#define usbip_udbg(fmt, args...) \
do { \
@@ -47,11 +47,11 @@
__FILE__, __LINE__, __func__, ##args); \
} while (0)
-#else /* CONFIG_USB_DEBUG */
+#else /* CONFIG_USB_IP_DEBUG_ENABLE */
#define usbip_udbg(fmt, args...) do { } while (0)
-#endif /* CONFIG_USB_DEBUG */
+#endif /* CONFIG_USB_IP_DEBUG_ENABLE */
enum {
diff --git a/drivers/staging/vme/Kconfig b/drivers/staging/vme/Kconfig
index ae628a58b0c..6411ae51ed3 100644
--- a/drivers/staging/vme/Kconfig
+++ b/drivers/staging/vme/Kconfig
@@ -14,4 +14,6 @@ source "drivers/staging/vme/bridges/Kconfig"
source "drivers/staging/vme/devices/Kconfig"
+source "drivers/staging/vme/boards/Kconfig"
+
endif # VME
diff --git a/drivers/staging/vme/Makefile b/drivers/staging/vme/Makefile
index 8c3b90ee585..b4ea3f8d0a5 100644
--- a/drivers/staging/vme/Makefile
+++ b/drivers/staging/vme/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_VME_BUS) += vme.o
obj-y += bridges/
obj-y += devices/
+obj-y += boards/
diff --git a/drivers/staging/vme/TODO b/drivers/staging/vme/TODO
index 2201ff6f74d..82c222b4a14 100644
--- a/drivers/staging/vme/TODO
+++ b/drivers/staging/vme/TODO
@@ -4,28 +4,6 @@
API
===
-DMA Resource Allocation incomplete
-----------------------------------
-
-The current DMA resource Allocation provides no means of selecting the
-suitability of a DMA controller based on it's supported modes of operation, as
-opposed to the resource allocation mechanisms for master and slave windows:
-
- struct vme_resource *vme_dma_request(struct device *dev);
-
-As opposed to:
-
- struct vme_resource * vme_master_request(struct device *dev,
- vme_address_t aspace, vme_cycle_t cycle, vme_width_t width);
-
-The TSI148 can perform, VME-to-PCI, PCI-to-VME, PATTERN-to-VME, PATTERN-to-PCI,
-VME-to-VME and PCI-to-PCI transfers. The CA91C142 can only provide VME-to-PCI
-and PCI-to-VME.
-
-Add a mechanism to select a VME controller based on source/target type,
-required aspace, cycle and width requirements.
-
-
Master window broadcast select mask
-----------------------------------
@@ -59,7 +37,6 @@ chips. They are currently not supported at all by the API.
Core
====
-- Rename vme_master_resource's "pci_resource" to be bus agnostic.
- Improve generic sanity checks (Such as does an offset and size fit within a
window and parameter checking).
@@ -69,7 +46,6 @@ Bridge Support
Tempe (tsi148)
--------------
-- Driver can currently only support a single bridge.
- 2eSST Broadcast mode.
- Mailboxes unsupported.
- Improve error detection.
@@ -80,10 +56,6 @@ Tempe (tsi148)
Universe II (ca91c142)
----------------------
-- Driver can currently only support a single bridge.
-- DMA unsupported.
-- RMW transactions unsupported.
-- Location Monitors unsupported.
- Mailboxes unsupported.
- Error Detection.
- Control of prefetch size, threshold.
diff --git a/drivers/staging/vme/boards/Kconfig b/drivers/staging/vme/boards/Kconfig
new file mode 100644
index 00000000000..76163135352
--- /dev/null
+++ b/drivers/staging/vme/boards/Kconfig
@@ -0,0 +1,9 @@
+comment "VME Board Drivers"
+
+config VMIVME_7805
+ tristate "VMIVME-7805"
+ help
+ If you say Y here you get support for the VMIVME-7805 board.
+ This board has an additional control interface to the Universe II
+ chip. This driver has to be included if you want to access VME bus
+ with VMIVME-7805 board.
diff --git a/drivers/staging/vme/boards/Makefile b/drivers/staging/vme/boards/Makefile
new file mode 100644
index 00000000000..43658340885
--- /dev/null
+++ b/drivers/staging/vme/boards/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the VME board drivers.
+#
+
+obj-$(CONFIG_VMIVME_7805) += vme_vmivme7805.o
diff --git a/drivers/staging/vme/boards/vme_vmivme7805.c b/drivers/staging/vme/boards/vme_vmivme7805.c
new file mode 100644
index 00000000000..843c9edde55
--- /dev/null
+++ b/drivers/staging/vme/boards/vme_vmivme7805.c
@@ -0,0 +1,124 @@
+/*
+ * Support for the VMIVME-7805 board access to the Universe II bridge.
+ *
+ * Author: Arthur Benilov <arthur.benilov@iba-group.com>
+ * Copyright 2010 Ion Beam Application, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/poll.h>
+#include <linux/io.h>
+
+#include "vme_vmivme7805.h"
+
+static int __init vmic_init(void);
+static int vmic_probe(struct pci_dev *, const struct pci_device_id *);
+static void vmic_remove(struct pci_dev *);
+static void __exit vmic_exit(void);
+
+/** Base address to access FPGA register */
+static void *vmic_base;
+
+static char driver_name[] = "vmivme_7805";
+
+static struct pci_device_id vmic_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_VMIC, PCI_DEVICE_ID_VTIMR) },
+ { },
+};
+
+static struct pci_driver vmic_driver = {
+ .name = driver_name,
+ .id_table = vmic_ids,
+ .probe = vmic_probe,
+ .remove = vmic_remove,
+};
+
+static int __init vmic_init(void)
+{
+ return pci_register_driver(&vmic_driver);
+}
+
+static int vmic_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ int retval;
+ u32 data;
+
+ /* Enable the device */
+ retval = pci_enable_device(pdev);
+ if (retval) {
+ dev_err(&pdev->dev, "Unable to enable device\n");
+ goto err;
+ }
+
+ /* Map Registers */
+ retval = pci_request_regions(pdev, driver_name);
+ if (retval) {
+ dev_err(&pdev->dev, "Unable to reserve resources\n");
+ goto err_resource;
+ }
+
+ /* Map registers in BAR 0 */
+ vmic_base = ioremap_nocache(pci_resource_start(pdev, 0), 16);
+ if (!vmic_base) {
+ dev_err(&pdev->dev, "Unable to remap CRG region\n");
+ retval = -EIO;
+ goto err_remap;
+ }
+
+ /* Clear the FPGA VME IF contents */
+ iowrite32(0, vmic_base + VME_CONTROL);
+
+ /* Clear any initial BERR */
+ data = ioread32(vmic_base + VME_CONTROL) & 0x00000FFF;
+ data |= BM_VME_CONTROL_BERRST;
+ iowrite32(data, vmic_base + VME_CONTROL);
+
+ /* Enable the vme interface and byte swapping */
+ data = ioread32(vmic_base + VME_CONTROL) & 0x00000FFF;
+ data = data | BM_VME_CONTROL_MASTER_ENDIAN |
+ BM_VME_CONTROL_SLAVE_ENDIAN |
+ BM_VME_CONTROL_ABLE |
+ BM_VME_CONTROL_BERRI |
+ BM_VME_CONTROL_BPENA |
+ BM_VME_CONTROL_VBENA;
+ iowrite32(data, vmic_base + VME_CONTROL);
+
+ return 0;
+
+err_remap:
+ pci_release_regions(pdev);
+err_resource:
+ pci_disable_device(pdev);
+err:
+ return retval;
+}
+
+static void vmic_remove(struct pci_dev *pdev)
+{
+ iounmap(vmic_base);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+
+}
+
+static void __exit vmic_exit(void)
+{
+ pci_unregister_driver(&vmic_driver);
+}
+
+MODULE_DESCRIPTION("VMIVME-7805 board support driver");
+MODULE_AUTHOR("Arthur Benilov <arthur.benilov@iba-group.com>");
+MODULE_LICENSE("GPL");
+
+module_init(vmic_init);
+module_exit(vmic_exit);
+
diff --git a/drivers/staging/vme/boards/vme_vmivme7805.h b/drivers/staging/vme/boards/vme_vmivme7805.h
new file mode 100644
index 00000000000..44c2c449808
--- /dev/null
+++ b/drivers/staging/vme/boards/vme_vmivme7805.h
@@ -0,0 +1,37 @@
+/*
+ * vmivme_7805.h
+ *
+ * Support for the VMIVME-7805 board access to the Universe II bridge.
+ *
+ * Author: Arthur Benilov <arthur.benilov@iba-group.com>
+ * Copyright 2010 Ion Beam Application, 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.
+ */
+
+
+#ifndef _VMIVME_7805_H
+#define _VMIVME_7805_H
+
+#ifndef PCI_VENDOR_ID_VMIC
+#define PCI_VENDOR_ID_VMIC 0x114A
+#endif
+
+#ifndef PCI_DEVICE_ID_VTIMR
+#define PCI_DEVICE_ID_VTIMR 0x0004
+#endif
+
+#define VME_CONTROL 0x0000
+#define BM_VME_CONTROL_MASTER_ENDIAN 0x0001
+#define BM_VME_CONTROL_SLAVE_ENDIAN 0x0002
+#define BM_VME_CONTROL_ABLE 0x0004
+#define BM_VME_CONTROL_BERRI 0x0040
+#define BM_VME_CONTROL_BERRST 0x0080
+#define BM_VME_CONTROL_BPENA 0x0400
+#define BM_VME_CONTROL_VBENA 0x0800
+
+#endif /* _VMIVME_7805_H */
+
diff --git a/drivers/staging/vme/bridges/Kconfig b/drivers/staging/vme/bridges/Kconfig
index 023cceba0c5..9331064e047 100644
--- a/drivers/staging/vme/bridges/Kconfig
+++ b/drivers/staging/vme/bridges/Kconfig
@@ -2,12 +2,14 @@ comment "VME Bridge Drivers"
config VME_CA91CX42
tristate "Universe II"
+ depends on VIRT_TO_BUS
help
If you say Y here you get support for the Tundra CA91C142
(Universe II) VME bridge chip.
config VME_TSI148
tristate "Tempe"
+ depends on VIRT_TO_BUS
help
If you say Y here you get support for the Tundra TSI148 VME bridge
chip.
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c
index 1cf3e91db59..2795ff2411e 100644
--- a/drivers/staging/vme/bridges/vme_ca91cx42.c
+++ b/drivers/staging/vme/bridges/vme_ca91cx42.c
@@ -1,8 +1,8 @@
/*
* Support for the Tundra Universe I/II VME-PCI Bridge Chips
*
- * Author: Martyn Welch <martyn.welch@gefanuc.com>
- * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ * Author: Martyn Welch <martyn.welch@ge.com>
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
*
* Based on work by Tom Armistead and Ajit Prem
* Copyright 2004 Motorola Inc.
@@ -38,25 +38,12 @@ static int ca91cx42_probe(struct pci_dev *, const struct pci_device_id *);
static void ca91cx42_remove(struct pci_dev *);
static void __exit ca91cx42_exit(void);
-struct vme_bridge *ca91cx42_bridge;
-wait_queue_head_t dma_queue;
-wait_queue_head_t iack_queue;
-wait_queue_head_t lm_queue;
-wait_queue_head_t mbox_queue;
-
-void (*lm_callback[4])(int); /* Called in interrupt handler, be careful! */
-void *crcsr_kernel;
-dma_addr_t crcsr_bus;
-
-struct mutex vme_rmw; /* Only one RMW cycle at a time */
-struct mutex vme_int; /*
- * Only one VME interrupt can be
- * generated at a time, provide locking
- */
+/* Module parameters */
+static int geoid;
static char driver_name[] = "vme_ca91cx42";
-static struct pci_device_id ca91cx42_ids[] = {
+static const struct pci_device_id ca91cx42_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_CA91C142) },
{ },
};
@@ -68,14 +55,14 @@ static struct pci_driver ca91cx42_driver = {
.remove = ca91cx42_remove,
};
-static u32 ca91cx42_DMA_irqhandler(void)
+static u32 ca91cx42_DMA_irqhandler(struct ca91cx42_driver *bridge)
{
- wake_up(&dma_queue);
+ wake_up(&(bridge->dma_queue));
return CA91CX42_LINT_DMA;
}
-static u32 ca91cx42_LM_irqhandler(u32 stat)
+static u32 ca91cx42_LM_irqhandler(struct ca91cx42_driver *bridge, u32 stat)
{
int i;
u32 serviced = 0;
@@ -83,7 +70,7 @@ static u32 ca91cx42_LM_irqhandler(u32 stat)
for (i = 0; i < 4; i++) {
if (stat & CA91CX42_LINT_LM[i]) {
/* We only enable interrupts if the callback is set */
- lm_callback[i](i);
+ bridge->lm_callback[i](i);
serviced |= CA91CX42_LINT_LM[i];
}
}
@@ -92,40 +79,25 @@ static u32 ca91cx42_LM_irqhandler(u32 stat)
}
/* XXX This needs to be split into 4 queues */
-static u32 ca91cx42_MB_irqhandler(int mbox_mask)
+static u32 ca91cx42_MB_irqhandler(struct ca91cx42_driver *bridge, int mbox_mask)
{
- wake_up(&mbox_queue);
+ wake_up(&(bridge->mbox_queue));
return CA91CX42_LINT_MBOX;
}
-static u32 ca91cx42_IACK_irqhandler(void)
+static u32 ca91cx42_IACK_irqhandler(struct ca91cx42_driver *bridge)
{
- wake_up(&iack_queue);
+ wake_up(&(bridge->iack_queue));
return CA91CX42_LINT_SW_IACK;
}
-#if 0
-int ca91cx42_bus_error_chk(int clrflag)
-{
- int tmp;
- tmp = ioread32(ca91cx42_bridge->base + PCI_COMMAND);
- if (tmp & 0x08000000) { /* S_TA is Set */
- if (clrflag)
- iowrite32(tmp | 0x08000000,
- ca91cx42_bridge->base + PCI_COMMAND);
- return 1;
- }
- return 0;
-}
-#endif
-
-static u32 ca91cx42_VERR_irqhandler(void)
+static u32 ca91cx42_VERR_irqhandler(struct ca91cx42_driver *bridge)
{
int val;
- val = ioread32(ca91cx42_bridge->base + DGCS);
+ val = ioread32(bridge->base + DGCS);
if (!(val & 0x00000800)) {
printk(KERN_ERR "ca91c042: ca91cx42_VERR_irqhandler DMA Read "
@@ -135,11 +107,11 @@ static u32 ca91cx42_VERR_irqhandler(void)
return CA91CX42_LINT_VERR;
}
-static u32 ca91cx42_LERR_irqhandler(void)
+static u32 ca91cx42_LERR_irqhandler(struct ca91cx42_driver *bridge)
{
int val;
- val = ioread32(ca91cx42_bridge->base + DGCS);
+ val = ioread32(bridge->base + DGCS);
if (!(val & 0x00000800)) {
printk(KERN_ERR "ca91c042: ca91cx42_LERR_irqhandler DMA Read "
@@ -151,13 +123,18 @@ static u32 ca91cx42_LERR_irqhandler(void)
}
-static u32 ca91cx42_VIRQ_irqhandler(int stat)
+static u32 ca91cx42_VIRQ_irqhandler(struct vme_bridge *ca91cx42_bridge,
+ int stat)
{
int vec, i, serviced = 0;
+ struct ca91cx42_driver *bridge;
+
+ bridge = ca91cx42_bridge->driver_priv;
+
for (i = 7; i > 0; i--) {
if (stat & (1 << i)) {
- vec = ioread32(ca91cx42_bridge->base +
+ vec = ioread32(bridge->base +
CA91CX42_V_STATID[i]) & 0xff;
vme_irq_handler(ca91cx42_bridge, i, vec);
@@ -169,15 +146,18 @@ static u32 ca91cx42_VIRQ_irqhandler(int stat)
return serviced;
}
-static irqreturn_t ca91cx42_irqhandler(int irq, void *dev_id)
+static irqreturn_t ca91cx42_irqhandler(int irq, void *ptr)
{
u32 stat, enable, serviced = 0;
+ struct vme_bridge *ca91cx42_bridge;
+ struct ca91cx42_driver *bridge;
- if (dev_id != ca91cx42_bridge->base)
- return IRQ_NONE;
+ ca91cx42_bridge = ptr;
- enable = ioread32(ca91cx42_bridge->base + LINT_EN);
- stat = ioread32(ca91cx42_bridge->base + LINT_STAT);
+ bridge = ca91cx42_bridge->driver_priv;
+
+ enable = ioread32(bridge->base + LINT_EN);
+ stat = ioread32(bridge->base + LINT_STAT);
/* Only look at unmasked interrupts */
stat &= enable;
@@ -186,42 +166,45 @@ static irqreturn_t ca91cx42_irqhandler(int irq, void *dev_id)
return IRQ_NONE;
if (stat & CA91CX42_LINT_DMA)
- serviced |= ca91cx42_DMA_irqhandler();
+ serviced |= ca91cx42_DMA_irqhandler(bridge);
if (stat & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 |
CA91CX42_LINT_LM3))
- serviced |= ca91cx42_LM_irqhandler(stat);
+ serviced |= ca91cx42_LM_irqhandler(bridge, stat);
if (stat & CA91CX42_LINT_MBOX)
- serviced |= ca91cx42_MB_irqhandler(stat);
+ serviced |= ca91cx42_MB_irqhandler(bridge, stat);
if (stat & CA91CX42_LINT_SW_IACK)
- serviced |= ca91cx42_IACK_irqhandler();
+ serviced |= ca91cx42_IACK_irqhandler(bridge);
if (stat & CA91CX42_LINT_VERR)
- serviced |= ca91cx42_VERR_irqhandler();
+ serviced |= ca91cx42_VERR_irqhandler(bridge);
if (stat & CA91CX42_LINT_LERR)
- serviced |= ca91cx42_LERR_irqhandler();
+ serviced |= ca91cx42_LERR_irqhandler(bridge);
if (stat & (CA91CX42_LINT_VIRQ1 | CA91CX42_LINT_VIRQ2 |
CA91CX42_LINT_VIRQ3 | CA91CX42_LINT_VIRQ4 |
CA91CX42_LINT_VIRQ5 | CA91CX42_LINT_VIRQ6 |
CA91CX42_LINT_VIRQ7))
- serviced |= ca91cx42_VIRQ_irqhandler(stat);
+ serviced |= ca91cx42_VIRQ_irqhandler(ca91cx42_bridge, stat);
/* Clear serviced interrupts */
- iowrite32(stat, ca91cx42_bridge->base + LINT_STAT);
+ iowrite32(stat, bridge->base + LINT_STAT);
return IRQ_HANDLED;
}
-static int ca91cx42_irq_init(struct vme_bridge *bridge)
+static int ca91cx42_irq_init(struct vme_bridge *ca91cx42_bridge)
{
int result, tmp;
struct pci_dev *pdev;
+ struct ca91cx42_driver *bridge;
+
+ bridge = ca91cx42_bridge->driver_priv;
/* Need pdev */
- pdev = container_of(bridge->parent, struct pci_dev, dev);
+ pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev);
/* Initialise list for VME bus errors */
- INIT_LIST_HEAD(&(bridge->vme_errors));
+ INIT_LIST_HEAD(&(ca91cx42_bridge->vme_errors));
- mutex_init(&(bridge->irq_mtx));
+ mutex_init(&(ca91cx42_bridge->irq_mtx));
/* Disable interrupts from PCI to VME */
iowrite32(0, bridge->base + VINT_EN);
@@ -232,7 +215,7 @@ static int ca91cx42_irq_init(struct vme_bridge *bridge)
iowrite32(0x00FFFFFF, bridge->base + LINT_STAT);
result = request_irq(pdev->irq, ca91cx42_irqhandler, IRQF_SHARED,
- driver_name, pdev);
+ driver_name, ca91cx42_bridge);
if (result) {
dev_err(&pdev->dev, "Can't get assigned pci irq vector %02X\n",
pdev->irq);
@@ -254,15 +237,16 @@ static int ca91cx42_irq_init(struct vme_bridge *bridge)
return 0;
}
-static void ca91cx42_irq_exit(struct pci_dev *pdev)
+static void ca91cx42_irq_exit(struct ca91cx42_driver *bridge,
+ struct pci_dev *pdev)
{
/* Disable interrupts from PCI to VME */
- iowrite32(0, ca91cx42_bridge->base + VINT_EN);
+ iowrite32(0, bridge->base + VINT_EN);
/* Disable PCI interrupts */
- iowrite32(0, ca91cx42_bridge->base + LINT_EN);
+ iowrite32(0, bridge->base + LINT_EN);
/* Clear Any Pending PCI Interrupts */
- iowrite32(0x00FFFFFF, ca91cx42_bridge->base + LINT_STAT);
+ iowrite32(0x00FFFFFF, bridge->base + LINT_STAT);
free_irq(pdev->irq, pdev);
}
@@ -270,21 +254,25 @@ static void ca91cx42_irq_exit(struct pci_dev *pdev)
/*
* Set up an VME interrupt
*/
-void ca91cx42_irq_set(int level, int state, int sync)
+void ca91cx42_irq_set(struct vme_bridge *ca91cx42_bridge, int level, int state,
+ int sync)
{
struct pci_dev *pdev;
u32 tmp;
+ struct ca91cx42_driver *bridge;
+
+ bridge = ca91cx42_bridge->driver_priv;
/* Enable IRQ level */
- tmp = ioread32(ca91cx42_bridge->base + LINT_EN);
+ tmp = ioread32(bridge->base + LINT_EN);
if (state == 0)
tmp &= ~CA91CX42_LINT_VIRQ[level];
else
tmp |= CA91CX42_LINT_VIRQ[level];
- iowrite32(tmp, ca91cx42_bridge->base + LINT_EN);
+ iowrite32(tmp, bridge->base + LINT_EN);
if ((state == 0) && (sync != 0)) {
pdev = container_of(ca91cx42_bridge->parent, struct pci_dev,
@@ -294,34 +282,38 @@ void ca91cx42_irq_set(int level, int state, int sync)
}
}
-int ca91cx42_irq_generate(int level, int statid)
+int ca91cx42_irq_generate(struct vme_bridge *ca91cx42_bridge, int level,
+ int statid)
{
u32 tmp;
+ struct ca91cx42_driver *bridge;
+
+ bridge = ca91cx42_bridge->driver_priv;
/* Universe can only generate even vectors */
if (statid & 1)
return -EINVAL;
- mutex_lock(&(vme_int));
+ mutex_lock(&(bridge->vme_int));
- tmp = ioread32(ca91cx42_bridge->base + VINT_EN);
+ tmp = ioread32(bridge->base + VINT_EN);
/* Set Status/ID */
- iowrite32(statid << 24, ca91cx42_bridge->base + STATID);
+ iowrite32(statid << 24, bridge->base + STATID);
/* Assert VMEbus IRQ */
tmp = tmp | (1 << (level + 24));
- iowrite32(tmp, ca91cx42_bridge->base + VINT_EN);
+ iowrite32(tmp, bridge->base + VINT_EN);
/* Wait for IACK */
- wait_event_interruptible(iack_queue, 0);
+ wait_event_interruptible(bridge->iack_queue, 0);
/* Return interrupt to low state */
- tmp = ioread32(ca91cx42_bridge->base + VINT_EN);
+ tmp = ioread32(bridge->base + VINT_EN);
tmp = tmp & ~(1 << (level + 24));
- iowrite32(tmp, ca91cx42_bridge->base + VINT_EN);
+ iowrite32(tmp, bridge->base + VINT_EN);
- mutex_unlock(&(vme_int));
+ mutex_unlock(&(bridge->vme_int));
return 0;
}
@@ -330,9 +322,12 @@ int ca91cx42_slave_set(struct vme_slave_resource *image, int enabled,
unsigned long long vme_base, unsigned long long size,
dma_addr_t pci_base, vme_address_t aspace, vme_cycle_t cycle)
{
- unsigned int i, addr = 0, granularity = 0;
+ unsigned int i, addr = 0, granularity;
unsigned int temp_ctl = 0;
unsigned int vme_bound, pci_offset;
+ struct ca91cx42_driver *bridge;
+
+ bridge = image->parent->driver_priv;
i = image->number;
@@ -366,13 +361,9 @@ int ca91cx42_slave_set(struct vme_slave_resource *image, int enabled,
* Bound address is a valid address for the window, adjust
* accordingly
*/
- vme_bound = vme_base + size - granularity;
+ vme_bound = vme_base + size;
pci_offset = pci_base - vme_base;
- /* XXX Need to check that vme_base, vme_bound and pci_offset aren't
- * too big for registers
- */
-
if ((i == 0) || (i == 4))
granularity = 0x1000;
else
@@ -392,26 +383,14 @@ int ca91cx42_slave_set(struct vme_slave_resource *image, int enabled,
}
/* Disable while we are mucking around */
- temp_ctl = ioread32(ca91cx42_bridge->base + CA91CX42_VSI_CTL[i]);
+ temp_ctl = ioread32(bridge->base + CA91CX42_VSI_CTL[i]);
temp_ctl &= ~CA91CX42_VSI_CTL_EN;
- iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_VSI_CTL[i]);
+ iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]);
/* Setup mapping */
- iowrite32(vme_base, ca91cx42_bridge->base + CA91CX42_VSI_BS[i]);
- iowrite32(vme_bound, ca91cx42_bridge->base + CA91CX42_VSI_BD[i]);
- iowrite32(pci_offset, ca91cx42_bridge->base + CA91CX42_VSI_TO[i]);
-
-/* XXX Prefetch stuff currently unsupported */
-#if 0
- if (vmeIn->wrPostEnable)
- temp_ctl |= CA91CX42_VSI_CTL_PWEN;
- if (vmeIn->prefetchEnable)
- temp_ctl |= CA91CX42_VSI_CTL_PREN;
- if (vmeIn->rmwLock)
- temp_ctl |= CA91CX42_VSI_CTL_LLRMW;
- if (vmeIn->data64BitCapable)
- temp_ctl |= CA91CX42_VSI_CTL_LD64EN;
-#endif
+ iowrite32(vme_base, bridge->base + CA91CX42_VSI_BS[i]);
+ iowrite32(vme_bound, bridge->base + CA91CX42_VSI_BD[i]);
+ iowrite32(pci_offset, bridge->base + CA91CX42_VSI_TO[i]);
/* Setup address space */
temp_ctl &= ~CA91CX42_VSI_CTL_VAS_M;
@@ -429,12 +408,12 @@ int ca91cx42_slave_set(struct vme_slave_resource *image, int enabled,
temp_ctl |= CA91CX42_VSI_CTL_PGM_DATA;
/* Write ctl reg without enable */
- iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_VSI_CTL[i]);
+ iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]);
if (enabled)
temp_ctl |= CA91CX42_VSI_CTL_EN;
- iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_VSI_CTL[i]);
+ iowrite32(temp_ctl, bridge->base + CA91CX42_VSI_CTL[i]);
return 0;
}
@@ -445,6 +424,9 @@ int ca91cx42_slave_get(struct vme_slave_resource *image, int *enabled,
{
unsigned int i, granularity = 0, ctl = 0;
unsigned long long vme_bound, pci_offset;
+ struct ca91cx42_driver *bridge;
+
+ bridge = image->parent->driver_priv;
i = image->number;
@@ -454,11 +436,11 @@ int ca91cx42_slave_get(struct vme_slave_resource *image, int *enabled,
granularity = 0x10000;
/* Read Registers */
- ctl = ioread32(ca91cx42_bridge->base + CA91CX42_VSI_CTL[i]);
+ ctl = ioread32(bridge->base + CA91CX42_VSI_CTL[i]);
- *vme_base = ioread32(ca91cx42_bridge->base + CA91CX42_VSI_BS[i]);
- vme_bound = ioread32(ca91cx42_bridge->base + CA91CX42_VSI_BD[i]);
- pci_offset = ioread32(ca91cx42_bridge->base + CA91CX42_VSI_TO[i]);
+ *vme_base = ioread32(bridge->base + CA91CX42_VSI_BS[i]);
+ vme_bound = ioread32(bridge->base + CA91CX42_VSI_BD[i]);
+ pci_offset = ioread32(bridge->base + CA91CX42_VSI_TO[i]);
*pci_base = (dma_addr_t)vme_base + pci_offset;
*size = (unsigned long long)((vme_bound - *vme_base) + granularity);
@@ -502,6 +484,9 @@ static int ca91cx42_alloc_resource(struct vme_master_resource *image,
unsigned long long existing_size;
int retval = 0;
struct pci_dev *pdev;
+ struct vme_bridge *ca91cx42_bridge;
+
+ ca91cx42_bridge = image->parent;
/* Find pci_dev container of dev */
if (ca91cx42_bridge->parent == NULL) {
@@ -510,8 +495,8 @@ static int ca91cx42_alloc_resource(struct vme_master_resource *image,
}
pdev = container_of(ca91cx42_bridge->parent, struct pci_dev, dev);
- existing_size = (unsigned long long)(image->pci_resource.end -
- image->pci_resource.start);
+ existing_size = (unsigned long long)(image->bus_resource.end -
+ image->bus_resource.start);
/* If the existing size is OK, return */
if (existing_size == (size - 1))
@@ -520,15 +505,15 @@ static int ca91cx42_alloc_resource(struct vme_master_resource *image,
if (existing_size != 0) {
iounmap(image->kern_base);
image->kern_base = NULL;
- if (image->pci_resource.name != NULL)
- kfree(image->pci_resource.name);
- release_resource(&(image->pci_resource));
- memset(&(image->pci_resource), 0, sizeof(struct resource));
+ if (image->bus_resource.name != NULL)
+ kfree(image->bus_resource.name);
+ release_resource(&(image->bus_resource));
+ memset(&(image->bus_resource), 0, sizeof(struct resource));
}
- if (image->pci_resource.name == NULL) {
- image->pci_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL);
- if (image->pci_resource.name == NULL) {
+ if (image->bus_resource.name == NULL) {
+ image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL);
+ if (image->bus_resource.name == NULL) {
printk(KERN_ERR "Unable to allocate memory for resource"
" name\n");
retval = -ENOMEM;
@@ -536,26 +521,26 @@ static int ca91cx42_alloc_resource(struct vme_master_resource *image,
}
}
- sprintf((char *)image->pci_resource.name, "%s.%d",
+ sprintf((char *)image->bus_resource.name, "%s.%d",
ca91cx42_bridge->name, image->number);
- image->pci_resource.start = 0;
- image->pci_resource.end = (unsigned long)size;
- image->pci_resource.flags = IORESOURCE_MEM;
+ image->bus_resource.start = 0;
+ image->bus_resource.end = (unsigned long)size;
+ image->bus_resource.flags = IORESOURCE_MEM;
retval = pci_bus_alloc_resource(pdev->bus,
- &(image->pci_resource), size, size, PCIBIOS_MIN_MEM,
+ &(image->bus_resource), size, size, PCIBIOS_MIN_MEM,
0, NULL, NULL);
if (retval) {
printk(KERN_ERR "Failed to allocate mem resource for "
"window %d size 0x%lx start 0x%lx\n",
image->number, (unsigned long)size,
- (unsigned long)image->pci_resource.start);
+ (unsigned long)image->bus_resource.start);
goto err_resource;
}
image->kern_base = ioremap_nocache(
- image->pci_resource.start, size);
+ image->bus_resource.start, size);
if (image->kern_base == NULL) {
printk(KERN_ERR "Failed to remap resource\n");
retval = -ENOMEM;
@@ -567,24 +552,24 @@ static int ca91cx42_alloc_resource(struct vme_master_resource *image,
iounmap(image->kern_base);
image->kern_base = NULL;
err_remap:
- release_resource(&(image->pci_resource));
+ release_resource(&(image->bus_resource));
err_resource:
- kfree(image->pci_resource.name);
- memset(&(image->pci_resource), 0, sizeof(struct resource));
+ kfree(image->bus_resource.name);
+ memset(&(image->bus_resource), 0, sizeof(struct resource));
err_name:
return retval;
}
/*
- * * Free and unmap PCI Resource
- * */
+ * Free and unmap PCI Resource
+ */
static void ca91cx42_free_resource(struct vme_master_resource *image)
{
iounmap(image->kern_base);
image->kern_base = NULL;
- release_resource(&(image->pci_resource));
- kfree(image->pci_resource.name);
- memset(&(image->pci_resource), 0, sizeof(struct resource));
+ release_resource(&(image->bus_resource));
+ kfree(image->bus_resource.name);
+ memset(&(image->bus_resource), 0, sizeof(struct resource));
}
@@ -593,17 +578,27 @@ int ca91cx42_master_set(struct vme_master_resource *image, int enabled,
vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth)
{
int retval = 0;
- unsigned int i;
+ unsigned int i, granularity = 0;
unsigned int temp_ctl = 0;
unsigned long long pci_bound, vme_offset, pci_base;
+ struct ca91cx42_driver *bridge;
+
+ bridge = image->parent->driver_priv;
+
+ i = image->number;
+
+ if ((i == 0) || (i == 4))
+ granularity = 0x1000;
+ else
+ granularity = 0x10000;
/* Verify input data */
- if (vme_base & 0xFFF) {
+ if (vme_base & (granularity - 1)) {
printk(KERN_ERR "Invalid VME Window alignment\n");
retval = -EINVAL;
goto err_window;
}
- if (size & 0xFFF) {
+ if (size & (granularity - 1)) {
printk(KERN_ERR "Invalid VME Window alignment\n");
retval = -EINVAL;
goto err_window;
@@ -611,9 +606,6 @@ int ca91cx42_master_set(struct vme_master_resource *image, int enabled,
spin_lock(&(image->lock));
- /* XXX We should do this much later, so that we can exit without
- * needing to redo the mapping...
- */
/*
* Let's allocate the resource here rather than further up the stack as
* it avoids pushing loads of bus dependant stuff up the stack
@@ -627,27 +619,19 @@ int ca91cx42_master_set(struct vme_master_resource *image, int enabled,
goto err_res;
}
- pci_base = (unsigned long long)image->pci_resource.start;
+ pci_base = (unsigned long long)image->bus_resource.start;
/*
* Bound address is a valid address for the window, adjust
* according to window granularity.
*/
- pci_bound = pci_base + (size - 0x1000);
+ pci_bound = pci_base + size;
vme_offset = vme_base - pci_base;
- i = image->number;
-
/* Disable while we are mucking around */
- temp_ctl = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_CTL[i]);
+ temp_ctl = ioread32(bridge->base + CA91CX42_LSI_CTL[i]);
temp_ctl &= ~CA91CX42_LSI_CTL_EN;
- iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_LSI_CTL[i]);
-
-/* XXX Prefetch stuff currently unsupported */
-#if 0
- if (vmeOut->wrPostEnable)
- temp_ctl |= 0x40000000;
-#endif
+ iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]);
/* Setup cycle types */
temp_ctl &= ~CA91CX42_LSI_CTL_VCT_M;
@@ -718,17 +702,17 @@ int ca91cx42_master_set(struct vme_master_resource *image, int enabled,
temp_ctl |= CA91CX42_LSI_CTL_PGM_PGM;
/* Setup mapping */
- iowrite32(pci_base, ca91cx42_bridge->base + CA91CX42_LSI_BS[i]);
- iowrite32(pci_bound, ca91cx42_bridge->base + CA91CX42_LSI_BD[i]);
- iowrite32(vme_offset, ca91cx42_bridge->base + CA91CX42_LSI_TO[i]);
+ iowrite32(pci_base, bridge->base + CA91CX42_LSI_BS[i]);
+ iowrite32(pci_bound, bridge->base + CA91CX42_LSI_BD[i]);
+ iowrite32(vme_offset, bridge->base + CA91CX42_LSI_TO[i]);
/* Write ctl reg without enable */
- iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_LSI_CTL[i]);
+ iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]);
if (enabled)
temp_ctl |= CA91CX42_LSI_CTL_EN;
- iowrite32(temp_ctl, ca91cx42_bridge->base + CA91CX42_LSI_CTL[i]);
+ iowrite32(temp_ctl, bridge->base + CA91CX42_LSI_CTL[i]);
spin_unlock(&(image->lock));
return 0;
@@ -747,17 +731,20 @@ int __ca91cx42_master_get(struct vme_master_resource *image, int *enabled,
{
unsigned int i, ctl;
unsigned long long pci_base, pci_bound, vme_offset;
+ struct ca91cx42_driver *bridge;
+
+ bridge = image->parent->driver_priv;
i = image->number;
- ctl = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_CTL[i]);
+ ctl = ioread32(bridge->base + CA91CX42_LSI_CTL[i]);
- pci_base = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_BS[i]);
- vme_offset = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_TO[i]);
- pci_bound = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_BD[i]);
+ pci_base = ioread32(bridge->base + CA91CX42_LSI_BS[i]);
+ vme_offset = ioread32(bridge->base + CA91CX42_LSI_TO[i]);
+ pci_bound = ioread32(bridge->base + CA91CX42_LSI_BD[i]);
*vme_base = pci_base + vme_offset;
- *size = (pci_bound - pci_base) + 0x1000;
+ *size = (unsigned long long)(pci_bound - pci_base);
*enabled = 0;
*aspace = 0;
@@ -822,12 +809,6 @@ int __ca91cx42_master_get(struct vme_master_resource *image, int *enabled,
break;
}
-/* XXX Prefetch stuff currently unsupported */
-#if 0
- if (ctl & 0x40000000)
- vmeOut->wrPostEnable = 1;
-#endif
-
return 0;
}
@@ -850,7 +831,7 @@ int ca91cx42_master_get(struct vme_master_resource *image, int *enabled,
ssize_t ca91cx42_master_read(struct vme_master_resource *image, void *buf,
size_t count, loff_t offset)
{
- int retval;
+ ssize_t retval;
spin_lock(&(image->lock));
@@ -877,12 +858,528 @@ ssize_t ca91cx42_master_write(struct vme_master_resource *image, void *buf,
return retval;
}
-int ca91cx42_slot_get(void)
+unsigned int ca91cx42_master_rmw(struct vme_master_resource *image,
+ unsigned int mask, unsigned int compare, unsigned int swap,
+ loff_t offset)
+{
+ u32 pci_addr, result;
+ int i;
+ struct ca91cx42_driver *bridge;
+ struct device *dev;
+
+ bridge = image->parent->driver_priv;
+ dev = image->parent->parent;
+
+ /* Find the PCI address that maps to the desired VME address */
+ i = image->number;
+
+ /* Locking as we can only do one of these at a time */
+ mutex_lock(&(bridge->vme_rmw));
+
+ /* Lock image */
+ spin_lock(&(image->lock));
+
+ pci_addr = (u32)image->kern_base + offset;
+
+ /* Address must be 4-byte aligned */
+ if (pci_addr & 0x3) {
+ dev_err(dev, "RMW Address not 4-byte aligned\n");
+ return -EINVAL;
+ }
+
+ /* Ensure RMW Disabled whilst configuring */
+ iowrite32(0, bridge->base + SCYC_CTL);
+
+ /* Configure registers */
+ iowrite32(mask, bridge->base + SCYC_EN);
+ iowrite32(compare, bridge->base + SCYC_CMP);
+ iowrite32(swap, bridge->base + SCYC_SWP);
+ iowrite32(pci_addr, bridge->base + SCYC_ADDR);
+
+ /* Enable RMW */
+ iowrite32(CA91CX42_SCYC_CTL_CYC_RMW, bridge->base + SCYC_CTL);
+
+ /* Kick process off with a read to the required address. */
+ result = ioread32(image->kern_base + offset);
+
+ /* Disable RMW */
+ iowrite32(0, bridge->base + SCYC_CTL);
+
+ spin_unlock(&(image->lock));
+
+ mutex_unlock(&(bridge->vme_rmw));
+
+ return result;
+}
+
+int ca91cx42_dma_list_add(struct vme_dma_list *list, struct vme_dma_attr *src,
+ struct vme_dma_attr *dest, size_t count)
+{
+ struct ca91cx42_dma_entry *entry, *prev;
+ struct vme_dma_pci *pci_attr;
+ struct vme_dma_vme *vme_attr;
+ dma_addr_t desc_ptr;
+ int retval = 0;
+
+ /* XXX descriptor must be aligned on 64-bit boundaries */
+ entry = (struct ca91cx42_dma_entry *)
+ kmalloc(sizeof(struct ca91cx42_dma_entry), GFP_KERNEL);
+ if (entry == NULL) {
+ printk(KERN_ERR "Failed to allocate memory for dma resource "
+ "structure\n");
+ retval = -ENOMEM;
+ goto err_mem;
+ }
+
+ /* Test descriptor alignment */
+ if ((unsigned long)&(entry->descriptor) & CA91CX42_DCPP_M) {
+ printk("Descriptor not aligned to 16 byte boundary as "
+ "required: %p\n", &(entry->descriptor));
+ retval = -EINVAL;
+ goto err_align;
+ }
+
+ memset(&(entry->descriptor), 0, sizeof(struct ca91cx42_dma_descriptor));
+
+ if (dest->type == VME_DMA_VME) {
+ entry->descriptor.dctl |= CA91CX42_DCTL_L2V;
+ vme_attr = (struct vme_dma_vme *)dest->private;
+ pci_attr = (struct vme_dma_pci *)src->private;
+ } else {
+ vme_attr = (struct vme_dma_vme *)src->private;
+ pci_attr = (struct vme_dma_pci *)dest->private;
+ }
+
+ /* Check we can do fullfill required attributes */
+ if ((vme_attr->aspace & ~(VME_A16 | VME_A24 | VME_A32 | VME_USER1 |
+ VME_USER2)) != 0) {
+
+ printk(KERN_ERR "Unsupported cycle type\n");
+ retval = -EINVAL;
+ goto err_aspace;
+ }
+
+ if ((vme_attr->cycle & ~(VME_SCT | VME_BLT | VME_SUPER | VME_USER |
+ VME_PROG | VME_DATA)) != 0) {
+
+ printk(KERN_ERR "Unsupported cycle type\n");
+ retval = -EINVAL;
+ goto err_cycle;
+ }
+
+ /* Check to see if we can fullfill source and destination */
+ if (!(((src->type == VME_DMA_PCI) && (dest->type == VME_DMA_VME)) ||
+ ((src->type == VME_DMA_VME) && (dest->type == VME_DMA_PCI)))) {
+
+ printk(KERN_ERR "Cannot perform transfer with this "
+ "source-destination combination\n");
+ retval = -EINVAL;
+ goto err_direct;
+ }
+
+ /* Setup cycle types */
+ if (vme_attr->cycle & VME_BLT)
+ entry->descriptor.dctl |= CA91CX42_DCTL_VCT_BLT;
+
+ /* Setup data width */
+ switch (vme_attr->dwidth) {
+ case VME_D8:
+ entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D8;
+ break;
+ case VME_D16:
+ entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D16;
+ break;
+ case VME_D32:
+ entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D32;
+ break;
+ case VME_D64:
+ entry->descriptor.dctl |= CA91CX42_DCTL_VDW_D64;
+ break;
+ default:
+ printk(KERN_ERR "Invalid data width\n");
+ return -EINVAL;
+ }
+
+ /* Setup address space */
+ switch (vme_attr->aspace) {
+ case VME_A16:
+ entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A16;
+ break;
+ case VME_A24:
+ entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A24;
+ break;
+ case VME_A32:
+ entry->descriptor.dctl |= CA91CX42_DCTL_VAS_A32;
+ break;
+ case VME_USER1:
+ entry->descriptor.dctl |= CA91CX42_DCTL_VAS_USER1;
+ break;
+ case VME_USER2:
+ entry->descriptor.dctl |= CA91CX42_DCTL_VAS_USER2;
+ break;
+ default:
+ printk(KERN_ERR "Invalid address space\n");
+ return -EINVAL;
+ break;
+ }
+
+ if (vme_attr->cycle & VME_SUPER)
+ entry->descriptor.dctl |= CA91CX42_DCTL_SUPER_SUPR;
+ if (vme_attr->cycle & VME_PROG)
+ entry->descriptor.dctl |= CA91CX42_DCTL_PGM_PGM;
+
+ entry->descriptor.dtbc = count;
+ entry->descriptor.dla = pci_attr->address;
+ entry->descriptor.dva = vme_attr->address;
+ entry->descriptor.dcpp = CA91CX42_DCPP_NULL;
+
+ /* Add to list */
+ list_add_tail(&(entry->list), &(list->entries));
+
+ /* Fill out previous descriptors "Next Address" */
+ if (entry->list.prev != &(list->entries)) {
+ prev = list_entry(entry->list.prev, struct ca91cx42_dma_entry,
+ list);
+ /* We need the bus address for the pointer */
+ desc_ptr = virt_to_bus(&(entry->descriptor));
+ prev->descriptor.dcpp = desc_ptr & ~CA91CX42_DCPP_M;
+ }
+
+ return 0;
+
+err_cycle:
+err_aspace:
+err_direct:
+err_align:
+ kfree(entry);
+err_mem:
+ return retval;
+}
+
+static int ca91cx42_dma_busy(struct vme_bridge *ca91cx42_bridge)
+{
+ u32 tmp;
+ struct ca91cx42_driver *bridge;
+
+ bridge = ca91cx42_bridge->driver_priv;
+
+ tmp = ioread32(bridge->base + DGCS);
+
+ if (tmp & CA91CX42_DGCS_ACT)
+ return 0;
+ else
+ return 1;
+}
+
+int ca91cx42_dma_list_exec(struct vme_dma_list *list)
+{
+ struct vme_dma_resource *ctrlr;
+ struct ca91cx42_dma_entry *entry;
+ int retval = 0;
+ dma_addr_t bus_addr;
+ u32 val;
+
+ struct ca91cx42_driver *bridge;
+
+ ctrlr = list->parent;
+
+ bridge = ctrlr->parent->driver_priv;
+
+ mutex_lock(&(ctrlr->mtx));
+
+ if (!(list_empty(&(ctrlr->running)))) {
+ /*
+ * XXX We have an active DMA transfer and currently haven't
+ * sorted out the mechanism for "pending" DMA transfers.
+ * Return busy.
+ */
+ /* Need to add to pending here */
+ mutex_unlock(&(ctrlr->mtx));
+ return -EBUSY;
+ } else {
+ list_add(&(list->list), &(ctrlr->running));
+ }
+
+ /* Get first bus address and write into registers */
+ entry = list_first_entry(&(list->entries), struct ca91cx42_dma_entry,
+ list);
+
+ bus_addr = virt_to_bus(&(entry->descriptor));
+
+ mutex_unlock(&(ctrlr->mtx));
+
+ iowrite32(0, bridge->base + DTBC);
+ iowrite32(bus_addr & ~CA91CX42_DCPP_M, bridge->base + DCPP);
+
+ /* Start the operation */
+ val = ioread32(bridge->base + DGCS);
+
+ /* XXX Could set VMEbus On and Off Counters here */
+ val &= (CA91CX42_DGCS_VON_M | CA91CX42_DGCS_VOFF_M);
+
+ val |= (CA91CX42_DGCS_CHAIN | CA91CX42_DGCS_STOP | CA91CX42_DGCS_HALT |
+ CA91CX42_DGCS_DONE | CA91CX42_DGCS_LERR | CA91CX42_DGCS_VERR |
+ CA91CX42_DGCS_PERR);
+
+ iowrite32(val, bridge->base + DGCS);
+
+ val |= CA91CX42_DGCS_GO;
+
+ iowrite32(val, bridge->base + DGCS);
+
+ wait_event_interruptible(bridge->dma_queue,
+ ca91cx42_dma_busy(ctrlr->parent));
+
+ /*
+ * Read status register, this register is valid until we kick off a
+ * new transfer.
+ */
+ val = ioread32(bridge->base + DGCS);
+
+ if (val & (CA91CX42_DGCS_LERR | CA91CX42_DGCS_VERR |
+ CA91CX42_DGCS_PERR)) {
+
+ printk(KERN_ERR "ca91c042: DMA Error. DGCS=%08X\n", val);
+ val = ioread32(bridge->base + DCTL);
+ }
+
+ /* Remove list from running list */
+ mutex_lock(&(ctrlr->mtx));
+ list_del(&(list->list));
+ mutex_unlock(&(ctrlr->mtx));
+
+ return retval;
+
+}
+
+int ca91cx42_dma_list_empty(struct vme_dma_list *list)
+{
+ struct list_head *pos, *temp;
+ struct ca91cx42_dma_entry *entry;
+
+ /* detach and free each entry */
+ list_for_each_safe(pos, temp, &(list->entries)) {
+ list_del(pos);
+ entry = list_entry(pos, struct ca91cx42_dma_entry, list);
+ kfree(entry);
+ }
+
+ return 0;
+}
+
+/*
+ * All 4 location monitors reside at the same base - this is therefore a
+ * system wide configuration.
+ *
+ * This does not enable the LM monitor - that should be done when the first
+ * callback is attached and disabled when the last callback is removed.
+ */
+int ca91cx42_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base,
+ vme_address_t aspace, vme_cycle_t cycle)
+{
+ u32 temp_base, lm_ctl = 0;
+ int i;
+ struct ca91cx42_driver *bridge;
+ struct device *dev;
+
+ bridge = lm->parent->driver_priv;
+ dev = lm->parent->parent;
+
+ /* Check the alignment of the location monitor */
+ temp_base = (u32)lm_base;
+ if (temp_base & 0xffff) {
+ dev_err(dev, "Location monitor must be aligned to 64KB "
+ "boundary");
+ return -EINVAL;
+ }
+
+ mutex_lock(&(lm->mtx));
+
+ /* If we already have a callback attached, we can't move it! */
+ for (i = 0; i < lm->monitors; i++) {
+ if (bridge->lm_callback[i] != NULL) {
+ mutex_unlock(&(lm->mtx));
+ dev_err(dev, "Location monitor callback attached, "
+ "can't reset\n");
+ return -EBUSY;
+ }
+ }
+
+ switch (aspace) {
+ case VME_A16:
+ lm_ctl |= CA91CX42_LM_CTL_AS_A16;
+ break;
+ case VME_A24:
+ lm_ctl |= CA91CX42_LM_CTL_AS_A24;
+ break;
+ case VME_A32:
+ lm_ctl |= CA91CX42_LM_CTL_AS_A32;
+ break;
+ default:
+ mutex_unlock(&(lm->mtx));
+ dev_err(dev, "Invalid address space\n");
+ return -EINVAL;
+ break;
+ }
+
+ if (cycle & VME_SUPER)
+ lm_ctl |= CA91CX42_LM_CTL_SUPR;
+ if (cycle & VME_USER)
+ lm_ctl |= CA91CX42_LM_CTL_NPRIV;
+ if (cycle & VME_PROG)
+ lm_ctl |= CA91CX42_LM_CTL_PGM;
+ if (cycle & VME_DATA)
+ lm_ctl |= CA91CX42_LM_CTL_DATA;
+
+ iowrite32(lm_base, bridge->base + LM_BS);
+ iowrite32(lm_ctl, bridge->base + LM_CTL);
+
+ mutex_unlock(&(lm->mtx));
+
+ return 0;
+}
+
+/* Get configuration of the callback monitor and return whether it is enabled
+ * or disabled.
+ */
+int ca91cx42_lm_get(struct vme_lm_resource *lm, unsigned long long *lm_base,
+ vme_address_t *aspace, vme_cycle_t *cycle)
+{
+ u32 lm_ctl, enabled = 0;
+ struct ca91cx42_driver *bridge;
+
+ bridge = lm->parent->driver_priv;
+
+ mutex_lock(&(lm->mtx));
+
+ *lm_base = (unsigned long long)ioread32(bridge->base + LM_BS);
+ lm_ctl = ioread32(bridge->base + LM_CTL);
+
+ if (lm_ctl & CA91CX42_LM_CTL_EN)
+ enabled = 1;
+
+ if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A16)
+ *aspace = VME_A16;
+ if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A24)
+ *aspace = VME_A24;
+ if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A32)
+ *aspace = VME_A32;
+
+ *cycle = 0;
+ if (lm_ctl & CA91CX42_LM_CTL_SUPR)
+ *cycle |= VME_SUPER;
+ if (lm_ctl & CA91CX42_LM_CTL_NPRIV)
+ *cycle |= VME_USER;
+ if (lm_ctl & CA91CX42_LM_CTL_PGM)
+ *cycle |= VME_PROG;
+ if (lm_ctl & CA91CX42_LM_CTL_DATA)
+ *cycle |= VME_DATA;
+
+ mutex_unlock(&(lm->mtx));
+
+ return enabled;
+}
+
+/*
+ * Attach a callback to a specific location monitor.
+ *
+ * Callback will be passed the monitor triggered.
+ */
+int ca91cx42_lm_attach(struct vme_lm_resource *lm, int monitor,
+ void (*callback)(int))
+{
+ u32 lm_ctl, tmp;
+ struct ca91cx42_driver *bridge;
+ struct device *dev;
+
+ bridge = lm->parent->driver_priv;
+ dev = lm->parent->parent;
+
+ mutex_lock(&(lm->mtx));
+
+ /* Ensure that the location monitor is configured - need PGM or DATA */
+ lm_ctl = ioread32(bridge->base + LM_CTL);
+ if ((lm_ctl & (CA91CX42_LM_CTL_PGM | CA91CX42_LM_CTL_DATA)) == 0) {
+ mutex_unlock(&(lm->mtx));
+ dev_err(dev, "Location monitor not properly configured\n");
+ return -EINVAL;
+ }
+
+ /* Check that a callback isn't already attached */
+ if (bridge->lm_callback[monitor] != NULL) {
+ mutex_unlock(&(lm->mtx));
+ dev_err(dev, "Existing callback attached\n");
+ return -EBUSY;
+ }
+
+ /* Attach callback */
+ bridge->lm_callback[monitor] = callback;
+
+ /* Enable Location Monitor interrupt */
+ tmp = ioread32(bridge->base + LINT_EN);
+ tmp |= CA91CX42_LINT_LM[monitor];
+ iowrite32(tmp, bridge->base + LINT_EN);
+
+ /* Ensure that global Location Monitor Enable set */
+ if ((lm_ctl & CA91CX42_LM_CTL_EN) == 0) {
+ lm_ctl |= CA91CX42_LM_CTL_EN;
+ iowrite32(lm_ctl, bridge->base + LM_CTL);
+ }
+
+ mutex_unlock(&(lm->mtx));
+
+ return 0;
+}
+
+/*
+ * Detach a callback function forn a specific location monitor.
+ */
+int ca91cx42_lm_detach(struct vme_lm_resource *lm, int monitor)
+{
+ u32 tmp;
+ struct ca91cx42_driver *bridge;
+
+ bridge = lm->parent->driver_priv;
+
+ mutex_lock(&(lm->mtx));
+
+ /* Disable Location Monitor and ensure previous interrupts are clear */
+ tmp = ioread32(bridge->base + LINT_EN);
+ tmp &= ~CA91CX42_LINT_LM[monitor];
+ iowrite32(tmp, bridge->base + LINT_EN);
+
+ iowrite32(CA91CX42_LINT_LM[monitor],
+ bridge->base + LINT_STAT);
+
+ /* Detach callback */
+ bridge->lm_callback[monitor] = NULL;
+
+ /* If all location monitors disabled, disable global Location Monitor */
+ if ((tmp & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 |
+ CA91CX42_LINT_LM3)) == 0) {
+ tmp = ioread32(bridge->base + LM_CTL);
+ tmp &= ~CA91CX42_LM_CTL_EN;
+ iowrite32(tmp, bridge->base + LM_CTL);
+ }
+
+ mutex_unlock(&(lm->mtx));
+
+ return 0;
+}
+
+int ca91cx42_slot_get(struct vme_bridge *ca91cx42_bridge)
{
u32 slot = 0;
+ struct ca91cx42_driver *bridge;
+
+ bridge = ca91cx42_bridge->driver_priv;
+
+ if (!geoid) {
+ slot = ioread32(bridge->base + VCSR_BS);
+ slot = ((slot & CA91CX42_VCSR_BS_SLOT_M) >> 27);
+ } else
+ slot = geoid;
- slot = ioread32(ca91cx42_bridge->base + VCSR_BS);
- slot = ((slot & CA91CX42_VCSR_BS_SLOT_M) >> 27);
return (int)slot;
}
@@ -900,19 +1397,21 @@ static int __init ca91cx42_init(void)
* Auto-ID or Geographic address. This function ensures that the window is
* enabled at an offset consistent with the boards geopgraphic address.
*/
-static int ca91cx42_crcsr_init(struct pci_dev *pdev)
+static int ca91cx42_crcsr_init(struct vme_bridge *ca91cx42_bridge,
+ struct pci_dev *pdev)
{
unsigned int crcsr_addr;
int tmp, slot;
+ struct ca91cx42_driver *bridge;
+
+ bridge = ca91cx42_bridge->driver_priv;
+
+ slot = ca91cx42_slot_get(ca91cx42_bridge);
+
+ /* Write CSR Base Address if slot ID is supplied as a module param */
+ if (geoid)
+ iowrite32(geoid << 27, bridge->base + VCSR_BS);
-/* XXX We may need to set this somehow as the Universe II does not support
- * geographical addressing.
- */
-#if 0
- if (vme_slotnum != -1)
- iowrite32(vme_slotnum << 27, ca91cx42_bridge->base + VCSR_BS);
-#endif
- slot = ca91cx42_slot_get();
dev_info(&pdev->dev, "CR/CSR Offset: %d\n", slot);
if (slot == 0) {
dev_err(&pdev->dev, "Slot number is unset, not configuring "
@@ -921,39 +1420,44 @@ static int ca91cx42_crcsr_init(struct pci_dev *pdev)
}
/* Allocate mem for CR/CSR image */
- crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE,
- &crcsr_bus);
- if (crcsr_kernel == NULL) {
+ bridge->crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE,
+ &(bridge->crcsr_bus));
+ if (bridge->crcsr_kernel == NULL) {
dev_err(&pdev->dev, "Failed to allocate memory for CR/CSR "
"image\n");
return -ENOMEM;
}
- memset(crcsr_kernel, 0, VME_CRCSR_BUF_SIZE);
+ memset(bridge->crcsr_kernel, 0, VME_CRCSR_BUF_SIZE);
crcsr_addr = slot * (512 * 1024);
- iowrite32(crcsr_bus - crcsr_addr, ca91cx42_bridge->base + VCSR_TO);
+ iowrite32(bridge->crcsr_bus - crcsr_addr, bridge->base + VCSR_TO);
- tmp = ioread32(ca91cx42_bridge->base + VCSR_CTL);
+ tmp = ioread32(bridge->base + VCSR_CTL);
tmp |= CA91CX42_VCSR_CTL_EN;
- iowrite32(tmp, ca91cx42_bridge->base + VCSR_CTL);
+ iowrite32(tmp, bridge->base + VCSR_CTL);
return 0;
}
-static void ca91cx42_crcsr_exit(struct pci_dev *pdev)
+static void ca91cx42_crcsr_exit(struct vme_bridge *ca91cx42_bridge,
+ struct pci_dev *pdev)
{
u32 tmp;
+ struct ca91cx42_driver *bridge;
+
+ bridge = ca91cx42_bridge->driver_priv;
/* Turn off CR/CSR space */
- tmp = ioread32(ca91cx42_bridge->base + VCSR_CTL);
+ tmp = ioread32(bridge->base + VCSR_CTL);
tmp &= ~CA91CX42_VCSR_CTL_EN;
- iowrite32(tmp, ca91cx42_bridge->base + VCSR_CTL);
+ iowrite32(tmp, bridge->base + VCSR_CTL);
/* Free image */
- iowrite32(0, ca91cx42_bridge->base + VCSR_TO);
+ iowrite32(0, bridge->base + VCSR_TO);
- pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, crcsr_kernel, crcsr_bus);
+ pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, bridge->crcsr_kernel,
+ bridge->crcsr_bus);
}
static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id)
@@ -961,11 +1465,11 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id)
int retval, i;
u32 data;
struct list_head *pos = NULL;
+ struct vme_bridge *ca91cx42_bridge;
+ struct ca91cx42_driver *ca91cx42_device;
struct vme_master_resource *master_image;
struct vme_slave_resource *slave_image;
-#if 0
struct vme_dma_resource *dma_ctrlr;
-#endif
struct vme_lm_resource *lm;
/* We want to support more than one of each bridge so we need to
@@ -982,6 +1486,19 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id)
memset(ca91cx42_bridge, 0, sizeof(struct vme_bridge));
+ ca91cx42_device = kmalloc(sizeof(struct ca91cx42_driver), GFP_KERNEL);
+
+ if (ca91cx42_device == NULL) {
+ dev_err(&pdev->dev, "Failed to allocate memory for device "
+ "structure\n");
+ retval = -ENOMEM;
+ goto err_driver;
+ }
+
+ memset(ca91cx42_device, 0, sizeof(struct ca91cx42_driver));
+
+ ca91cx42_bridge->driver_priv = ca91cx42_device;
+
/* Enable the device */
retval = pci_enable_device(pdev);
if (retval) {
@@ -997,16 +1514,16 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
/* map registers in BAR 0 */
- ca91cx42_bridge->base = ioremap_nocache(pci_resource_start(pdev, 0),
+ ca91cx42_device->base = ioremap_nocache(pci_resource_start(pdev, 0),
4096);
- if (!ca91cx42_bridge->base) {
+ if (!ca91cx42_device->base) {
dev_err(&pdev->dev, "Unable to remap CRG region\n");
retval = -EIO;
goto err_remap;
}
/* Check to see if the mapping worked out */
- data = ioread32(ca91cx42_bridge->base + CA91CX42_PCI_ID) & 0x0000FFFF;
+ data = ioread32(ca91cx42_device->base + CA91CX42_PCI_ID) & 0x0000FFFF;
if (data != PCI_VENDOR_ID_TUNDRA) {
dev_err(&pdev->dev, "PCI_ID check failed\n");
retval = -EIO;
@@ -1014,11 +1531,10 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
/* Initialize wait queues & mutual exclusion flags */
- /* XXX These need to be moved to the vme_bridge structure */
- init_waitqueue_head(&dma_queue);
- init_waitqueue_head(&iack_queue);
- mutex_init(&(vme_int));
- mutex_init(&(vme_rmw));
+ init_waitqueue_head(&(ca91cx42_device->dma_queue));
+ init_waitqueue_head(&(ca91cx42_device->iack_queue));
+ mutex_init(&(ca91cx42_device->vme_int));
+ mutex_init(&(ca91cx42_device->vme_rmw));
ca91cx42_bridge->parent = &(pdev->dev);
strcpy(ca91cx42_bridge->name, driver_name);
@@ -1050,7 +1566,7 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id)
master_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT |
VME_SUPER | VME_USER | VME_PROG | VME_DATA;
master_image->width_attr = VME_D8 | VME_D16 | VME_D32 | VME_D64;
- memset(&(master_image->pci_resource), 0,
+ memset(&(master_image->bus_resource), 0,
sizeof(struct resource));
master_image->kern_base = NULL;
list_add_tail(&(master_image->list),
@@ -1084,7 +1600,7 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id)
list_add_tail(&(slave_image->list),
&(ca91cx42_bridge->slave_resources));
}
-#if 0
+
/* Add dma engines to list */
INIT_LIST_HEAD(&(ca91cx42_bridge->dma_resources));
for (i = 0; i < CA91C142_MAX_DMA; i++) {
@@ -1100,12 +1616,14 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mutex_init(&(dma_ctrlr->mtx));
dma_ctrlr->locked = 0;
dma_ctrlr->number = i;
+ dma_ctrlr->route_attr = VME_DMA_VME_TO_MEM |
+ VME_DMA_MEM_TO_VME;
INIT_LIST_HEAD(&(dma_ctrlr->pending));
INIT_LIST_HEAD(&(dma_ctrlr->running));
list_add_tail(&(dma_ctrlr->list),
&(ca91cx42_bridge->dma_resources));
}
-#endif
+
/* Add location monitor to list */
INIT_LIST_HEAD(&(ca91cx42_bridge->lm_resources));
lm = kmalloc(sizeof(struct vme_lm_resource), GFP_KERNEL);
@@ -1128,33 +1646,26 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ca91cx42_bridge->master_set = ca91cx42_master_set;
ca91cx42_bridge->master_read = ca91cx42_master_read;
ca91cx42_bridge->master_write = ca91cx42_master_write;
-#if 0
ca91cx42_bridge->master_rmw = ca91cx42_master_rmw;
ca91cx42_bridge->dma_list_add = ca91cx42_dma_list_add;
ca91cx42_bridge->dma_list_exec = ca91cx42_dma_list_exec;
ca91cx42_bridge->dma_list_empty = ca91cx42_dma_list_empty;
-#endif
ca91cx42_bridge->irq_set = ca91cx42_irq_set;
ca91cx42_bridge->irq_generate = ca91cx42_irq_generate;
-#if 0
ca91cx42_bridge->lm_set = ca91cx42_lm_set;
ca91cx42_bridge->lm_get = ca91cx42_lm_get;
ca91cx42_bridge->lm_attach = ca91cx42_lm_attach;
ca91cx42_bridge->lm_detach = ca91cx42_lm_detach;
-#endif
ca91cx42_bridge->slot_get = ca91cx42_slot_get;
- data = ioread32(ca91cx42_bridge->base + MISC_CTL);
+ data = ioread32(ca91cx42_device->base + MISC_CTL);
dev_info(&pdev->dev, "Board is%s the VME system controller\n",
(data & CA91CX42_MISC_CTL_SYSCON) ? "" : " not");
- dev_info(&pdev->dev, "Slot ID is %d\n", ca91cx42_slot_get());
+ dev_info(&pdev->dev, "Slot ID is %d\n",
+ ca91cx42_slot_get(ca91cx42_bridge));
- if (ca91cx42_crcsr_init(pdev)) {
+ if (ca91cx42_crcsr_init(ca91cx42_bridge, pdev)) {
dev_err(&pdev->dev, "CR/CSR configuration failed.\n");
- retval = -EINVAL;
-#if 0
- goto err_crcsr;
-#endif
}
/* Need to save ca91cx42_bridge pointer locally in link list for use in
@@ -1166,14 +1677,13 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_reg;
}
+ pci_set_drvdata(pdev, ca91cx42_bridge);
+
return 0;
vme_unregister_bridge(ca91cx42_bridge);
err_reg:
- ca91cx42_crcsr_exit(pdev);
-#if 0
-err_crcsr:
-#endif
+ ca91cx42_crcsr_exit(ca91cx42_bridge, pdev);
err_lm:
/* resources are stored in link list */
list_for_each(pos, &(ca91cx42_bridge->lm_resources)) {
@@ -1181,7 +1691,6 @@ err_lm:
list_del(pos);
kfree(lm);
}
-#if 0
err_dma:
/* resources are stored in link list */
list_for_each(pos, &(ca91cx42_bridge->dma_resources)) {
@@ -1189,7 +1698,6 @@ err_dma:
list_del(pos);
kfree(dma_ctrlr);
}
-#endif
err_slave:
/* resources are stored in link list */
list_for_each(pos, &(ca91cx42_bridge->slave_resources)) {
@@ -1206,15 +1714,17 @@ err_master:
kfree(master_image);
}
- ca91cx42_irq_exit(pdev);
+ ca91cx42_irq_exit(ca91cx42_device, pdev);
err_irq:
err_test:
- iounmap(ca91cx42_bridge->base);
+ iounmap(ca91cx42_device->base);
err_remap:
pci_release_regions(pdev);
err_resource:
pci_disable_device(pdev);
err_enable:
+ kfree(ca91cx42_device);
+err_driver:
kfree(ca91cx42_bridge);
err_struct:
return retval;
@@ -1228,32 +1738,37 @@ void ca91cx42_remove(struct pci_dev *pdev)
struct vme_slave_resource *slave_image;
struct vme_dma_resource *dma_ctrlr;
struct vme_lm_resource *lm;
+ struct ca91cx42_driver *bridge;
+ struct vme_bridge *ca91cx42_bridge = pci_get_drvdata(pdev);
+
+ bridge = ca91cx42_bridge->driver_priv;
+
/* Turn off Ints */
- iowrite32(0, ca91cx42_bridge->base + LINT_EN);
+ iowrite32(0, bridge->base + LINT_EN);
/* Turn off the windows */
- iowrite32(0x00800000, ca91cx42_bridge->base + LSI0_CTL);
- iowrite32(0x00800000, ca91cx42_bridge->base + LSI1_CTL);
- iowrite32(0x00800000, ca91cx42_bridge->base + LSI2_CTL);
- iowrite32(0x00800000, ca91cx42_bridge->base + LSI3_CTL);
- iowrite32(0x00800000, ca91cx42_bridge->base + LSI4_CTL);
- iowrite32(0x00800000, ca91cx42_bridge->base + LSI5_CTL);
- iowrite32(0x00800000, ca91cx42_bridge->base + LSI6_CTL);
- iowrite32(0x00800000, ca91cx42_bridge->base + LSI7_CTL);
- iowrite32(0x00F00000, ca91cx42_bridge->base + VSI0_CTL);
- iowrite32(0x00F00000, ca91cx42_bridge->base + VSI1_CTL);
- iowrite32(0x00F00000, ca91cx42_bridge->base + VSI2_CTL);
- iowrite32(0x00F00000, ca91cx42_bridge->base + VSI3_CTL);
- iowrite32(0x00F00000, ca91cx42_bridge->base + VSI4_CTL);
- iowrite32(0x00F00000, ca91cx42_bridge->base + VSI5_CTL);
- iowrite32(0x00F00000, ca91cx42_bridge->base + VSI6_CTL);
- iowrite32(0x00F00000, ca91cx42_bridge->base + VSI7_CTL);
+ iowrite32(0x00800000, bridge->base + LSI0_CTL);
+ iowrite32(0x00800000, bridge->base + LSI1_CTL);
+ iowrite32(0x00800000, bridge->base + LSI2_CTL);
+ iowrite32(0x00800000, bridge->base + LSI3_CTL);
+ iowrite32(0x00800000, bridge->base + LSI4_CTL);
+ iowrite32(0x00800000, bridge->base + LSI5_CTL);
+ iowrite32(0x00800000, bridge->base + LSI6_CTL);
+ iowrite32(0x00800000, bridge->base + LSI7_CTL);
+ iowrite32(0x00F00000, bridge->base + VSI0_CTL);
+ iowrite32(0x00F00000, bridge->base + VSI1_CTL);
+ iowrite32(0x00F00000, bridge->base + VSI2_CTL);
+ iowrite32(0x00F00000, bridge->base + VSI3_CTL);
+ iowrite32(0x00F00000, bridge->base + VSI4_CTL);
+ iowrite32(0x00F00000, bridge->base + VSI5_CTL);
+ iowrite32(0x00F00000, bridge->base + VSI6_CTL);
+ iowrite32(0x00F00000, bridge->base + VSI7_CTL);
vme_unregister_bridge(ca91cx42_bridge);
-#if 0
- ca91cx42_crcsr_exit(pdev);
-#endif
+
+ ca91cx42_crcsr_exit(ca91cx42_bridge, pdev);
+
/* resources are stored in link list */
list_for_each(pos, &(ca91cx42_bridge->lm_resources)) {
lm = list_entry(pos, struct vme_lm_resource, list);
@@ -1283,9 +1798,9 @@ void ca91cx42_remove(struct pci_dev *pdev)
kfree(master_image);
}
- ca91cx42_irq_exit(pdev);
+ ca91cx42_irq_exit(bridge, pdev);
- iounmap(ca91cx42_bridge->base);
+ iounmap(bridge->base);
pci_release_regions(pdev);
@@ -1299,588 +1814,11 @@ static void __exit ca91cx42_exit(void)
pci_unregister_driver(&ca91cx42_driver);
}
+MODULE_PARM_DESC(geoid, "Override geographical addressing");
+module_param(geoid, int, 0);
+
MODULE_DESCRIPTION("VME driver for the Tundra Universe II VME bridge");
MODULE_LICENSE("GPL");
module_init(ca91cx42_init);
module_exit(ca91cx42_exit);
-
-/*----------------------------------------------------------------------------
- * STAGING
- *--------------------------------------------------------------------------*/
-
-#if 0
-#define SWIZZLE(X) ( ((X & 0xFF000000) >> 24) | ((X & 0x00FF0000) >> 8) | ((X & 0x0000FF00) << 8) | ((X & 0x000000FF) << 24))
-
-int ca91cx42_master_rmw(vmeRmwCfg_t *vmeRmw)
-{
- int temp_ctl = 0;
- int tempBS = 0;
- int tempBD = 0;
- int tempTO = 0;
- int vmeBS = 0;
- int vmeBD = 0;
- int *rmw_pci_data_ptr = NULL;
- int *vaDataPtr = NULL;
- int i;
- vmeOutWindowCfg_t vmeOut;
- if (vmeRmw->maxAttempts < 1) {
- return -EINVAL;
- }
- if (vmeRmw->targetAddrU) {
- return -EINVAL;
- }
- /* Find the PCI address that maps to the desired VME address */
- for (i = 0; i < 8; i++) {
- temp_ctl = ioread32(ca91cx42_bridge->base +
- CA91CX42_LSI_CTL[i]);
- if ((temp_ctl & 0x80000000) == 0) {
- continue;
- }
- memset(&vmeOut, 0, sizeof(vmeOut));
- vmeOut.windowNbr = i;
- ca91cx42_get_out_bound(&vmeOut);
- if (vmeOut.addrSpace != vmeRmw->addrSpace) {
- continue;
- }
- tempBS = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_BS[i]);
- tempBD = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_BD[i]);
- tempTO = ioread32(ca91cx42_bridge->base + CA91CX42_LSI_TO[i]);
- vmeBS = tempBS + tempTO;
- vmeBD = tempBD + tempTO;
- if ((vmeRmw->targetAddr >= vmeBS) &&
- (vmeRmw->targetAddr < vmeBD)) {
- rmw_pci_data_ptr =
- (int *)(tempBS + (vmeRmw->targetAddr - vmeBS));
- vaDataPtr =
- (int *)(out_image_va[i] +
- (vmeRmw->targetAddr - vmeBS));
- break;
- }
- }
-
- /* If no window - fail. */
- if (rmw_pci_data_ptr == NULL) {
- return -EINVAL;
- }
- /* Setup the RMW registers. */
- iowrite32(0, ca91cx42_bridge->base + SCYC_CTL);
- iowrite32(SWIZZLE(vmeRmw->enableMask), ca91cx42_bridge->base + SCYC_EN);
- iowrite32(SWIZZLE(vmeRmw->compareData), ca91cx42_bridge->base +
- SCYC_CMP);
- iowrite32(SWIZZLE(vmeRmw->swapData), ca91cx42_bridge->base + SCYC_SWP);
- iowrite32((int)rmw_pci_data_ptr, ca91cx42_bridge->base + SCYC_ADDR);
- iowrite32(1, ca91cx42_bridge->base + SCYC_CTL);
-
- /* Run the RMW cycle until either success or max attempts. */
- vmeRmw->numAttempts = 1;
- while (vmeRmw->numAttempts <= vmeRmw->maxAttempts) {
-
- if ((ioread32(vaDataPtr) & vmeRmw->enableMask) ==
- (vmeRmw->swapData & vmeRmw->enableMask)) {
-
- iowrite32(0, ca91cx42_bridge->base + SCYC_CTL);
- break;
-
- }
- vmeRmw->numAttempts++;
- }
-
- /* If no success, set num Attempts to be greater than max attempts */
- if (vmeRmw->numAttempts > vmeRmw->maxAttempts) {
- vmeRmw->numAttempts = vmeRmw->maxAttempts + 1;
- }
-
- return 0;
-}
-
-int uniSetupDctlReg(vmeDmaPacket_t * vmeDma, int *dctlregreturn)
-{
- unsigned int dctlreg = 0x80;
- struct vmeAttr *vmeAttr;
-
- if (vmeDma->srcBus == VME_DMA_VME) {
- dctlreg = 0;
- vmeAttr = &vmeDma->srcVmeAttr;
- } else {
- dctlreg = 0x80000000;
- vmeAttr = &vmeDma->dstVmeAttr;
- }
-
- switch (vmeAttr->maxDataWidth) {
- case VME_D8:
- break;
- case VME_D16:
- dctlreg |= 0x00400000;
- break;
- case VME_D32:
- dctlreg |= 0x00800000;
- break;
- case VME_D64:
- dctlreg |= 0x00C00000;
- break;
- }
-
- switch (vmeAttr->addrSpace) {
- case VME_A16:
- break;
- case VME_A24:
- dctlreg |= 0x00010000;
- break;
- case VME_A32:
- dctlreg |= 0x00020000;
- break;
- case VME_USER1:
- dctlreg |= 0x00060000;
- break;
- case VME_USER2:
- dctlreg |= 0x00070000;
- break;
-
- case VME_A64: /* not supported in Universe DMA */
- case VME_CRCSR:
- case VME_USER3:
- case VME_USER4:
- return -EINVAL;
- break;
- }
- if (vmeAttr->userAccessType == VME_PROG) {
- dctlreg |= 0x00004000;
- }
- if (vmeAttr->dataAccessType == VME_SUPER) {
- dctlreg |= 0x00001000;
- }
- if (vmeAttr->xferProtocol != VME_SCT) {
- dctlreg |= 0x00000100;
- }
- *dctlregreturn = dctlreg;
- return 0;
-}
-
-unsigned int
-ca91cx42_start_dma(int channel, unsigned int dgcsreg, TDMA_Cmd_Packet *vmeLL)
-{
- unsigned int val;
-
- /* Setup registers as needed for direct or chained. */
- if (dgcsreg & 0x8000000) {
- iowrite32(0, ca91cx42_bridge->base + DTBC);
- iowrite32((unsigned int)vmeLL, ca91cx42_bridge->base + DCPP);
- } else {
-#if 0
- printk(KERN_ERR "Starting: DGCS = %08x\n", dgcsreg);
- printk(KERN_ERR "Starting: DVA = %08x\n",
- ioread32(&vmeLL->dva));
- printk(KERN_ERR "Starting: DLV = %08x\n",
- ioread32(&vmeLL->dlv));
- printk(KERN_ERR "Starting: DTBC = %08x\n",
- ioread32(&vmeLL->dtbc));
- printk(KERN_ERR "Starting: DCTL = %08x\n",
- ioread32(&vmeLL->dctl));
-#endif
- /* Write registers */
- iowrite32(ioread32(&vmeLL->dva), ca91cx42_bridge->base + DVA);
- iowrite32(ioread32(&vmeLL->dlv), ca91cx42_bridge->base + DLA);
- iowrite32(ioread32(&vmeLL->dtbc), ca91cx42_bridge->base + DTBC);
- iowrite32(ioread32(&vmeLL->dctl), ca91cx42_bridge->base + DCTL);
- iowrite32(0, ca91cx42_bridge->base + DCPP);
- }
-
- /* Start the operation */
- iowrite32(dgcsreg, ca91cx42_bridge->base + DGCS);
- val = get_tbl();
- iowrite32(dgcsreg | 0x8000000F, ca91cx42_bridge->base + DGCS);
- return val;
-}
-
-TDMA_Cmd_Packet *ca91cx42_setup_dma(vmeDmaPacket_t * vmeDma)
-{
- vmeDmaPacket_t *vmeCur;
- int maxPerPage;
- int currentLLcount;
- TDMA_Cmd_Packet *startLL;
- TDMA_Cmd_Packet *currentLL;
- TDMA_Cmd_Packet *nextLL;
- unsigned int dctlreg = 0;
-
- maxPerPage = PAGESIZE / sizeof(TDMA_Cmd_Packet) - 1;
- startLL = (TDMA_Cmd_Packet *) __get_free_pages(GFP_KERNEL, 0);
- if (startLL == 0) {
- return startLL;
- }
- /* First allocate pages for descriptors and create linked list */
- vmeCur = vmeDma;
- currentLL = startLL;
- currentLLcount = 0;
- while (vmeCur != 0) {
- if (vmeCur->pNextPacket != 0) {
- currentLL->dcpp = (unsigned int)(currentLL + 1);
- currentLLcount++;
- if (currentLLcount >= maxPerPage) {
- currentLL->dcpp =
- __get_free_pages(GFP_KERNEL, 0);
- currentLLcount = 0;
- }
- currentLL = (TDMA_Cmd_Packet *) currentLL->dcpp;
- } else {
- currentLL->dcpp = (unsigned int)0;
- }
- vmeCur = vmeCur->pNextPacket;
- }
-
- /* Next fill in information for each descriptor */
- vmeCur = vmeDma;
- currentLL = startLL;
- while (vmeCur != 0) {
- if (vmeCur->srcBus == VME_DMA_VME) {
- iowrite32(vmeCur->srcAddr, &currentLL->dva);
- iowrite32(vmeCur->dstAddr, &currentLL->dlv);
- } else {
- iowrite32(vmeCur->srcAddr, &currentLL->dlv);
- iowrite32(vmeCur->dstAddr, &currentLL->dva);
- }
- uniSetupDctlReg(vmeCur, &dctlreg);
- iowrite32(dctlreg, &currentLL->dctl);
- iowrite32(vmeCur->byteCount, &currentLL->dtbc);
-
- currentLL = (TDMA_Cmd_Packet *) currentLL->dcpp;
- vmeCur = vmeCur->pNextPacket;
- }
-
- /* Convert Links to PCI addresses. */
- currentLL = startLL;
- while (currentLL != 0) {
- nextLL = (TDMA_Cmd_Packet *) currentLL->dcpp;
- if (nextLL == 0) {
- iowrite32(1, &currentLL->dcpp);
- } else {
- iowrite32((unsigned int)virt_to_bus(nextLL),
- &currentLL->dcpp);
- }
- currentLL = nextLL;
- }
-
- /* Return pointer to descriptors list */
- return startLL;
-}
-
-int ca91cx42_free_dma(TDMA_Cmd_Packet *startLL)
-{
- TDMA_Cmd_Packet *currentLL;
- TDMA_Cmd_Packet *prevLL;
- TDMA_Cmd_Packet *nextLL;
- unsigned int dcppreg;
-
- /* Convert Links to virtual addresses. */
- currentLL = startLL;
- while (currentLL != 0) {
- dcppreg = ioread32(&currentLL->dcpp);
- dcppreg &= ~6;
- if (dcppreg & 1) {
- currentLL->dcpp = 0;
- } else {
- currentLL->dcpp = (unsigned int)bus_to_virt(dcppreg);
- }
- currentLL = (TDMA_Cmd_Packet *) currentLL->dcpp;
- }
-
- /* Free all pages associated with the descriptors. */
- currentLL = startLL;
- prevLL = currentLL;
- while (currentLL != 0) {
- nextLL = (TDMA_Cmd_Packet *) currentLL->dcpp;
- if (currentLL + 1 != nextLL) {
- free_pages((int)prevLL, 0);
- prevLL = nextLL;
- }
- currentLL = nextLL;
- }
-
- /* Return pointer to descriptors list */
- return 0;
-}
-
-int ca91cx42_do_dma(vmeDmaPacket_t *vmeDma)
-{
- unsigned int dgcsreg = 0;
- unsigned int dctlreg = 0;
- int val;
- int channel, x;
- vmeDmaPacket_t *curDma;
- TDMA_Cmd_Packet *dmaLL;
-
- /* Sanity check the VME chain. */
- channel = vmeDma->channel_number;
- if (channel > 0) {
- return -EINVAL;
- }
- curDma = vmeDma;
- while (curDma != 0) {
- if (curDma->byteCount == 0) {
- return -EINVAL;
- }
- if (curDma->byteCount >= 0x1000000) {
- return -EINVAL;
- }
- if ((curDma->srcAddr & 7) != (curDma->dstAddr & 7)) {
- return -EINVAL;
- }
- switch (curDma->srcBus) {
- case VME_DMA_PCI:
- if (curDma->dstBus != VME_DMA_VME) {
- return -EINVAL;
- }
- break;
- case VME_DMA_VME:
- if (curDma->dstBus != VME_DMA_PCI) {
- return -EINVAL;
- }
- break;
- default:
- return -EINVAL;
- break;
- }
- if (uniSetupDctlReg(curDma, &dctlreg) < 0) {
- return -EINVAL;
- }
-
- curDma = curDma->pNextPacket;
- if (curDma == vmeDma) { /* Endless Loop! */
- return -EINVAL;
- }
- }
-
- /* calculate control register */
- if (vmeDma->pNextPacket != 0) {
- dgcsreg = 0x8000000;
- } else {
- dgcsreg = 0;
- }
-
- for (x = 0; x < 8; x++) { /* vme block size */
- if ((256 << x) >= vmeDma->maxVmeBlockSize) {
- break;
- }
- }
- if (x == 8)
- x = 7;
- dgcsreg |= (x << 20);
-
- if (vmeDma->vmeBackOffTimer) {
- for (x = 1; x < 8; x++) { /* vme timer */
- if ((16 << (x - 1)) >= vmeDma->vmeBackOffTimer) {
- break;
- }
- }
- if (x == 8)
- x = 7;
- dgcsreg |= (x << 16);
- }
- /*` Setup the dma chain */
- dmaLL = ca91cx42_setup_dma(vmeDma);
-
- /* Start the DMA */
- if (dgcsreg & 0x8000000) {
- vmeDma->vmeDmaStartTick =
- ca91cx42_start_dma(channel, dgcsreg,
- (TDMA_Cmd_Packet *) virt_to_phys(dmaLL));
- } else {
- vmeDma->vmeDmaStartTick =
- ca91cx42_start_dma(channel, dgcsreg, dmaLL);
- }
-
- wait_event_interruptible(dma_queue,
- ioread32(ca91cx42_bridge->base + DGCS) & 0x800);
-
- val = ioread32(ca91cx42_bridge->base + DGCS);
- iowrite32(val | 0xF00, ca91cx42_bridge->base + DGCS);
-
- vmeDma->vmeDmaStatus = 0;
-
- if (!(val & 0x00000800)) {
- vmeDma->vmeDmaStatus = val & 0x700;
- printk(KERN_ERR "ca91c042: DMA Error in ca91cx42_DMA_irqhandler"
- " DGCS=%08X\n", val);
- val = ioread32(ca91cx42_bridge->base + DCPP);
- printk(KERN_ERR "ca91c042: DCPP=%08X\n", val);
- val = ioread32(ca91cx42_bridge->base + DCTL);
- printk(KERN_ERR "ca91c042: DCTL=%08X\n", val);
- val = ioread32(ca91cx42_bridge->base + DTBC);
- printk(KERN_ERR "ca91c042: DTBC=%08X\n", val);
- val = ioread32(ca91cx42_bridge->base + DLA);
- printk(KERN_ERR "ca91c042: DLA=%08X\n", val);
- val = ioread32(ca91cx42_bridge->base + DVA);
- printk(KERN_ERR "ca91c042: DVA=%08X\n", val);
-
- }
- /* Free the dma chain */
- ca91cx42_free_dma(dmaLL);
-
- return 0;
-}
-
-int ca91cx42_lm_set(vmeLmCfg_t *vmeLm)
-{
- int temp_ctl = 0;
-
- if (vmeLm->addrU)
- return -EINVAL;
-
- switch (vmeLm->addrSpace) {
- case VME_A64:
- case VME_USER3:
- case VME_USER4:
- return -EINVAL;
- case VME_A16:
- temp_ctl |= 0x00000;
- break;
- case VME_A24:
- temp_ctl |= 0x10000;
- break;
- case VME_A32:
- temp_ctl |= 0x20000;
- break;
- case VME_CRCSR:
- temp_ctl |= 0x50000;
- break;
- case VME_USER1:
- temp_ctl |= 0x60000;
- break;
- case VME_USER2:
- temp_ctl |= 0x70000;
- break;
- }
-
- /* Disable while we are mucking around */
- iowrite32(0x00000000, ca91cx42_bridge->base + LM_CTL);
-
- iowrite32(vmeLm->addr, ca91cx42_bridge->base + LM_BS);
-
- /* Setup CTL register. */
- if (vmeLm->userAccessType & VME_SUPER)
- temp_ctl |= 0x00200000;
- if (vmeLm->userAccessType & VME_USER)
- temp_ctl |= 0x00100000;
- if (vmeLm->dataAccessType & VME_PROG)
- temp_ctl |= 0x00800000;
- if (vmeLm->dataAccessType & VME_DATA)
- temp_ctl |= 0x00400000;
-
-
- /* Write ctl reg and enable */
- iowrite32(0x80000000 | temp_ctl, ca91cx42_bridge->base + LM_CTL);
- temp_ctl = ioread32(ca91cx42_bridge->base + LM_CTL);
-
- return 0;
-}
-
-int ca91cx42_wait_lm(vmeLmCfg_t *vmeLm)
-{
- unsigned long flags;
- unsigned int tmp;
-
- spin_lock_irqsave(&lm_lock, flags);
- spin_unlock_irqrestore(&lm_lock, flags);
- if (tmp == 0) {
- if (vmeLm->lmWait < 10)
- vmeLm->lmWait = 10;
- interruptible_sleep_on_timeout(&lm_queue, vmeLm->lmWait);
- }
- iowrite32(0x00000000, ca91cx42_bridge->base + LM_CTL);
-
- return 0;
-}
-
-
-
-int ca91cx42_set_arbiter(vmeArbiterCfg_t *vmeArb)
-{
- int temp_ctl = 0;
- int vbto = 0;
-
- temp_ctl = ioread32(ca91cx42_bridge->base + MISC_CTL);
- temp_ctl &= 0x00FFFFFF;
-
- if (vmeArb->globalTimeoutTimer == 0xFFFFFFFF) {
- vbto = 7;
- } else if (vmeArb->globalTimeoutTimer > 1024) {
- return -EINVAL;
- } else if (vmeArb->globalTimeoutTimer == 0) {
- vbto = 0;
- } else {
- vbto = 1;
- while ((16 * (1 << (vbto - 1))) < vmeArb->globalTimeoutTimer)
- vbto += 1;
- }
- temp_ctl |= (vbto << 28);
-
- if (vmeArb->arbiterMode == VME_PRIORITY_MODE)
- temp_ctl |= 1 << 26;
-
- if (vmeArb->arbiterTimeoutFlag)
- temp_ctl |= 2 << 24;
-
- iowrite32(temp_ctl, ca91cx42_bridge->base + MISC_CTL);
- return 0;
-}
-
-int ca91cx42_get_arbiter(vmeArbiterCfg_t *vmeArb)
-{
- int temp_ctl = 0;
- int vbto = 0;
-
- temp_ctl = ioread32(ca91cx42_bridge->base + MISC_CTL);
-
- vbto = (temp_ctl >> 28) & 0xF;
- if (vbto != 0)
- vmeArb->globalTimeoutTimer = (16 * (1 << (vbto - 1)));
-
- if (temp_ctl & (1 << 26))
- vmeArb->arbiterMode = VME_PRIORITY_MODE;
- else
- vmeArb->arbiterMode = VME_R_ROBIN_MODE;
-
- if (temp_ctl & (3 << 24))
- vmeArb->arbiterTimeoutFlag = 1;
-
- return 0;
-}
-
-int ca91cx42_set_requestor(vmeRequesterCfg_t *vmeReq)
-{
- int temp_ctl = 0;
-
- temp_ctl = ioread32(ca91cx42_bridge->base + MAST_CTL);
- temp_ctl &= 0xFF0FFFFF;
-
- if (vmeReq->releaseMode == 1)
- temp_ctl |= (1 << 20);
-
- if (vmeReq->fairMode == 1)
- temp_ctl |= (1 << 21);
-
- temp_ctl |= (vmeReq->requestLevel << 22);
-
- iowrite32(temp_ctl, ca91cx42_bridge->base + MAST_CTL);
- return 0;
-}
-
-int ca91cx42_get_requestor(vmeRequesterCfg_t *vmeReq)
-{
- int temp_ctl = 0;
-
- temp_ctl = ioread32(ca91cx42_bridge->base + MAST_CTL);
-
- if (temp_ctl & (1 << 20))
- vmeReq->releaseMode = 1;
-
- if (temp_ctl & (1 << 21))
- vmeReq->fairMode = 1;
-
- vmeReq->requestLevel = (temp_ctl & 0xC00000) >> 22;
-
- return 0;
-}
-
-
-#endif
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.h b/drivers/staging/vme/bridges/vme_ca91cx42.h
index 95a42c240a2..e72c65b193e 100644
--- a/drivers/staging/vme/bridges/vme_ca91cx42.h
+++ b/drivers/staging/vme/bridges/vme_ca91cx42.h
@@ -7,8 +7,8 @@
* Updated by Ajit Prem
* Copyright 2004 Motorola Inc.
*
- * Further updated by Martyn Welch <martyn.welch@gefanuc.com>
- * Copyright 2009 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ * Further updated by Martyn Welch <martyn.welch@ge.com>
+ * Copyright 2009 GE Intelligent Platforms Embedded Systems, Inc.
*
* Derived from ca91c042.h by Michael Wyrick
*
@@ -37,11 +37,27 @@
#define CA91C142_MAX_DMA 1 /* Max DMA Controllers */
#define CA91C142_MAX_MAILBOX 4 /* Max Mail Box registers */
+/* Structure used to hold driver specific information */
+struct ca91cx42_driver {
+ void *base; /* Base Address of device registers */
+ wait_queue_head_t dma_queue;
+ wait_queue_head_t iack_queue;
+ wait_queue_head_t mbox_queue;
+ void (*lm_callback[4])(int); /* Called in interrupt handler */
+ void *crcsr_kernel;
+ dma_addr_t crcsr_bus;
+ struct mutex vme_rmw; /* Only one RMW cycle at a time */
+ struct mutex vme_int; /*
+ * Only one VME interrupt can be
+ * generated at a time, provide locking
+ */
+};
+
/* See Page 2-77 in the Universe User Manual */
struct ca91cx42_dma_descriptor {
unsigned int dctl; /* DMA Control */
unsigned int dtbc; /* Transfer Byte Count */
- unsigned int dlv; /* PCI Address */
+ unsigned int dla; /* PCI Address */
unsigned int res1; /* Reserved */
unsigned int dva; /* Vme Address */
unsigned int res2; /* Reserved */
@@ -237,32 +253,6 @@ static const int CA91CX42_VSI_TO[] = { VSI0_TO, VSI1_TO, VSI2_TO, VSI3_TO,
#define VCSR_SET 0x0FF8
#define VCSR_BS 0x0FFC
-// DMA General Control/Status Register DGCS (0x220)
-// 32-24 || GO | STOPR | HALTR | 0 || CHAIN | 0 | 0 | 0 ||
-// 23-16 || VON || VOFF ||
-// 15-08 || ACT | STOP | HALT | 0 || DONE | LERR | VERR | P_ERR ||
-// 07-00 || 0 | INT_S | INT_H | 0 || I_DNE | I_LER | I_VER | I_PER ||
-
-// VON - Length Per DMA VMEBus Transfer
-// 0000 = None
-// 0001 = 256 Bytes
-// 0010 = 512
-// 0011 = 1024
-// 0100 = 2048
-// 0101 = 4096
-// 0110 = 8192
-// 0111 = 16384
-
-// VOFF - wait between DMA tenures
-// 0000 = 0 us
-// 0001 = 16
-// 0010 = 32
-// 0011 = 64
-// 0100 = 128
-// 0101 = 256
-// 0110 = 512
-// 0111 = 1024
-
/*
* PCI Class Register
* offset 008
@@ -326,6 +316,16 @@ static const int CA91CX42_VSI_TO[] = { VSI0_TO, VSI1_TO, VSI2_TO, VSI3_TO,
#define CA91CX42_LSI_CTL_VCT_MBLT (1<<8)
#define CA91CX42_LSI_CTL_LAS (1<<0)
+/*
+ * SCYC_CTL Register
+ * offset 178
+ */
+#define CA91CX42_SCYC_CTL_LAS_PCIMEM 0
+#define CA91CX42_SCYC_CTL_LAS_PCIIO (1<<2)
+
+#define CA91CX42_SCYC_CTL_CYC_M (3<<0)
+#define CA91CX42_SCYC_CTL_CYC_RMW (1<<0)
+#define CA91CX42_SCYC_CTL_CYC_ADOH (1<<1)
/*
* LMISC Register
@@ -355,6 +355,71 @@ static const int CA91CX42_VSI_TO[] = { VSI0_TO, VSI1_TO, VSI2_TO, VSI3_TO,
#define CA91CX42_BM_SLSI_RESERVED 0x3F0F0000
/*
+ * DCTL Register
+ * offset 200
+ */
+#define CA91CX42_DCTL_L2V (1<<31)
+#define CA91CX42_DCTL_VDW_M (3<<22)
+#define CA91CX42_DCTL_VDW_M (3<<22)
+#define CA91CX42_DCTL_VDW_D8 0
+#define CA91CX42_DCTL_VDW_D16 (1<<22)
+#define CA91CX42_DCTL_VDW_D32 (1<<23)
+#define CA91CX42_DCTL_VDW_D64 (3<<22)
+
+#define CA91CX42_DCTL_VAS_M (7<<16)
+#define CA91CX42_DCTL_VAS_A16 0
+#define CA91CX42_DCTL_VAS_A24 (1<<16)
+#define CA91CX42_DCTL_VAS_A32 (1<<17)
+#define CA91CX42_DCTL_VAS_USER1 (3<<17)
+#define CA91CX42_DCTL_VAS_USER2 (7<<16)
+
+#define CA91CX42_DCTL_PGM_M (1<<14)
+#define CA91CX42_DCTL_PGM_DATA 0
+#define CA91CX42_DCTL_PGM_PGM (1<<14)
+
+#define CA91CX42_DCTL_SUPER_M (1<<12)
+#define CA91CX42_DCTL_SUPER_NPRIV 0
+#define CA91CX42_DCTL_SUPER_SUPR (1<<12)
+
+#define CA91CX42_DCTL_VCT_M (1<<8)
+#define CA91CX42_DCTL_VCT_BLT (1<<8)
+#define CA91CX42_DCTL_LD64EN (1<<7)
+
+/*
+ * DCPP Register
+ * offset 218
+ */
+#define CA91CX42_DCPP_M 0xf
+#define CA91CX42_DCPP_NULL (1<<0)
+
+/*
+ * DMA General Control/Status Register (DGCS)
+ * offset 220
+ */
+#define CA91CX42_DGCS_GO (1<<31)
+#define CA91CX42_DGCS_STOP_REQ (1<<30)
+#define CA91CX42_DGCS_HALT_REQ (1<<29)
+#define CA91CX42_DGCS_CHAIN (1<<27)
+
+#define CA91CX42_DGCS_VON_M (7<<20)
+
+#define CA91CX42_DGCS_VOFF_M (0xf<<16)
+
+#define CA91CX42_DGCS_ACT (1<<15)
+#define CA91CX42_DGCS_STOP (1<<14)
+#define CA91CX42_DGCS_HALT (1<<13)
+#define CA91CX42_DGCS_DONE (1<<11)
+#define CA91CX42_DGCS_LERR (1<<10)
+#define CA91CX42_DGCS_VERR (1<<9)
+#define CA91CX42_DGCS_PERR (1<<8)
+#define CA91CX42_DGCS_INT_STOP (1<<6)
+#define CA91CX42_DGCS_INT_HALT (1<<5)
+#define CA91CX42_DGCS_INT_DONE (1<<3)
+#define CA91CX42_DGCS_INT_LERR (1<<2)
+#define CA91CX42_DGCS_INT_VERR (1<<1)
+#define CA91CX42_DGCS_INT_PERR (1<<0)
+
+/*
* PCI Interrupt Enable Register
* offset 300
*/
@@ -475,6 +540,19 @@ static const int CA91CX42_LINT_LM[] = { CA91CX42_LINT_LM0, CA91CX42_LINT_LM1,
#define CA91CX42_VSI_CTL_LAS_PCI_IO (1<<0)
#define CA91CX42_VSI_CTL_LAS_PCI_CONF (1<<1)
+/* LM_CTL Register
+ * offset F64
+ */
+#define CA91CX42_LM_CTL_EN (1<<31)
+#define CA91CX42_LM_CTL_PGM (1<<23)
+#define CA91CX42_LM_CTL_DATA (1<<22)
+#define CA91CX42_LM_CTL_SUPR (1<<21)
+#define CA91CX42_LM_CTL_NPRIV (1<<20)
+#define CA91CX42_LM_CTL_AS_M (5<<16)
+#define CA91CX42_LM_CTL_AS_A16 0
+#define CA91CX42_LM_CTL_AS_A24 (1<<16)
+#define CA91CX42_LM_CTL_AS_A32 (1<<17)
+
/*
* VRAI_CTL Register
* offset F70
diff --git a/drivers/staging/vme/bridges/vme_tsi148.c b/drivers/staging/vme/bridges/vme_tsi148.c
index 89a7dccb934..faf652edb70 100644
--- a/drivers/staging/vme/bridges/vme_tsi148.c
+++ b/drivers/staging/vme/bridges/vme_tsi148.c
@@ -1,8 +1,8 @@
/*
* Support for the Tundra TSI148 VME-PCI Bridge Chip
*
- * Author: Martyn Welch <martyn.welch@gefanuc.com>
- * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ * Author: Martyn Welch <martyn.welch@ge.com>
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
*
* Based on work by Tom Armistead and Ajit Prem
* Copyright 2004 Motorola Inc.
@@ -59,28 +59,14 @@ int tsi148_dma_list_add (struct vme_dma_list *, struct vme_dma_attr *,
int tsi148_dma_list_exec(struct vme_dma_list *);
int tsi148_dma_list_empty(struct vme_dma_list *);
int tsi148_generate_irq(int, int);
-int tsi148_slot_get(void);
-
-/* Modue parameter */
-int err_chk = 0;
-
-/* XXX These should all be in a per device structure */
-struct vme_bridge *tsi148_bridge;
-wait_queue_head_t dma_queue[2];
-wait_queue_head_t iack_queue;
-void (*lm_callback[4])(int); /* Called in interrupt handler, be careful! */
-void *crcsr_kernel;
-dma_addr_t crcsr_bus;
-struct vme_master_resource *flush_image;
-struct mutex vme_rmw; /* Only one RMW cycle at a time */
-struct mutex vme_int; /*
- * Only one VME interrupt can be
- * generated at a time, provide locking
- */
+
+/* Module parameter */
+static int err_chk;
+static int geoid;
static char driver_name[] = "vme_tsi148";
-static struct pci_device_id tsi148_ids[] = {
+static const struct pci_device_id tsi148_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_TUNDRA, PCI_DEVICE_ID_TUNDRA_TSI148) },
{ },
};
@@ -109,16 +95,17 @@ static void reg_split(unsigned long long variable, unsigned int *high,
/*
* Wakes up DMA queue.
*/
-static u32 tsi148_DMA_irqhandler(int channel_mask)
+static u32 tsi148_DMA_irqhandler(struct tsi148_driver *bridge,
+ int channel_mask)
{
u32 serviced = 0;
if (channel_mask & TSI148_LCSR_INTS_DMA0S) {
- wake_up(&dma_queue[0]);
+ wake_up(&(bridge->dma_queue[0]));
serviced |= TSI148_LCSR_INTC_DMA0C;
}
if (channel_mask & TSI148_LCSR_INTS_DMA1S) {
- wake_up(&dma_queue[1]);
+ wake_up(&(bridge->dma_queue[1]));
serviced |= TSI148_LCSR_INTC_DMA1C;
}
@@ -128,7 +115,7 @@ static u32 tsi148_DMA_irqhandler(int channel_mask)
/*
* Wake up location monitor queue
*/
-static u32 tsi148_LM_irqhandler(u32 stat)
+static u32 tsi148_LM_irqhandler(struct tsi148_driver *bridge, u32 stat)
{
int i;
u32 serviced = 0;
@@ -136,7 +123,7 @@ static u32 tsi148_LM_irqhandler(u32 stat)
for (i = 0; i < 4; i++) {
if(stat & TSI148_LCSR_INTS_LMS[i]) {
/* We only enable interrupts if the callback is set */
- lm_callback[i](i);
+ bridge->lm_callback[i](i);
serviced |= TSI148_LCSR_INTC_LMC[i];
}
}
@@ -149,7 +136,7 @@ static u32 tsi148_LM_irqhandler(u32 stat)
*
* XXX This functionality is not exposed up though API.
*/
-static u32 tsi148_MB_irqhandler(u32 stat)
+static u32 tsi148_MB_irqhandler(struct tsi148_driver *bridge, u32 stat)
{
int i;
u32 val;
@@ -157,8 +144,7 @@ static u32 tsi148_MB_irqhandler(u32 stat)
for (i = 0; i < 4; i++) {
if(stat & TSI148_LCSR_INTS_MBS[i]) {
- val = ioread32be(tsi148_bridge->base +
- TSI148_GCSR_MBOX[i]);
+ val = ioread32be(bridge->base + TSI148_GCSR_MBOX[i]);
printk("VME Mailbox %d received: 0x%x\n", i, val);
serviced |= TSI148_LCSR_INTC_MBC[i];
}
@@ -170,22 +156,21 @@ static u32 tsi148_MB_irqhandler(u32 stat)
/*
* Display error & status message when PERR (PCI) exception interrupt occurs.
*/
-static u32 tsi148_PERR_irqhandler(void)
+static u32 tsi148_PERR_irqhandler(struct tsi148_driver *bridge)
{
printk(KERN_ERR
"PCI Exception at address: 0x%08x:%08x, attributes: %08x\n",
- ioread32be(tsi148_bridge->base + TSI148_LCSR_EDPAU),
- ioread32be(tsi148_bridge->base + TSI148_LCSR_EDPAL),
- ioread32be(tsi148_bridge->base + TSI148_LCSR_EDPAT)
+ ioread32be(bridge->base + TSI148_LCSR_EDPAU),
+ ioread32be(bridge->base + TSI148_LCSR_EDPAL),
+ ioread32be(bridge->base + TSI148_LCSR_EDPAT)
);
printk(KERN_ERR
"PCI-X attribute reg: %08x, PCI-X split completion reg: %08x\n",
- ioread32be(tsi148_bridge->base + TSI148_LCSR_EDPXA),
- ioread32be(tsi148_bridge->base + TSI148_LCSR_EDPXS)
+ ioread32be(bridge->base + TSI148_LCSR_EDPXA),
+ ioread32be(bridge->base + TSI148_LCSR_EDPXS)
);
- iowrite32be(TSI148_LCSR_EDPAT_EDPCL,
- tsi148_bridge->base + TSI148_LCSR_EDPAT);
+ iowrite32be(TSI148_LCSR_EDPAT_EDPCL, bridge->base + TSI148_LCSR_EDPAT);
return TSI148_LCSR_INTC_PERRC;
}
@@ -193,16 +178,19 @@ static u32 tsi148_PERR_irqhandler(void)
/*
* Save address and status when VME error interrupt occurs.
*/
-static u32 tsi148_VERR_irqhandler(void)
+static u32 tsi148_VERR_irqhandler(struct vme_bridge *tsi148_bridge)
{
unsigned int error_addr_high, error_addr_low;
unsigned long long error_addr;
u32 error_attrib;
struct vme_bus_error *error;
+ struct tsi148_driver *bridge;
+
+ bridge = tsi148_bridge->driver_priv;
- error_addr_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_VEAU);
- error_addr_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_VEAL);
- error_attrib = ioread32be(tsi148_bridge->base + TSI148_LCSR_VEAT);
+ error_addr_high = ioread32be(bridge->base + TSI148_LCSR_VEAU);
+ error_addr_low = ioread32be(bridge->base + TSI148_LCSR_VEAL);
+ error_attrib = ioread32be(bridge->base + TSI148_LCSR_VEAT);
reg_join(error_addr_high, error_addr_low, &error_addr);
@@ -226,8 +214,7 @@ static u32 tsi148_VERR_irqhandler(void)
}
/* Clear Status */
- iowrite32be(TSI148_LCSR_VEAT_VESCL,
- tsi148_bridge->base + TSI148_LCSR_VEAT);
+ iowrite32be(TSI148_LCSR_VEAT_VESCL, bridge->base + TSI148_LCSR_VEAT);
return TSI148_LCSR_INTC_VERRC;
}
@@ -235,9 +222,9 @@ static u32 tsi148_VERR_irqhandler(void)
/*
* Wake up IACK queue.
*/
-static u32 tsi148_IACK_irqhandler(void)
+static u32 tsi148_IACK_irqhandler(struct tsi148_driver *bridge)
{
- wake_up(&iack_queue);
+ wake_up(&(bridge->iack_queue));
return TSI148_LCSR_INTC_IACKC;
}
@@ -245,9 +232,13 @@ static u32 tsi148_IACK_irqhandler(void)
/*
* Calling VME bus interrupt callback if provided.
*/
-static u32 tsi148_VIRQ_irqhandler(u32 stat)
+static u32 tsi148_VIRQ_irqhandler(struct vme_bridge *tsi148_bridge,
+ u32 stat)
{
int vec, i, serviced = 0;
+ struct tsi148_driver *bridge;
+
+ bridge = tsi148_bridge->driver_priv;
for (i = 7; i > 0; i--) {
if (stat & (1 << i)) {
@@ -257,8 +248,7 @@ static u32 tsi148_VIRQ_irqhandler(u32 stat)
* 8-bit IACK cycles on the bus, read from offset
* 3.
*/
- vec = ioread8(tsi148_bridge->base +
- TSI148_LCSR_VIACK[i] + 3);
+ vec = ioread8(bridge->base + TSI148_LCSR_VIACK[i] + 3);
vme_irq_handler(tsi148_bridge, i, vec);
@@ -273,13 +263,19 @@ static u32 tsi148_VIRQ_irqhandler(u32 stat)
* Top level interrupt handler. Clears appropriate interrupt status bits and
* then calls appropriate sub handler(s).
*/
-static irqreturn_t tsi148_irqhandler(int irq, void *dev_id)
+static irqreturn_t tsi148_irqhandler(int irq, void *ptr)
{
u32 stat, enable, serviced = 0;
+ struct vme_bridge *tsi148_bridge;
+ struct tsi148_driver *bridge;
+
+ tsi148_bridge = ptr;
+
+ bridge = tsi148_bridge->driver_priv;
/* Determine which interrupts are unmasked and set */
- enable = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEO);
- stat = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTS);
+ enable = ioread32be(bridge->base + TSI148_LCSR_INTEO);
+ stat = ioread32be(bridge->base + TSI148_LCSR_INTS);
/* Only look at unmasked interrupts */
stat &= enable;
@@ -291,61 +287,63 @@ static irqreturn_t tsi148_irqhandler(int irq, void *dev_id)
/* Call subhandlers as appropriate */
/* DMA irqs */
if (stat & (TSI148_LCSR_INTS_DMA1S | TSI148_LCSR_INTS_DMA0S))
- serviced |= tsi148_DMA_irqhandler(stat);
+ serviced |= tsi148_DMA_irqhandler(bridge, stat);
/* Location monitor irqs */
if (stat & (TSI148_LCSR_INTS_LM3S | TSI148_LCSR_INTS_LM2S |
TSI148_LCSR_INTS_LM1S | TSI148_LCSR_INTS_LM0S))
- serviced |= tsi148_LM_irqhandler(stat);
+ serviced |= tsi148_LM_irqhandler(bridge, stat);
/* Mail box irqs */
if (stat & (TSI148_LCSR_INTS_MB3S | TSI148_LCSR_INTS_MB2S |
TSI148_LCSR_INTS_MB1S | TSI148_LCSR_INTS_MB0S))
- serviced |= tsi148_MB_irqhandler(stat);
+ serviced |= tsi148_MB_irqhandler(bridge, stat);
/* PCI bus error */
if (stat & TSI148_LCSR_INTS_PERRS)
- serviced |= tsi148_PERR_irqhandler();
+ serviced |= tsi148_PERR_irqhandler(bridge);
/* VME bus error */
if (stat & TSI148_LCSR_INTS_VERRS)
- serviced |= tsi148_VERR_irqhandler();
+ serviced |= tsi148_VERR_irqhandler(tsi148_bridge);
/* IACK irq */
if (stat & TSI148_LCSR_INTS_IACKS)
- serviced |= tsi148_IACK_irqhandler();
+ serviced |= tsi148_IACK_irqhandler(bridge);
/* VME bus irqs */
if (stat & (TSI148_LCSR_INTS_IRQ7S | TSI148_LCSR_INTS_IRQ6S |
TSI148_LCSR_INTS_IRQ5S | TSI148_LCSR_INTS_IRQ4S |
TSI148_LCSR_INTS_IRQ3S | TSI148_LCSR_INTS_IRQ2S |
TSI148_LCSR_INTS_IRQ1S))
- serviced |= tsi148_VIRQ_irqhandler(stat);
+ serviced |= tsi148_VIRQ_irqhandler(tsi148_bridge, stat);
/* Clear serviced interrupts */
- iowrite32be(serviced, tsi148_bridge->base + TSI148_LCSR_INTC);
+ iowrite32be(serviced, bridge->base + TSI148_LCSR_INTC);
return IRQ_HANDLED;
}
-static int tsi148_irq_init(struct vme_bridge *bridge)
+static int tsi148_irq_init(struct vme_bridge *tsi148_bridge)
{
int result;
unsigned int tmp;
struct pci_dev *pdev;
+ struct tsi148_driver *bridge;
+
+ pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev);
- /* Need pdev */
- pdev = container_of(bridge->parent, struct pci_dev, dev);
+ bridge = tsi148_bridge->driver_priv;
/* Initialise list for VME bus errors */
- INIT_LIST_HEAD(&(bridge->vme_errors));
+ INIT_LIST_HEAD(&(tsi148_bridge->vme_errors));
- mutex_init(&(bridge->irq_mtx));
+ mutex_init(&(tsi148_bridge->irq_mtx));
result = request_irq(pdev->irq,
tsi148_irqhandler,
IRQF_SHARED,
- driver_name, pdev);
+ driver_name, tsi148_bridge);
if (result) {
dev_err(&pdev->dev, "Can't get assigned pci irq vector %02X\n",
pdev->irq);
@@ -359,7 +357,7 @@ static int tsi148_irq_init(struct vme_bridge *bridge)
TSI148_LCSR_INTEO_PERREO | TSI148_LCSR_INTEO_VERREO |
TSI148_LCSR_INTEO_IACKEO;
- /* XXX This leaves the following interrupts masked.
+ /* This leaves the following interrupts masked.
* TSI148_LCSR_INTEO_VIEEO
* TSI148_LCSR_INTEO_SYSFLEO
* TSI148_LCSR_INTEO_ACFLEO
@@ -392,14 +390,14 @@ static int tsi148_irq_init(struct vme_bridge *bridge)
return 0;
}
-static void tsi148_irq_exit(struct pci_dev *pdev)
+static void tsi148_irq_exit(struct tsi148_driver *bridge, struct pci_dev *pdev)
{
/* Turn off interrupts */
- iowrite32be(0x0, tsi148_bridge->base + TSI148_LCSR_INTEO);
- iowrite32be(0x0, tsi148_bridge->base + TSI148_LCSR_INTEN);
+ iowrite32be(0x0, bridge->base + TSI148_LCSR_INTEO);
+ iowrite32be(0x0, bridge->base + TSI148_LCSR_INTEN);
/* Clear all interrupts */
- iowrite32be(0xFFFFFFFF, tsi148_bridge->base + TSI148_LCSR_INTC);
+ iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_INTC);
/* Detach interrupt handler */
free_irq(pdev->irq, pdev);
@@ -408,11 +406,11 @@ static void tsi148_irq_exit(struct pci_dev *pdev)
/*
* Check to see if an IACk has been received, return true (1) or false (0).
*/
-int tsi148_iack_received(void)
+int tsi148_iack_received(struct tsi148_driver *bridge)
{
u32 tmp;
- tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_VICR);
+ tmp = ioread32be(bridge->base + TSI148_LCSR_VICR);
if (tmp & TSI148_LCSR_VICR_IRQS)
return 0;
@@ -423,20 +421,24 @@ int tsi148_iack_received(void)
/*
* Configure VME interrupt
*/
-void tsi148_irq_set(int level, int state, int sync)
+void tsi148_irq_set(struct vme_bridge *tsi148_bridge, int level,
+ int state, int sync)
{
struct pci_dev *pdev;
u32 tmp;
+ struct tsi148_driver *bridge;
+
+ bridge = tsi148_bridge->driver_priv;
/* We need to do the ordering differently for enabling and disabling */
if (state == 0) {
- tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEN);
+ tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN);
tmp &= ~TSI148_LCSR_INTEN_IRQEN[level - 1];
- iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEN);
+ iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN);
- tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEO);
+ tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO);
tmp &= ~TSI148_LCSR_INTEO_IRQEO[level - 1];
- iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEO);
+ iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO);
if (sync != 0) {
pdev = container_of(tsi148_bridge->parent,
@@ -445,13 +447,13 @@ void tsi148_irq_set(int level, int state, int sync)
synchronize_irq(pdev->irq);
}
} else {
- tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEO);
+ tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO);
tmp |= TSI148_LCSR_INTEO_IRQEO[level - 1];
- iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEO);
+ iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO);
- tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEN);
+ tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN);
tmp |= TSI148_LCSR_INTEN_IRQEN[level - 1];
- iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEN);
+ iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN);
}
}
@@ -459,28 +461,32 @@ void tsi148_irq_set(int level, int state, int sync)
* Generate a VME bus interrupt at the requested level & vector. Wait for
* interrupt to be acked.
*/
-int tsi148_irq_generate(int level, int statid)
+int tsi148_irq_generate(struct vme_bridge *tsi148_bridge, int level, int statid)
{
u32 tmp;
+ struct tsi148_driver *bridge;
+
+ bridge = tsi148_bridge->driver_priv;
- mutex_lock(&(vme_int));
+ mutex_lock(&(bridge->vme_int));
/* Read VICR register */
- tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_VICR);
+ tmp = ioread32be(bridge->base + TSI148_LCSR_VICR);
/* Set Status/ID */
tmp = (tmp & ~TSI148_LCSR_VICR_STID_M) |
(statid & TSI148_LCSR_VICR_STID_M);
- iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_VICR);
+ iowrite32be(tmp, bridge->base + TSI148_LCSR_VICR);
/* Assert VMEbus IRQ */
tmp = tmp | TSI148_LCSR_VICR_IRQL[level];
- iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_VICR);
+ iowrite32be(tmp, bridge->base + TSI148_LCSR_VICR);
/* XXX Consider implementing a timeout? */
- wait_event_interruptible(iack_queue, tsi148_iack_received());
+ wait_event_interruptible(bridge->iack_queue,
+ tsi148_iack_received(bridge));
- mutex_unlock(&(vme_int));
+ mutex_unlock(&(bridge->vme_int));
return 0;
}
@@ -488,8 +494,8 @@ int tsi148_irq_generate(int level, int statid)
/*
* Find the first error in this address range
*/
-static struct vme_bus_error *tsi148_find_error(vme_address_t aspace,
- unsigned long long address, size_t count)
+static struct vme_bus_error *tsi148_find_error(struct vme_bridge *tsi148_bridge,
+ vme_address_t aspace, unsigned long long address, size_t count)
{
struct list_head *err_pos;
struct vme_bus_error *vme_err, *valid = NULL;
@@ -520,8 +526,8 @@ static struct vme_bus_error *tsi148_find_error(vme_address_t aspace,
/*
* Clear errors in the provided address range.
*/
-static void tsi148_clear_errors(vme_address_t aspace,
- unsigned long long address, size_t count)
+static void tsi148_clear_errors(struct vme_bridge *tsi148_bridge,
+ vme_address_t aspace, unsigned long long address, size_t count)
{
struct list_head *err_pos, *temp;
struct vme_bus_error *vme_err;
@@ -561,16 +567,9 @@ int tsi148_slave_set(struct vme_slave_resource *image, int enabled,
unsigned int vme_bound_low, vme_bound_high;
unsigned int pci_offset_low, pci_offset_high;
unsigned long long vme_bound, pci_offset;
+ struct tsi148_driver *bridge;
-#if 0
- printk("Set slave image %d to:\n", image->number);
- printk("\tEnabled: %s\n", (enabled == 1)? "yes" : "no");
- printk("\tVME Base:0x%llx\n", vme_base);
- printk("\tWindow Size:0x%llx\n", size);
- printk("\tPCI Base:0x%lx\n", (unsigned long)pci_base);
- printk("\tAddress Space:0x%x\n", aspace);
- printk("\tTransfer Cycle Properties:0x%x\n", cycle);
-#endif
+ bridge = image->parent->driver_priv;
i = image->number;
@@ -627,49 +626,27 @@ int tsi148_slave_set(struct vme_slave_resource *image, int enabled,
return -EINVAL;
}
-#if 0
- printk("\tVME Bound:0x%llx\n", vme_bound);
- printk("\tPCI Offset:0x%llx\n", pci_offset);
-#endif
-
/* Disable while we are mucking around */
- temp_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+ temp_ctl = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
TSI148_LCSR_OFFSET_ITAT);
temp_ctl &= ~TSI148_LCSR_ITAT_EN;
- iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+ iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] +
TSI148_LCSR_OFFSET_ITAT);
/* Setup mapping */
- iowrite32be(vme_base_high, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+ iowrite32be(vme_base_high, bridge->base + TSI148_LCSR_IT[i] +
TSI148_LCSR_OFFSET_ITSAU);
- iowrite32be(vme_base_low, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+ iowrite32be(vme_base_low, bridge->base + TSI148_LCSR_IT[i] +
TSI148_LCSR_OFFSET_ITSAL);
- iowrite32be(vme_bound_high, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+ iowrite32be(vme_bound_high, bridge->base + TSI148_LCSR_IT[i] +
TSI148_LCSR_OFFSET_ITEAU);
- iowrite32be(vme_bound_low, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+ iowrite32be(vme_bound_low, bridge->base + TSI148_LCSR_IT[i] +
TSI148_LCSR_OFFSET_ITEAL);
- iowrite32be(pci_offset_high, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+ iowrite32be(pci_offset_high, bridge->base + TSI148_LCSR_IT[i] +
TSI148_LCSR_OFFSET_ITOFU);
- iowrite32be(pci_offset_low, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+ iowrite32be(pci_offset_low, bridge->base + TSI148_LCSR_IT[i] +
TSI148_LCSR_OFFSET_ITOFL);
-/* XXX Prefetch stuff currently unsupported */
-#if 0
-
- for (x = 0; x < 4; x++) {
- if ((64 << x) >= vmeIn->prefetchSize) {
- break;
- }
- }
- if (x == 4)
- x--;
- temp_ctl |= (x << 16);
-
- if (vmeIn->prefetchThreshold)
- if (vmeIn->prefetchThreshold)
- temp_ctl |= 0x40000;
-#endif
-
/* Setup 2eSST speeds */
temp_ctl &= ~TSI148_LCSR_ITAT_2eSSTM_M;
switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) {
@@ -712,13 +689,13 @@ int tsi148_slave_set(struct vme_slave_resource *image, int enabled,
temp_ctl |= TSI148_LCSR_ITAT_DATA;
/* Write ctl reg without enable */
- iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+ iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] +
TSI148_LCSR_OFFSET_ITAT);
if (enabled)
temp_ctl |= TSI148_LCSR_ITAT_EN;
- iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+ iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_IT[i] +
TSI148_LCSR_OFFSET_ITAT);
return 0;
@@ -726,8 +703,6 @@ int tsi148_slave_set(struct vme_slave_resource *image, int enabled,
/*
* Get slave window configuration.
- *
- * XXX Prefetch currently unsupported.
*/
int tsi148_slave_get(struct vme_slave_resource *image, int *enabled,
unsigned long long *vme_base, unsigned long long *size,
@@ -738,25 +713,27 @@ int tsi148_slave_get(struct vme_slave_resource *image, int *enabled,
unsigned int vme_bound_low, vme_bound_high;
unsigned int pci_offset_low, pci_offset_high;
unsigned long long vme_bound, pci_offset;
+ struct tsi148_driver *bridge;
+ bridge = image->parent->driver_priv;
i = image->number;
/* Read registers */
- ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+ ctl = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
TSI148_LCSR_OFFSET_ITAT);
- vme_base_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+ vme_base_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
TSI148_LCSR_OFFSET_ITSAU);
- vme_base_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+ vme_base_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
TSI148_LCSR_OFFSET_ITSAL);
- vme_bound_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+ vme_bound_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
TSI148_LCSR_OFFSET_ITEAU);
- vme_bound_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+ vme_bound_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
TSI148_LCSR_OFFSET_ITEAL);
- pci_offset_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+ pci_offset_high = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
TSI148_LCSR_OFFSET_ITOFU);
- pci_offset_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_IT[i] +
+ pci_offset_low = ioread32be(bridge->base + TSI148_LCSR_IT[i] +
TSI148_LCSR_OFFSET_ITOFL);
/* Convert 64-bit variables to 2x 32-bit variables */
@@ -833,6 +810,9 @@ static int tsi148_alloc_resource(struct vme_master_resource *image,
unsigned long long existing_size;
int retval = 0;
struct pci_dev *pdev;
+ struct vme_bridge *tsi148_bridge;
+
+ tsi148_bridge = image->parent;
/* Find pci_dev container of dev */
if (tsi148_bridge->parent == NULL) {
@@ -841,8 +821,8 @@ static int tsi148_alloc_resource(struct vme_master_resource *image,
}
pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev);
- existing_size = (unsigned long long)(image->pci_resource.end -
- image->pci_resource.start);
+ existing_size = (unsigned long long)(image->bus_resource.end -
+ image->bus_resource.start);
/* If the existing size is OK, return */
if ((size != 0) && (existing_size == (size - 1)))
@@ -851,10 +831,10 @@ static int tsi148_alloc_resource(struct vme_master_resource *image,
if (existing_size != 0) {
iounmap(image->kern_base);
image->kern_base = NULL;
- if (image->pci_resource.name != NULL)
- kfree(image->pci_resource.name);
- release_resource(&(image->pci_resource));
- memset(&(image->pci_resource), 0, sizeof(struct resource));
+ if (image->bus_resource.name != NULL)
+ kfree(image->bus_resource.name);
+ release_resource(&(image->bus_resource));
+ memset(&(image->bus_resource), 0, sizeof(struct resource));
}
/* Exit here if size is zero */
@@ -862,9 +842,9 @@ static int tsi148_alloc_resource(struct vme_master_resource *image,
return 0;
}
- if (image->pci_resource.name == NULL) {
- image->pci_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL);
- if (image->pci_resource.name == NULL) {
+ if (image->bus_resource.name == NULL) {
+ image->bus_resource.name = kmalloc(VMENAMSIZ+3, GFP_KERNEL);
+ if (image->bus_resource.name == NULL) {
printk(KERN_ERR "Unable to allocate memory for resource"
" name\n");
retval = -ENOMEM;
@@ -872,26 +852,26 @@ static int tsi148_alloc_resource(struct vme_master_resource *image,
}
}
- sprintf((char *)image->pci_resource.name, "%s.%d", tsi148_bridge->name,
+ sprintf((char *)image->bus_resource.name, "%s.%d", tsi148_bridge->name,
image->number);
- image->pci_resource.start = 0;
- image->pci_resource.end = (unsigned long)size;
- image->pci_resource.flags = IORESOURCE_MEM;
+ image->bus_resource.start = 0;
+ image->bus_resource.end = (unsigned long)size;
+ image->bus_resource.flags = IORESOURCE_MEM;
retval = pci_bus_alloc_resource(pdev->bus,
- &(image->pci_resource), size, size, PCIBIOS_MIN_MEM,
+ &(image->bus_resource), size, size, PCIBIOS_MIN_MEM,
0, NULL, NULL);
if (retval) {
printk(KERN_ERR "Failed to allocate mem resource for "
"window %d size 0x%lx start 0x%lx\n",
image->number, (unsigned long)size,
- (unsigned long)image->pci_resource.start);
+ (unsigned long)image->bus_resource.start);
goto err_resource;
}
image->kern_base = ioremap_nocache(
- image->pci_resource.start, size);
+ image->bus_resource.start, size);
if (image->kern_base == NULL) {
printk(KERN_ERR "Failed to remap resource\n");
retval = -ENOMEM;
@@ -903,10 +883,10 @@ static int tsi148_alloc_resource(struct vme_master_resource *image,
iounmap(image->kern_base);
image->kern_base = NULL;
err_remap:
- release_resource(&(image->pci_resource));
+ release_resource(&(image->bus_resource));
err_resource:
- kfree(image->pci_resource.name);
- memset(&(image->pci_resource), 0, sizeof(struct resource));
+ kfree(image->bus_resource.name);
+ memset(&(image->bus_resource), 0, sizeof(struct resource));
err_name:
return retval;
}
@@ -918,9 +898,9 @@ static void tsi148_free_resource(struct vme_master_resource *image)
{
iounmap(image->kern_base);
image->kern_base = NULL;
- release_resource(&(image->pci_resource));
- kfree(image->pci_resource.name);
- memset(&(image->pci_resource), 0, sizeof(struct resource));
+ release_resource(&(image->bus_resource));
+ kfree(image->bus_resource.name);
+ memset(&(image->bus_resource), 0, sizeof(struct resource));
}
/*
@@ -937,6 +917,9 @@ int tsi148_master_set( struct vme_master_resource *image, int enabled,
unsigned int pci_bound_low, pci_bound_high;
unsigned int vme_offset_low, vme_offset_high;
unsigned long long pci_bound, vme_offset, pci_base;
+ struct tsi148_driver *bridge;
+
+ bridge = image->parent->driver_priv;
/* Verify input data */
if (vme_base & 0xFFFF) {
@@ -970,7 +953,7 @@ int tsi148_master_set( struct vme_master_resource *image, int enabled,
pci_bound = 0;
vme_offset = 0;
} else {
- pci_base = (unsigned long long)image->pci_resource.start;
+ pci_base = (unsigned long long)image->bus_resource.start;
/*
* Bound address is a valid address for the window, adjust
@@ -1007,26 +990,12 @@ int tsi148_master_set( struct vme_master_resource *image, int enabled,
i = image->number;
/* Disable while we are mucking around */
- temp_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+ temp_ctl = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
TSI148_LCSR_OFFSET_OTAT);
temp_ctl &= ~TSI148_LCSR_OTAT_EN;
- iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+ iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] +
TSI148_LCSR_OFFSET_OTAT);
-/* XXX Prefetch stuff currently unsupported */
-#if 0
- if (vmeOut->prefetchEnable) {
- temp_ctl |= 0x40000;
- for (x = 0; x < 4; x++) {
- if ((2 << x) >= vmeOut->prefetchSize)
- break;
- }
- if (x == 4)
- x = 3;
- temp_ctl |= (x << 16);
- }
-#endif
-
/* Setup 2eSST speeds */
temp_ctl &= ~TSI148_LCSR_OTAT_2eSSTM_M;
switch (cycle & (VME_2eSST160 | VME_2eSST267 | VME_2eSST320)) {
@@ -1126,33 +1095,27 @@ int tsi148_master_set( struct vme_master_resource *image, int enabled,
temp_ctl |= TSI148_LCSR_OTAT_PGM;
/* Setup mapping */
- iowrite32be(pci_base_high, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+ iowrite32be(pci_base_high, bridge->base + TSI148_LCSR_OT[i] +
TSI148_LCSR_OFFSET_OTSAU);
- iowrite32be(pci_base_low, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+ iowrite32be(pci_base_low, bridge->base + TSI148_LCSR_OT[i] +
TSI148_LCSR_OFFSET_OTSAL);
- iowrite32be(pci_bound_high, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+ iowrite32be(pci_bound_high, bridge->base + TSI148_LCSR_OT[i] +
TSI148_LCSR_OFFSET_OTEAU);
- iowrite32be(pci_bound_low, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+ iowrite32be(pci_bound_low, bridge->base + TSI148_LCSR_OT[i] +
TSI148_LCSR_OFFSET_OTEAL);
- iowrite32be(vme_offset_high, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+ iowrite32be(vme_offset_high, bridge->base + TSI148_LCSR_OT[i] +
TSI148_LCSR_OFFSET_OTOFU);
- iowrite32be(vme_offset_low, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+ iowrite32be(vme_offset_low, bridge->base + TSI148_LCSR_OT[i] +
TSI148_LCSR_OFFSET_OTOFL);
-/* XXX We need to deal with OTBS */
-#if 0
- iowrite32be(vmeOut->bcastSelect2esst, tsi148_bridge->base +
- TSI148_LCSR_OT[i] + TSI148_LCSR_OFFSET_OTBS);
-#endif
-
/* Write ctl reg without enable */
- iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+ iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] +
TSI148_LCSR_OFFSET_OTAT);
if (enabled)
temp_ctl |= TSI148_LCSR_OTAT_EN;
- iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+ iowrite32be(temp_ctl, bridge->base + TSI148_LCSR_OT[i] +
TSI148_LCSR_OFFSET_OTAT);
spin_unlock(&(image->lock));
@@ -1183,23 +1146,26 @@ int __tsi148_master_get( struct vme_master_resource *image, int *enabled,
unsigned int vme_offset_low, vme_offset_high;
unsigned long long pci_base, pci_bound, vme_offset;
+ struct tsi148_driver *bridge;
+
+ bridge = image->parent->driver_priv;
i = image->number;
- ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+ ctl = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
TSI148_LCSR_OFFSET_OTAT);
- pci_base_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+ pci_base_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
TSI148_LCSR_OFFSET_OTSAU);
- pci_base_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+ pci_base_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
TSI148_LCSR_OFFSET_OTSAL);
- pci_bound_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+ pci_bound_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
TSI148_LCSR_OFFSET_OTEAU);
- pci_bound_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+ pci_bound_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
TSI148_LCSR_OFFSET_OTEAL);
- vme_offset_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+ vme_offset_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
TSI148_LCSR_OFFSET_OTOFU);
- vme_offset_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+ vme_offset_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
TSI148_LCSR_OFFSET_OTOFL);
/* Convert 64-bit variables to 2x 32-bit variables */
@@ -1305,6 +1271,9 @@ ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf,
vme_cycle_t cycle;
vme_width_t dwidth;
struct vme_bus_error *vme_err = NULL;
+ struct vme_bridge *tsi148_bridge;
+
+ tsi148_bridge = image->parent;
spin_lock(&(image->lock));
@@ -1317,13 +1286,15 @@ ssize_t tsi148_master_read(struct vme_master_resource *image, void *buf,
__tsi148_master_get(image, &enabled, &vme_base, &size, &aspace, &cycle,
&dwidth);
- vme_err = tsi148_find_error(aspace, vme_base + offset, count);
+ vme_err = tsi148_find_error(tsi148_bridge, aspace, vme_base + offset,
+ count);
if(vme_err != NULL) {
dev_err(image->parent->parent, "First VME read error detected "
"an at address 0x%llx\n", vme_err->address);
retval = vme_err->address - (vme_base + offset);
/* Clear down save errors in this address range */
- tsi148_clear_errors(aspace, vme_base + offset, count);
+ tsi148_clear_errors(tsi148_bridge, aspace, vme_base + offset,
+ count);
}
skip_chk:
@@ -1333,9 +1304,6 @@ skip_chk:
}
-/* XXX We need to change vme_master_resource->mtx to a spinlock so that read
- * and write functions can be used in an interrupt context
- */
ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf,
size_t count, loff_t offset)
{
@@ -1346,6 +1314,12 @@ ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf,
vme_width_t dwidth;
struct vme_bus_error *vme_err = NULL;
+ struct vme_bridge *tsi148_bridge;
+ struct tsi148_driver *bridge;
+
+ tsi148_bridge = image->parent;
+
+ bridge = tsi148_bridge->driver_priv;
spin_lock(&(image->lock));
@@ -1373,15 +1347,17 @@ ssize_t tsi148_master_write(struct vme_master_resource *image, void *buf,
__tsi148_master_get(image, &enabled, &vme_base, &size, &aspace, &cycle,
&dwidth);
- ioread16(flush_image->kern_base + 0x7F000);
+ ioread16(bridge->flush_image->kern_base + 0x7F000);
- vme_err = tsi148_find_error(aspace, vme_base + offset, count);
+ vme_err = tsi148_find_error(tsi148_bridge, aspace, vme_base + offset,
+ count);
if(vme_err != NULL) {
printk("First VME write error detected an at address 0x%llx\n",
vme_err->address);
retval = vme_err->address - (vme_base + offset);
/* Clear down save errors in this address range */
- tsi148_clear_errors(aspace, vme_base + offset, count);
+ tsi148_clear_errors(tsi148_bridge, aspace, vme_base + offset,
+ count);
}
skip_chk:
@@ -1403,48 +1379,50 @@ unsigned int tsi148_master_rmw(struct vme_master_resource *image,
unsigned int pci_addr_high, pci_addr_low;
u32 tmp, result;
int i;
+ struct tsi148_driver *bridge;
+ bridge = image->parent->driver_priv;
/* Find the PCI address that maps to the desired VME address */
i = image->number;
/* Locking as we can only do one of these at a time */
- mutex_lock(&(vme_rmw));
+ mutex_lock(&(bridge->vme_rmw));
/* Lock image */
spin_lock(&(image->lock));
- pci_addr_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+ pci_addr_high = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
TSI148_LCSR_OFFSET_OTSAU);
- pci_addr_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_OT[i] +
+ pci_addr_low = ioread32be(bridge->base + TSI148_LCSR_OT[i] +
TSI148_LCSR_OFFSET_OTSAL);
reg_join(pci_addr_high, pci_addr_low, &pci_addr);
reg_split(pci_addr + offset, &pci_addr_high, &pci_addr_low);
/* Configure registers */
- iowrite32be(mask, tsi148_bridge->base + TSI148_LCSR_RMWEN);
- iowrite32be(compare, tsi148_bridge->base + TSI148_LCSR_RMWC);
- iowrite32be(swap, tsi148_bridge->base + TSI148_LCSR_RMWS);
- iowrite32be(pci_addr_high, tsi148_bridge->base + TSI148_LCSR_RMWAU);
- iowrite32be(pci_addr_low, tsi148_bridge->base + TSI148_LCSR_RMWAL);
+ iowrite32be(mask, bridge->base + TSI148_LCSR_RMWEN);
+ iowrite32be(compare, bridge->base + TSI148_LCSR_RMWC);
+ iowrite32be(swap, bridge->base + TSI148_LCSR_RMWS);
+ iowrite32be(pci_addr_high, bridge->base + TSI148_LCSR_RMWAU);
+ iowrite32be(pci_addr_low, bridge->base + TSI148_LCSR_RMWAL);
/* Enable RMW */
- tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_VMCTRL);
+ tmp = ioread32be(bridge->base + TSI148_LCSR_VMCTRL);
tmp |= TSI148_LCSR_VMCTRL_RMWEN;
- iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_VMCTRL);
+ iowrite32be(tmp, bridge->base + TSI148_LCSR_VMCTRL);
/* Kick process off with a read to the required address. */
result = ioread32be(image->kern_base + offset);
/* Disable RMW */
- tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_VMCTRL);
+ tmp = ioread32be(bridge->base + TSI148_LCSR_VMCTRL);
tmp &= ~TSI148_LCSR_VMCTRL_RMWEN;
- iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_VMCTRL);
+ iowrite32be(tmp, bridge->base + TSI148_LCSR_VMCTRL);
spin_unlock(&(image->lock));
- mutex_unlock(&(vme_rmw));
+ mutex_unlock(&(bridge->vme_rmw));
return result;
}
@@ -1637,8 +1615,6 @@ static int tsi148_dma_set_vme_dest_attributes(u32 *attr, vme_address_t aspace,
/*
* Add a link list descriptor to the list
- *
- * XXX Need to handle 2eSST Broadcast select bits
*/
int tsi148_dma_list_add (struct vme_dma_list *list, struct vme_dma_attr *src,
struct vme_dma_attr *dest, size_t count)
@@ -1651,7 +1627,7 @@ int tsi148_dma_list_add (struct vme_dma_list *list, struct vme_dma_attr *src,
dma_addr_t desc_ptr;
int retval = 0;
- /* XXX descriptor must be aligned on 64-bit boundaries */
+ /* Descriptor must be aligned on 64-bit boundaries */
entry = (struct tsi148_dma_entry *)kmalloc(
sizeof(struct tsi148_dma_entry), GFP_KERNEL);
if (entry == NULL) {
@@ -1788,11 +1764,14 @@ err_mem:
/*
* Check to see if the provided DMA channel is busy.
*/
-static int tsi148_dma_busy(int channel)
+static int tsi148_dma_busy(struct vme_bridge *tsi148_bridge, int channel)
{
u32 tmp;
+ struct tsi148_driver *bridge;
+
+ bridge = tsi148_bridge->driver_priv;
- tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_DMA[channel] +
+ tmp = ioread32be(bridge->base + TSI148_LCSR_DMA[channel] +
TSI148_LCSR_OFFSET_DSTA);
if (tmp & TSI148_LCSR_DSTA_BSY)
@@ -1815,12 +1794,12 @@ int tsi148_dma_list_exec(struct vme_dma_list *list)
dma_addr_t bus_addr;
u32 bus_addr_high, bus_addr_low;
u32 val, dctlreg = 0;
-#if 0
- int x;
-#endif
+ struct tsi148_driver *bridge;
ctrlr = list->parent;
+ bridge = ctrlr->parent->driver_priv;
+
mutex_lock(&(ctrlr->mtx));
channel = ctrlr->number;
@@ -1837,48 +1816,6 @@ int tsi148_dma_list_exec(struct vme_dma_list *list)
} else {
list_add(&(list->list), &(ctrlr->running));
}
-#if 0
- /* XXX Still todo */
- for (x = 0; x < 8; x++) { /* vme block size */
- if ((32 << x) >= vmeDma->maxVmeBlockSize) {
- break;
- }
- }
- if (x == 8)
- x = 7;
- dctlreg |= (x << 12);
-
- for (x = 0; x < 8; x++) { /* pci block size */
- if ((32 << x) >= vmeDma->maxPciBlockSize) {
- break;
- }
- }
- if (x == 8)
- x = 7;
- dctlreg |= (x << 4);
-
- if (vmeDma->vmeBackOffTimer) {
- for (x = 1; x < 8; x++) { /* vme timer */
- if ((1 << (x - 1)) >= vmeDma->vmeBackOffTimer) {
- break;
- }
- }
- if (x == 8)
- x = 7;
- dctlreg |= (x << 8);
- }
-
- if (vmeDma->pciBackOffTimer) {
- for (x = 1; x < 8; x++) { /* pci timer */
- if ((1 << (x - 1)) >= vmeDma->pciBackOffTimer) {
- break;
- }
- }
- if (x == 8)
- x = 7;
- dctlreg |= (x << 0);
- }
-#endif
/* Get first bus address and write into registers */
entry = list_first_entry(&(list->entries), struct tsi148_dma_entry,
@@ -1890,21 +1827,22 @@ int tsi148_dma_list_exec(struct vme_dma_list *list)
reg_split(bus_addr, &bus_addr_high, &bus_addr_low);
- iowrite32be(bus_addr_high, tsi148_bridge->base +
+ iowrite32be(bus_addr_high, bridge->base +
TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DNLAU);
- iowrite32be(bus_addr_low, tsi148_bridge->base +
+ iowrite32be(bus_addr_low, bridge->base +
TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DNLAL);
/* Start the operation */
- iowrite32be(dctlreg | TSI148_LCSR_DCTL_DGO, tsi148_bridge->base +
+ iowrite32be(dctlreg | TSI148_LCSR_DCTL_DGO, bridge->base +
TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DCTL);
- wait_event_interruptible(dma_queue[channel], tsi148_dma_busy(channel));
+ wait_event_interruptible(bridge->dma_queue[channel],
+ tsi148_dma_busy(ctrlr->parent, channel));
/*
* Read status register, this register is valid until we kick off a
* new transfer.
*/
- val = ioread32be(tsi148_bridge->base + TSI148_LCSR_DMA[channel] +
+ val = ioread32be(bridge->base + TSI148_LCSR_DMA[channel] +
TSI148_LCSR_OFFSET_DSTA);
if (val & TSI148_LCSR_DSTA_VBE) {
@@ -1952,12 +1890,15 @@ int tsi148_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base,
{
u32 lm_base_high, lm_base_low, lm_ctl = 0;
int i;
+ struct tsi148_driver *bridge;
+
+ bridge = lm->parent->driver_priv;
mutex_lock(&(lm->mtx));
/* If we already have a callback attached, we can't move it! */
for (i = 0; i < lm->monitors; i++) {
- if(lm_callback[i] != NULL) {
+ if (bridge->lm_callback[i] != NULL) {
mutex_unlock(&(lm->mtx));
printk("Location monitor callback attached, can't "
"reset\n");
@@ -1996,9 +1937,9 @@ int tsi148_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base,
reg_split(lm_base, &lm_base_high, &lm_base_low);
- iowrite32be(lm_base_high, tsi148_bridge->base + TSI148_LCSR_LMBAU);
- iowrite32be(lm_base_low, tsi148_bridge->base + TSI148_LCSR_LMBAL);
- iowrite32be(lm_ctl, tsi148_bridge->base + TSI148_LCSR_LMAT);
+ iowrite32be(lm_base_high, bridge->base + TSI148_LCSR_LMBAU);
+ iowrite32be(lm_base_low, bridge->base + TSI148_LCSR_LMBAL);
+ iowrite32be(lm_ctl, bridge->base + TSI148_LCSR_LMAT);
mutex_unlock(&(lm->mtx));
@@ -2012,12 +1953,15 @@ int tsi148_lm_get(struct vme_lm_resource *lm, unsigned long long *lm_base,
vme_address_t *aspace, vme_cycle_t *cycle)
{
u32 lm_base_high, lm_base_low, lm_ctl, enabled = 0;
+ struct tsi148_driver *bridge;
+
+ bridge = lm->parent->driver_priv;
mutex_lock(&(lm->mtx));
- lm_base_high = ioread32be(tsi148_bridge->base + TSI148_LCSR_LMBAU);
- lm_base_low = ioread32be(tsi148_bridge->base + TSI148_LCSR_LMBAL);
- lm_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_LMAT);
+ lm_base_high = ioread32be(bridge->base + TSI148_LCSR_LMBAU);
+ lm_base_low = ioread32be(bridge->base + TSI148_LCSR_LMBAL);
+ lm_ctl = ioread32be(bridge->base + TSI148_LCSR_LMAT);
reg_join(lm_base_high, lm_base_low, lm_base);
@@ -2060,11 +2004,14 @@ int tsi148_lm_attach(struct vme_lm_resource *lm, int monitor,
void (*callback)(int))
{
u32 lm_ctl, tmp;
+ struct tsi148_driver *bridge;
+
+ bridge = lm->parent->driver_priv;
mutex_lock(&(lm->mtx));
/* Ensure that the location monitor is configured - need PGM or DATA */
- lm_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_LMAT);
+ lm_ctl = ioread32be(bridge->base + TSI148_LCSR_LMAT);
if ((lm_ctl & (TSI148_LCSR_LMAT_PGM | TSI148_LCSR_LMAT_DATA)) == 0) {
mutex_unlock(&(lm->mtx));
printk("Location monitor not properly configured\n");
@@ -2072,28 +2019,28 @@ int tsi148_lm_attach(struct vme_lm_resource *lm, int monitor,
}
/* Check that a callback isn't already attached */
- if (lm_callback[monitor] != NULL) {
+ if (bridge->lm_callback[monitor] != NULL) {
mutex_unlock(&(lm->mtx));
printk("Existing callback attached\n");
return -EBUSY;
}
/* Attach callback */
- lm_callback[monitor] = callback;
+ bridge->lm_callback[monitor] = callback;
/* Enable Location Monitor interrupt */
- tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEN);
+ tmp = ioread32be(bridge->base + TSI148_LCSR_INTEN);
tmp |= TSI148_LCSR_INTEN_LMEN[monitor];
- iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEN);
+ iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEN);
- tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEO);
+ tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO);
tmp |= TSI148_LCSR_INTEO_LMEO[monitor];
- iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEO);
+ iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO);
/* Ensure that global Location Monitor Enable set */
if ((lm_ctl & TSI148_LCSR_LMAT_EN) == 0) {
lm_ctl |= TSI148_LCSR_LMAT_EN;
- iowrite32be(lm_ctl, tsi148_bridge->base + TSI148_LCSR_LMAT);
+ iowrite32be(lm_ctl, bridge->base + TSI148_LCSR_LMAT);
}
mutex_unlock(&(lm->mtx));
@@ -2107,30 +2054,33 @@ int tsi148_lm_attach(struct vme_lm_resource *lm, int monitor,
int tsi148_lm_detach(struct vme_lm_resource *lm, int monitor)
{
u32 lm_en, tmp;
+ struct tsi148_driver *bridge;
+
+ bridge = lm->parent->driver_priv;
mutex_lock(&(lm->mtx));
/* Disable Location Monitor and ensure previous interrupts are clear */
- lm_en = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEN);
+ lm_en = ioread32be(bridge->base + TSI148_LCSR_INTEN);
lm_en &= ~TSI148_LCSR_INTEN_LMEN[monitor];
- iowrite32be(lm_en, tsi148_bridge->base + TSI148_LCSR_INTEN);
+ iowrite32be(lm_en, bridge->base + TSI148_LCSR_INTEN);
- tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_INTEO);
+ tmp = ioread32be(bridge->base + TSI148_LCSR_INTEO);
tmp &= ~TSI148_LCSR_INTEO_LMEO[monitor];
- iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_INTEO);
+ iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO);
iowrite32be(TSI148_LCSR_INTC_LMC[monitor],
- tsi148_bridge->base + TSI148_LCSR_INTC);
+ bridge->base + TSI148_LCSR_INTC);
/* Detach callback */
- lm_callback[monitor] = NULL;
+ bridge->lm_callback[monitor] = NULL;
/* If all location monitors disabled, disable global Location Monitor */
if ((lm_en & (TSI148_LCSR_INTS_LM0S | TSI148_LCSR_INTS_LM1S |
TSI148_LCSR_INTS_LM2S | TSI148_LCSR_INTS_LM3S)) == 0) {
- tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_LMAT);
+ tmp = ioread32be(bridge->base + TSI148_LCSR_LMAT);
tmp &= ~TSI148_LCSR_LMAT_EN;
- iowrite32be(tmp, tsi148_bridge->base + TSI148_LCSR_LMAT);
+ iowrite32be(tmp, bridge->base + TSI148_LCSR_LMAT);
}
mutex_unlock(&(lm->mtx));
@@ -2141,12 +2091,19 @@ int tsi148_lm_detach(struct vme_lm_resource *lm, int monitor)
/*
* Determine Geographical Addressing
*/
-int tsi148_slot_get(void)
+int tsi148_slot_get(struct vme_bridge *tsi148_bridge)
{
u32 slot = 0;
+ struct tsi148_driver *bridge;
+
+ bridge = tsi148_bridge->driver_priv;
+
+ if (!geoid) {
+ slot = ioread32be(bridge->base + TSI148_LCSR_VSTAT);
+ slot = slot & TSI148_LCSR_VSTAT_GA_M;
+ } else
+ slot = geoid;
- slot = ioread32be(tsi148_bridge->base + TSI148_LCSR_VSTAT);
- slot = slot & TSI148_LCSR_VSTAT_GA_M;
return (int)slot;
}
@@ -2167,45 +2124,50 @@ static int __init tsi148_init(void)
* boards registers, this means there is a fix length 508kB window which must
* be mapped onto PCI memory.
*/
-static int tsi148_crcsr_init(struct pci_dev *pdev)
+static int tsi148_crcsr_init(struct vme_bridge *tsi148_bridge,
+ struct pci_dev *pdev)
{
u32 cbar, crat, vstat;
u32 crcsr_bus_high, crcsr_bus_low;
int retval;
+ struct tsi148_driver *bridge;
+
+ bridge = tsi148_bridge->driver_priv;
/* Allocate mem for CR/CSR image */
- crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE,
- &crcsr_bus);
- if (crcsr_kernel == NULL) {
+ bridge->crcsr_kernel = pci_alloc_consistent(pdev, VME_CRCSR_BUF_SIZE,
+ &(bridge->crcsr_bus));
+ if (bridge->crcsr_kernel == NULL) {
dev_err(&pdev->dev, "Failed to allocate memory for CR/CSR "
"image\n");
return -ENOMEM;
}
- memset(crcsr_kernel, 0, VME_CRCSR_BUF_SIZE);
+ memset(bridge->crcsr_kernel, 0, VME_CRCSR_BUF_SIZE);
- reg_split(crcsr_bus, &crcsr_bus_high, &crcsr_bus_low);
+ reg_split(bridge->crcsr_bus, &crcsr_bus_high, &crcsr_bus_low);
- iowrite32be(crcsr_bus_high, tsi148_bridge->base + TSI148_LCSR_CROU);
- iowrite32be(crcsr_bus_low, tsi148_bridge->base + TSI148_LCSR_CROL);
+ iowrite32be(crcsr_bus_high, bridge->base + TSI148_LCSR_CROU);
+ iowrite32be(crcsr_bus_low, bridge->base + TSI148_LCSR_CROL);
/* Ensure that the CR/CSR is configured at the correct offset */
- cbar = ioread32be(tsi148_bridge->base + TSI148_CBAR);
+ cbar = ioread32be(bridge->base + TSI148_CBAR);
cbar = (cbar & TSI148_CRCSR_CBAR_M)>>3;
- vstat = tsi148_slot_get();
+ vstat = tsi148_slot_get(tsi148_bridge);
if (cbar != vstat) {
+ cbar = vstat;
dev_info(&pdev->dev, "Setting CR/CSR offset\n");
- iowrite32be(cbar<<3, tsi148_bridge->base + TSI148_CBAR);
+ iowrite32be(cbar<<3, bridge->base + TSI148_CBAR);
}
dev_info(&pdev->dev, "CR/CSR Offset: %d\n", cbar);
- crat = ioread32be(tsi148_bridge->base + TSI148_LCSR_CRAT);
+ crat = ioread32be(bridge->base + TSI148_LCSR_CRAT);
if (crat & TSI148_LCSR_CRAT_EN) {
dev_info(&pdev->dev, "Enabling CR/CSR space\n");
iowrite32be(crat | TSI148_LCSR_CRAT_EN,
- tsi148_bridge->base + TSI148_LCSR_CRAT);
+ bridge->base + TSI148_LCSR_CRAT);
} else
dev_info(&pdev->dev, "CR/CSR already enabled\n");
@@ -2214,8 +2176,9 @@ static int tsi148_crcsr_init(struct pci_dev *pdev)
* through VME writes.
*/
if(err_chk) {
- retval = tsi148_master_set(flush_image, 1, (vstat * 0x80000),
- 0x80000, VME_CRCSR, VME_SCT, VME_D16);
+ retval = tsi148_master_set(bridge->flush_image, 1,
+ (vstat * 0x80000), 0x80000, VME_CRCSR, VME_SCT,
+ VME_D16);
if (retval)
dev_err(&pdev->dev, "Configuring flush image failed\n");
}
@@ -2224,20 +2187,25 @@ static int tsi148_crcsr_init(struct pci_dev *pdev)
}
-static void tsi148_crcsr_exit(struct pci_dev *pdev)
+static void tsi148_crcsr_exit(struct vme_bridge *tsi148_bridge,
+ struct pci_dev *pdev)
{
u32 crat;
+ struct tsi148_driver *bridge;
+
+ bridge = tsi148_bridge->driver_priv;
/* Turn off CR/CSR space */
- crat = ioread32be(tsi148_bridge->base + TSI148_LCSR_CRAT);
+ crat = ioread32be(bridge->base + TSI148_LCSR_CRAT);
iowrite32be(crat & ~TSI148_LCSR_CRAT_EN,
- tsi148_bridge->base + TSI148_LCSR_CRAT);
+ bridge->base + TSI148_LCSR_CRAT);
/* Free image */
- iowrite32be(0, tsi148_bridge->base + TSI148_LCSR_CROU);
- iowrite32be(0, tsi148_bridge->base + TSI148_LCSR_CROL);
+ iowrite32be(0, bridge->base + TSI148_LCSR_CROU);
+ iowrite32be(0, bridge->base + TSI148_LCSR_CROL);
- pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, crcsr_kernel, crcsr_bus);
+ pci_free_consistent(pdev, VME_CRCSR_BUF_SIZE, bridge->crcsr_kernel,
+ bridge->crcsr_bus);
}
static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id)
@@ -2245,6 +2213,8 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id)
int retval, i, master_num;
u32 data;
struct list_head *pos = NULL;
+ struct vme_bridge *tsi148_bridge;
+ struct tsi148_driver *tsi148_device;
struct vme_master_resource *master_image;
struct vme_slave_resource *slave_image;
struct vme_dma_resource *dma_ctrlr;
@@ -2264,6 +2234,18 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id)
memset(tsi148_bridge, 0, sizeof(struct vme_bridge));
+ tsi148_device = kmalloc(sizeof(struct tsi148_driver), GFP_KERNEL);
+ if (tsi148_device == NULL) {
+ dev_err(&pdev->dev, "Failed to allocate memory for device "
+ "structure\n");
+ retval = -ENOMEM;
+ goto err_driver;
+ }
+
+ memset(tsi148_device, 0, sizeof(struct tsi148_driver));
+
+ tsi148_bridge->driver_priv = tsi148_device;
+
/* Enable the device */
retval = pci_enable_device(pdev);
if (retval) {
@@ -2279,15 +2261,16 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
/* map registers in BAR 0 */
- tsi148_bridge->base = ioremap_nocache(pci_resource_start(pdev, 0), 4096);
- if (!tsi148_bridge->base) {
+ tsi148_device->base = ioremap_nocache(pci_resource_start(pdev, 0),
+ 4096);
+ if (!tsi148_device->base) {
dev_err(&pdev->dev, "Unable to remap CRG region\n");
retval = -EIO;
goto err_remap;
}
/* Check to see if the mapping worked out */
- data = ioread32(tsi148_bridge->base + TSI148_PCFS_ID) & 0x0000FFFF;
+ data = ioread32(tsi148_device->base + TSI148_PCFS_ID) & 0x0000FFFF;
if (data != PCI_VENDOR_ID_TUNDRA) {
dev_err(&pdev->dev, "CRG region check failed\n");
retval = -EIO;
@@ -2295,12 +2278,11 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
/* Initialize wait queues & mutual exclusion flags */
- /* XXX These need to be moved to the vme_bridge structure */
- init_waitqueue_head(&dma_queue[0]);
- init_waitqueue_head(&dma_queue[1]);
- init_waitqueue_head(&iack_queue);
- mutex_init(&(vme_int));
- mutex_init(&(vme_rmw));
+ init_waitqueue_head(&(tsi148_device->dma_queue[0]));
+ init_waitqueue_head(&(tsi148_device->dma_queue[1]));
+ init_waitqueue_head(&(tsi148_device->iack_queue));
+ mutex_init(&(tsi148_device->vme_int));
+ mutex_init(&(tsi148_device->vme_rmw));
tsi148_bridge->parent = &(pdev->dev);
strcpy(tsi148_bridge->name, driver_name);
@@ -2320,29 +2302,29 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id)
master_num = TSI148_MAX_MASTER;
if(err_chk){
master_num--;
- /* XXX */
- flush_image = (struct vme_master_resource *)kmalloc(
- sizeof(struct vme_master_resource), GFP_KERNEL);
- if (flush_image == NULL) {
+
+ tsi148_device->flush_image = (struct vme_master_resource *)
+ kmalloc(sizeof(struct vme_master_resource), GFP_KERNEL);
+ if (tsi148_device->flush_image == NULL) {
dev_err(&pdev->dev, "Failed to allocate memory for "
"flush resource structure\n");
retval = -ENOMEM;
goto err_master;
}
- flush_image->parent = tsi148_bridge;
- spin_lock_init(&(flush_image->lock));
- flush_image->locked = 1;
- flush_image->number = master_num;
- flush_image->address_attr = VME_A16 | VME_A24 | VME_A32 |
- VME_A64;
- flush_image->cycle_attr = VME_SCT | VME_BLT | VME_MBLT |
- VME_2eVME | VME_2eSST | VME_2eSSTB | VME_2eSST160 |
- VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER |
- VME_PROG | VME_DATA;
- flush_image->width_attr = VME_D16 | VME_D32;
- memset(&(flush_image->pci_resource), 0,
+ tsi148_device->flush_image->parent = tsi148_bridge;
+ spin_lock_init(&(tsi148_device->flush_image->lock));
+ tsi148_device->flush_image->locked = 1;
+ tsi148_device->flush_image->number = master_num;
+ tsi148_device->flush_image->address_attr = VME_A16 | VME_A24 |
+ VME_A32 | VME_A64;
+ tsi148_device->flush_image->cycle_attr = VME_SCT | VME_BLT |
+ VME_MBLT | VME_2eVME | VME_2eSST | VME_2eSSTB |
+ VME_2eSST160 | VME_2eSST267 | VME_2eSST320 | VME_SUPER |
+ VME_USER | VME_PROG | VME_DATA;
+ tsi148_device->flush_image->width_attr = VME_D16 | VME_D32;
+ memset(&(tsi148_device->flush_image->bus_resource), 0,
sizeof(struct resource));
- flush_image->kern_base = NULL;
+ tsi148_device->flush_image->kern_base = NULL;
}
/* Add master windows to list */
@@ -2367,7 +2349,7 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id)
VME_2eSST267 | VME_2eSST320 | VME_SUPER | VME_USER |
VME_PROG | VME_DATA;
master_image->width_attr = VME_D16 | VME_D32;
- memset(&(master_image->pci_resource), 0,
+ memset(&(master_image->bus_resource), 0,
sizeof(struct resource));
master_image->kern_base = NULL;
list_add_tail(&(master_image->list),
@@ -2415,6 +2397,10 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mutex_init(&(dma_ctrlr->mtx));
dma_ctrlr->locked = 0;
dma_ctrlr->number = i;
+ dma_ctrlr->route_attr = VME_DMA_VME_TO_MEM |
+ VME_DMA_MEM_TO_VME | VME_DMA_VME_TO_VME |
+ VME_DMA_MEM_TO_MEM | VME_DMA_PATTERN_TO_VME |
+ VME_DMA_PATTERN_TO_MEM;
INIT_LIST_HEAD(&(dma_ctrlr->pending));
INIT_LIST_HEAD(&(dma_ctrlr->running));
list_add_tail(&(dma_ctrlr->list),
@@ -2455,40 +2441,42 @@ static int tsi148_probe(struct pci_dev *pdev, const struct pci_device_id *id)
tsi148_bridge->lm_detach = tsi148_lm_detach;
tsi148_bridge->slot_get = tsi148_slot_get;
- data = ioread32be(tsi148_bridge->base + TSI148_LCSR_VSTAT);
+ data = ioread32be(tsi148_device->base + TSI148_LCSR_VSTAT);
dev_info(&pdev->dev, "Board is%s the VME system controller\n",
(data & TSI148_LCSR_VSTAT_SCONS)? "" : " not");
- dev_info(&pdev->dev, "VME geographical address is %d\n",
- data & TSI148_LCSR_VSTAT_GA_M);
+ if (!geoid)
+ dev_info(&pdev->dev, "VME geographical address is %d\n",
+ data & TSI148_LCSR_VSTAT_GA_M);
+ else
+ dev_info(&pdev->dev, "VME geographical address is set to %d\n",
+ geoid);
+
dev_info(&pdev->dev, "VME Write and flush and error check is %s\n",
err_chk ? "enabled" : "disabled");
- if(tsi148_crcsr_init(pdev)) {
+ if (tsi148_crcsr_init(tsi148_bridge, pdev))
dev_err(&pdev->dev, "CR/CSR configuration failed.\n");
goto err_crcsr;
- }
-
- /* Need to save tsi148_bridge pointer locally in link list for use in
- * tsi148_remove()
- */
retval = vme_register_bridge(tsi148_bridge);
if (retval != 0) {
dev_err(&pdev->dev, "Chip Registration failed.\n");
goto err_reg;
}
+ pci_set_drvdata(pdev, tsi148_bridge);
+
/* Clear VME bus "board fail", and "power-up reset" lines */
- data = ioread32be(tsi148_bridge->base + TSI148_LCSR_VSTAT);
+ data = ioread32be(tsi148_device->base + TSI148_LCSR_VSTAT);
data &= ~TSI148_LCSR_VSTAT_BRDFL;
data |= TSI148_LCSR_VSTAT_CPURST;
- iowrite32be(data, tsi148_bridge->base + TSI148_LCSR_VSTAT);
+ iowrite32be(data, tsi148_device->base + TSI148_LCSR_VSTAT);
return 0;
vme_unregister_bridge(tsi148_bridge);
err_reg:
- tsi148_crcsr_exit(pdev);
+ tsi148_crcsr_exit(tsi148_bridge, pdev);
err_crcsr:
err_lm:
/* resources are stored in link list */
@@ -2519,15 +2507,17 @@ err_master:
kfree(master_image);
}
- tsi148_irq_exit(pdev);
+ tsi148_irq_exit(tsi148_device, pdev);
err_irq:
err_test:
- iounmap(tsi148_bridge->base);
+ iounmap(tsi148_device->base);
err_remap:
pci_release_regions(pdev);
err_resource:
pci_disable_device(pdev);
err_enable:
+ kfree(tsi148_device);
+err_driver:
kfree(tsi148_bridge);
err_struct:
return retval;
@@ -2541,56 +2531,58 @@ static void tsi148_remove(struct pci_dev *pdev)
struct vme_slave_resource *slave_image;
struct vme_dma_resource *dma_ctrlr;
int i;
+ struct tsi148_driver *bridge;
+ struct vme_bridge *tsi148_bridge = pci_get_drvdata(pdev);
- dev_dbg(&pdev->dev, "Driver is being unloaded.\n");
+ bridge = tsi148_bridge->driver_priv;
- /* XXX We need to find the pdev->dev in the list of vme_bridge->dev's */
+
+ dev_dbg(&pdev->dev, "Driver is being unloaded.\n");
/*
* Shutdown all inbound and outbound windows.
*/
for (i = 0; i < 8; i++) {
- iowrite32be(0, tsi148_bridge->base + TSI148_LCSR_IT[i] +
+ iowrite32be(0, bridge->base + TSI148_LCSR_IT[i] +
TSI148_LCSR_OFFSET_ITAT);
- iowrite32be(0, tsi148_bridge->base + TSI148_LCSR_OT[i] +
+ iowrite32be(0, bridge->base + TSI148_LCSR_OT[i] +
TSI148_LCSR_OFFSET_OTAT);
}
/*
* Shutdown Location monitor.
*/
- iowrite32be(0, tsi148_bridge->base + TSI148_LCSR_LMAT);
+ iowrite32be(0, bridge->base + TSI148_LCSR_LMAT);
/*
* Shutdown CRG map.
*/
- iowrite32be(0, tsi148_bridge->base + TSI148_LCSR_CSRAT);
+ iowrite32be(0, bridge->base + TSI148_LCSR_CSRAT);
/*
* Clear error status.
*/
- iowrite32be(0xFFFFFFFF, tsi148_bridge->base + TSI148_LCSR_EDPAT);
- iowrite32be(0xFFFFFFFF, tsi148_bridge->base + TSI148_LCSR_VEAT);
- iowrite32be(0x07000700, tsi148_bridge->base + TSI148_LCSR_PSTAT);
+ iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_EDPAT);
+ iowrite32be(0xFFFFFFFF, bridge->base + TSI148_LCSR_VEAT);
+ iowrite32be(0x07000700, bridge->base + TSI148_LCSR_PSTAT);
/*
* Remove VIRQ interrupt (if any)
*/
- if (ioread32be(tsi148_bridge->base + TSI148_LCSR_VICR) & 0x800) {
- iowrite32be(0x8000, tsi148_bridge->base + TSI148_LCSR_VICR);
- }
+ if (ioread32be(bridge->base + TSI148_LCSR_VICR) & 0x800)
+ iowrite32be(0x8000, bridge->base + TSI148_LCSR_VICR);
/*
* Map all Interrupts to PCI INTA
*/
- iowrite32be(0x0, tsi148_bridge->base + TSI148_LCSR_INTM1);
- iowrite32be(0x0, tsi148_bridge->base + TSI148_LCSR_INTM2);
+ iowrite32be(0x0, bridge->base + TSI148_LCSR_INTM1);
+ iowrite32be(0x0, bridge->base + TSI148_LCSR_INTM2);
- tsi148_irq_exit(pdev);
+ tsi148_irq_exit(bridge, pdev);
vme_unregister_bridge(tsi148_bridge);
- tsi148_crcsr_exit(pdev);
+ tsi148_crcsr_exit(tsi148_bridge, pdev);
/* resources are stored in link list */
list_for_each(pos, &(tsi148_bridge->dma_resources)) {
@@ -2608,19 +2600,22 @@ static void tsi148_remove(struct pci_dev *pdev)
/* resources are stored in link list */
list_for_each(pos, &(tsi148_bridge->master_resources)) {
- master_image = list_entry(pos, struct vme_master_resource, list);
+ master_image = list_entry(pos, struct vme_master_resource,
+ list);
list_del(pos);
kfree(master_image);
}
- tsi148_irq_exit(pdev);
+ tsi148_irq_exit(bridge, pdev);
- iounmap(tsi148_bridge->base);
+ iounmap(bridge->base);
pci_release_regions(pdev);
pci_disable_device(pdev);
+ kfree(tsi148_bridge->driver_priv);
+
kfree(tsi148_bridge);
}
@@ -2634,250 +2629,11 @@ static void __exit tsi148_exit(void)
MODULE_PARM_DESC(err_chk, "Check for VME errors on reads and writes");
module_param(err_chk, bool, 0);
+MODULE_PARM_DESC(geoid, "Override geographical addressing");
+module_param(geoid, int, 0);
+
MODULE_DESCRIPTION("VME driver for the Tundra Tempe VME bridge");
MODULE_LICENSE("GPL");
module_init(tsi148_init);
module_exit(tsi148_exit);
-
-/*----------------------------------------------------------------------------
- * STAGING
- *--------------------------------------------------------------------------*/
-
-#if 0
-/*
- * Direct Mode DMA transfer
- *
- * XXX Not looking at direct mode for now, we can always use link list mode
- * with a single entry.
- */
-int tsi148_dma_run(struct vme_dma_resource *resource, struct vme_dma_attr src,
- struct vme_dma_attr dest, size_t count)
-{
- u32 dctlreg = 0;
- unsigned int tmp;
- int val;
- int channel, x;
- struct vmeDmaPacket *cur_dma;
- struct tsi148_dma_descriptor *dmaLL;
-
- /* direct mode */
- dctlreg = 0x800000;
-
- for (x = 0; x < 8; x++) { /* vme block size */
- if ((32 << x) >= vmeDma->maxVmeBlockSize) {
- break;
- }
- }
- if (x == 8)
- x = 7;
- dctlreg |= (x << 12);
-
- for (x = 0; x < 8; x++) { /* pci block size */
- if ((32 << x) >= vmeDma->maxPciBlockSize) {
- break;
- }
- }
- if (x == 8)
- x = 7;
- dctlreg |= (x << 4);
-
- if (vmeDma->vmeBackOffTimer) {
- for (x = 1; x < 8; x++) { /* vme timer */
- if ((1 << (x - 1)) >= vmeDma->vmeBackOffTimer) {
- break;
- }
- }
- if (x == 8)
- x = 7;
- dctlreg |= (x << 8);
- }
-
- if (vmeDma->pciBackOffTimer) {
- for (x = 1; x < 8; x++) { /* pci timer */
- if ((1 << (x - 1)) >= vmeDma->pciBackOffTimer) {
- break;
- }
- }
- if (x == 8)
- x = 7;
- dctlreg |= (x << 0);
- }
-
- /* Program registers for DMA transfer */
- iowrite32be(dmaLL->dsau, tsi148_bridge->base +
- TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DSAU);
- iowrite32be(dmaLL->dsal, tsi148_bridge->base +
- TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DSAL);
- iowrite32be(dmaLL->ddau, tsi148_bridge->base +
- TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DDAU);
- iowrite32be(dmaLL->ddal, tsi148_bridge->base +
- TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DDAL);
- iowrite32be(dmaLL->dsat, tsi148_bridge->base +
- TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DSAT);
- iowrite32be(dmaLL->ddat, tsi148_bridge->base +
- TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DDAT);
- iowrite32be(dmaLL->dcnt, tsi148_bridge->base +
- TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DCNT);
- iowrite32be(dmaLL->ddbs, tsi148_bridge->base +
- TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DDBS);
-
- /* Start the operation */
- iowrite32be(dctlreg | 0x2000000, tsi148_bridge->base +
- TSI148_LCSR_DMA[channel] + TSI148_LCSR_OFFSET_DCTL);
-
- tmp = ioread32be(tsi148_bridge->base + TSI148_LCSR_DMA[channel] +
- TSI148_LCSR_OFFSET_DSTA);
- wait_event_interruptible(dma_queue[channel], (tmp & 0x1000000) == 0);
-
- /*
- * Read status register, we should probably do this in some error
- * handler rather than here so that we can be sure we haven't kicked off
- * another DMA transfer.
- */
- val = ioread32be(tsi148_bridge->base + TSI148_LCSR_DMA[channel] +
- TSI148_LCSR_OFFSET_DSTA);
-
- vmeDma->vmeDmaStatus = 0;
- if (val & 0x10000000) {
- printk(KERN_ERR
- "DMA Error in DMA_tempe_irqhandler DSTA=%08X\n",
- val);
- vmeDma->vmeDmaStatus = val;
-
- }
- return (0);
-}
-#endif
-
-#if 0
-
-/* Global VME controller information */
-struct pci_dev *vme_pci_dev;
-
-/*
- * Set the VME bus arbiter with the requested attributes
- */
-int tempe_set_arbiter(vmeArbiterCfg_t * vmeArb)
-{
- int temp_ctl = 0;
- int gto = 0;
-
- temp_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_VCTRL);
- temp_ctl &= 0xFFEFFF00;
-
- if (vmeArb->globalTimeoutTimer == 0xFFFFFFFF) {
- gto = 8;
- } else if (vmeArb->globalTimeoutTimer > 2048) {
- return (-EINVAL);
- } else if (vmeArb->globalTimeoutTimer == 0) {
- gto = 0;
- } else {
- gto = 1;
- while ((16 * (1 << (gto - 1))) < vmeArb->globalTimeoutTimer) {
- gto += 1;
- }
- }
- temp_ctl |= gto;
-
- if (vmeArb->arbiterMode != VME_PRIORITY_MODE) {
- temp_ctl |= 1 << 6;
- }
-
- if (vmeArb->arbiterTimeoutFlag) {
- temp_ctl |= 1 << 7;
- }
-
- if (vmeArb->noEarlyReleaseFlag) {
- temp_ctl |= 1 << 20;
- }
- iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_VCTRL);
-
- return (0);
-}
-
-/*
- * Return the attributes of the VME bus arbiter.
- */
-int tempe_get_arbiter(vmeArbiterCfg_t * vmeArb)
-{
- int temp_ctl = 0;
- int gto = 0;
-
-
- temp_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_VCTRL);
-
- gto = temp_ctl & 0xF;
- if (gto != 0) {
- vmeArb->globalTimeoutTimer = (16 * (1 << (gto - 1)));
- }
-
- if (temp_ctl & (1 << 6)) {
- vmeArb->arbiterMode = VME_R_ROBIN_MODE;
- } else {
- vmeArb->arbiterMode = VME_PRIORITY_MODE;
- }
-
- if (temp_ctl & (1 << 7)) {
- vmeArb->arbiterTimeoutFlag = 1;
- }
-
- if (temp_ctl & (1 << 20)) {
- vmeArb->noEarlyReleaseFlag = 1;
- }
-
- return (0);
-}
-
-/*
- * Set the VME bus requestor with the requested attributes
- */
-int tempe_set_requestor(vmeRequesterCfg_t * vmeReq)
-{
- int temp_ctl = 0;
-
- temp_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_VMCTRL);
- temp_ctl &= 0xFFFF0000;
-
- if (vmeReq->releaseMode == 1) {
- temp_ctl |= (1 << 3);
- }
-
- if (vmeReq->fairMode == 1) {
- temp_ctl |= (1 << 2);
- }
-
- temp_ctl |= (vmeReq->timeonTimeoutTimer & 7) << 8;
- temp_ctl |= (vmeReq->timeoffTimeoutTimer & 7) << 12;
- temp_ctl |= vmeReq->requestLevel;
-
- iowrite32be(temp_ctl, tsi148_bridge->base + TSI148_LCSR_VMCTRL);
- return (0);
-}
-
-/*
- * Return the attributes of the VME bus requestor
- */
-int tempe_get_requestor(vmeRequesterCfg_t * vmeReq)
-{
- int temp_ctl = 0;
-
- temp_ctl = ioread32be(tsi148_bridge->base + TSI148_LCSR_VMCTRL);
-
- if (temp_ctl & 0x18) {
- vmeReq->releaseMode = 1;
- }
-
- if (temp_ctl & (1 << 2)) {
- vmeReq->fairMode = 1;
- }
-
- vmeReq->requestLevel = temp_ctl & 3;
- vmeReq->timeonTimeoutTimer = (temp_ctl >> 8) & 7;
- vmeReq->timeoffTimeoutTimer = (temp_ctl >> 12) & 7;
-
- return (0);
-}
-
-
-#endif
diff --git a/drivers/staging/vme/bridges/vme_tsi148.h b/drivers/staging/vme/bridges/vme_tsi148.h
index 6f0f705ce6b..9e5f7fa1d74 100644
--- a/drivers/staging/vme/bridges/vme_tsi148.h
+++ b/drivers/staging/vme/bridges/vme_tsi148.h
@@ -33,6 +33,22 @@
#define TSI148_MAX_MAILBOX 4 /* Max Mail Box registers */
#define TSI148_MAX_SEMAPHORE 8 /* Max Semaphores */
+/* Structure used to hold driver specific information */
+struct tsi148_driver {
+ void *base; /* Base Address of device registers */
+ wait_queue_head_t dma_queue[2];
+ wait_queue_head_t iack_queue;
+ void (*lm_callback[4])(int); /* Called in interrupt handler */
+ void *crcsr_kernel;
+ dma_addr_t crcsr_bus;
+ struct vme_master_resource *flush_image;
+ struct mutex vme_rmw; /* Only one RMW cycle at a time */
+ struct mutex vme_int; /*
+ * Only one VME interrupt can be
+ * generated at a time, provide locking
+ */
+};
+
/*
* Layout of a DMAC Linked-List Descriptor
*
diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c
index e228942ee08..c60c80fb241 100644
--- a/drivers/staging/vme/devices/vme_user.c
+++ b/drivers/staging/vme/devices/vme_user.c
@@ -1,8 +1,8 @@
/*
* VMEbus User access driver
*
- * Author: Martyn Welch <martyn.welch@gefanuc.com>
- * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ * Author: Martyn Welch <martyn.welch@ge.com>
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
*
* Based on work by:
* Tom Armistead and Ajit Prem
@@ -400,8 +400,39 @@ static ssize_t vme_user_write(struct file *file, const char *buf, size_t count,
static loff_t vme_user_llseek(struct file *file, loff_t off, int whence)
{
- printk(KERN_ERR "Llseek currently incomplete\n");
- return -EINVAL;
+ loff_t absolute = -1;
+ unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+ size_t image_size;
+
+ down(&image[minor].sem);
+ image_size = vme_get_size(image[minor].resource);
+
+ switch (whence) {
+ case SEEK_SET:
+ absolute = off;
+ break;
+ case SEEK_CUR:
+ absolute = file->f_pos + off;
+ break;
+ case SEEK_END:
+ absolute = image_size + off;
+ break;
+ default:
+ up(&image[minor].sem);
+ return -EINVAL;
+ break;
+ }
+
+ if ((absolute < 0) || (absolute >= image_size)) {
+ up(&image[minor].sem);
+ return -EINVAL;
+ }
+
+ file->f_pos = absolute;
+
+ up(&image[minor].sem);
+
+ return absolute;
}
/*
@@ -574,8 +605,8 @@ static int __init vme_user_init(void)
* in future revisions if that ever becomes necessary.
*/
if (bus_num > USER_BUS_MAX) {
- printk(KERN_ERR "%s: Driver only able to handle %d PIO2 "
- "Cards\n", driver_name, USER_BUS_MAX);
+ printk(KERN_ERR "%s: Driver only able to handle %d buses\n",
+ driver_name, USER_BUS_MAX);
bus_num = USER_BUS_MAX;
}
@@ -670,8 +701,12 @@ static int __init vme_user_probe(struct device *dev, int cur_bus, int cur_slot)
/* Request slave resources and allocate buffers (128kB wide) */
for (i = SLAVE_MINOR; i < (SLAVE_MAX + 1); i++) {
/* XXX Need to properly request attributes */
+ /* For ca91cx42 bridge there are only two slave windows
+ * supporting A16 addressing, so we request A24 supported
+ * by all windows.
+ */
image[i].resource = vme_slave_request(vme_user_bridge,
- VME_A16, VME_SCT);
+ VME_A24, VME_SCT);
if (image[i].resource == NULL) {
printk(KERN_WARNING "Unable to allocate slave "
"resource\n");
@@ -703,6 +738,14 @@ static int __init vme_user_probe(struct device *dev, int cur_bus, int cur_slot)
"resource\n");
goto err_master;
}
+ image[i].size_buf = PCI_BUF_SIZE;
+ image[i].kern_buf = kmalloc(image[i].size_buf, GFP_KERNEL);
+ if (image[i].kern_buf == NULL) {
+ printk(KERN_WARNING "Unable to allocate memory for "
+ "master window buffers\n");
+ err = -ENOMEM;
+ goto err_master_buf;
+ }
}
/* Create sysfs entries - on udev systems this creates the dev files */
@@ -756,6 +799,9 @@ err_sysfs:
/* Ensure counter set correcty to unalloc all master windows */
i = MASTER_MAX + 1;
+err_master_buf:
+ for (i = MASTER_MINOR; i < (MASTER_MAX + 1); i++)
+ kfree(image[i].kern_buf);
err_master:
while (i > MASTER_MINOR) {
i--;
@@ -791,6 +837,9 @@ static int __exit vme_user_remove(struct device *dev, int cur_bus, int cur_slot)
}
class_destroy(vme_user_sysfs_class);
+ for (i = MASTER_MINOR; i < (MASTER_MAX + 1); i++)
+ kfree(image[i].kern_buf);
+
for (i = SLAVE_MINOR; i < (SLAVE_MAX + 1); i++) {
vme_slave_set(image[i].resource, 0, 0, 0, 0, VME_A32, 0);
vme_slave_free(image[i].resource);
@@ -818,7 +867,7 @@ MODULE_PARM_DESC(bus, "Enumeration of VMEbus to which the driver is connected");
module_param_array(bus, int, &bus_num, 0);
MODULE_DESCRIPTION("VME User Space Access Driver");
-MODULE_AUTHOR("Martyn Welch <martyn.welch@gefanuc.com");
+MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
MODULE_LICENSE("GPL");
module_init(vme_user_init);
diff --git a/drivers/staging/vme/vme.c b/drivers/staging/vme/vme.c
index 994fdb9b212..d6d84ebeeec 100644
--- a/drivers/staging/vme/vme.c
+++ b/drivers/staging/vme/vme.c
@@ -1,8 +1,8 @@
/*
* VME Bridge Framework
*
- * Author: Martyn Welch <martyn.welch@gefanuc.com>
- * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ * Author: Martyn Welch <martyn.welch@ge.com>
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, Inc.
*
* Based on work by Tom Armistead and Ajit Prem
* Copyright 2004 Motorola Inc.
@@ -37,8 +37,8 @@
static unsigned int vme_bus_numbers;
DEFINE_MUTEX(vme_bus_num_mtx);
-static void __exit vme_exit (void);
-static int __init vme_init (void);
+static void __exit vme_exit(void);
+static int __init vme_init(void);
/*
@@ -86,26 +86,26 @@ static struct vme_bridge *find_bridge(struct vme_resource *resource)
* XXX VME bridges could be available on buses other than PCI. At the momment
* this framework only supports PCI devices.
*/
-void * vme_alloc_consistent(struct vme_resource *resource, size_t size,
+void *vme_alloc_consistent(struct vme_resource *resource, size_t size,
dma_addr_t *dma)
{
struct vme_bridge *bridge;
struct pci_dev *pdev;
- if(resource == NULL) {
- printk("No resource\n");
+ if (resource == NULL) {
+ printk(KERN_ERR "No resource\n");
return NULL;
}
bridge = find_bridge(resource);
- if(bridge == NULL) {
- printk("Can't find bridge\n");
+ if (bridge == NULL) {
+ printk(KERN_ERR "Can't find bridge\n");
return NULL;
}
/* Find pci_dev container of dev */
if (bridge->parent == NULL) {
- printk("Dev entry NULL\n");
+ printk(KERN_ERR "Dev entry NULL\n");
return NULL;
}
pdev = container_of(bridge->parent, struct pci_dev, dev);
@@ -126,14 +126,14 @@ void vme_free_consistent(struct vme_resource *resource, size_t size,
struct vme_bridge *bridge;
struct pci_dev *pdev;
- if(resource == NULL) {
- printk("No resource\n");
+ if (resource == NULL) {
+ printk(KERN_ERR "No resource\n");
return;
}
bridge = find_bridge(resource);
- if(bridge == NULL) {
- printk("Can't find bridge\n");
+ if (bridge == NULL) {
+ printk(KERN_ERR "Can't find bridge\n");
return;
}
@@ -216,7 +216,7 @@ static int vme_check_window(vme_address_t aspace, unsigned long long vme_base,
/* User Defined */
break;
default:
- printk("Invalid address space\n");
+ printk(KERN_ERR "Invalid address space\n");
retval = -EINVAL;
break;
}
@@ -228,7 +228,7 @@ static int vme_check_window(vme_address_t aspace, unsigned long long vme_base,
* Request a slave image with specific attributes, return some unique
* identifier.
*/
-struct vme_resource * vme_slave_request(struct device *dev,
+struct vme_resource *vme_slave_request(struct device *dev,
vme_address_t address, vme_cycle_t cycle)
{
struct vme_bridge *bridge;
@@ -249,13 +249,13 @@ struct vme_resource * vme_slave_request(struct device *dev,
struct vme_slave_resource, list);
if (slave_image == NULL) {
- printk("Registered NULL Slave resource\n");
+ printk(KERN_ERR "Registered NULL Slave resource\n");
continue;
}
/* Find an unlocked and compatible image */
mutex_lock(&(slave_image->mtx));
- if(((slave_image->address_attr & address) == address) &&
+ if (((slave_image->address_attr & address) == address) &&
((slave_image->cycle_attr & cycle) == cycle) &&
(slave_image->locked == 0)) {
@@ -292,7 +292,7 @@ err_bus:
}
EXPORT_SYMBOL(vme_slave_request);
-int vme_slave_set (struct vme_resource *resource, int enabled,
+int vme_slave_set(struct vme_resource *resource, int enabled,
unsigned long long vme_base, unsigned long long size,
dma_addr_t buf_base, vme_address_t aspace, vme_cycle_t cycle)
{
@@ -301,25 +301,25 @@ int vme_slave_set (struct vme_resource *resource, int enabled,
int retval;
if (resource->type != VME_SLAVE) {
- printk("Not a slave resource\n");
+ printk(KERN_ERR "Not a slave resource\n");
return -EINVAL;
}
image = list_entry(resource->entry, struct vme_slave_resource, list);
if (bridge->slave_set == NULL) {
- printk("Function not supported\n");
+ printk(KERN_ERR "Function not supported\n");
return -ENOSYS;
}
- if(!(((image->address_attr & aspace) == aspace) &&
+ if (!(((image->address_attr & aspace) == aspace) &&
((image->cycle_attr & cycle) == cycle))) {
- printk("Invalid attributes\n");
+ printk(KERN_ERR "Invalid attributes\n");
return -EINVAL;
}
retval = vme_check_window(aspace, vme_base, size);
- if(retval)
+ if (retval)
return retval;
return bridge->slave_set(image, enabled, vme_base, size, buf_base,
@@ -327,7 +327,7 @@ int vme_slave_set (struct vme_resource *resource, int enabled,
}
EXPORT_SYMBOL(vme_slave_set);
-int vme_slave_get (struct vme_resource *resource, int *enabled,
+int vme_slave_get(struct vme_resource *resource, int *enabled,
unsigned long long *vme_base, unsigned long long *size,
dma_addr_t *buf_base, vme_address_t *aspace, vme_cycle_t *cycle)
{
@@ -335,14 +335,14 @@ int vme_slave_get (struct vme_resource *resource, int *enabled,
struct vme_slave_resource *image;
if (resource->type != VME_SLAVE) {
- printk("Not a slave resource\n");
+ printk(KERN_ERR "Not a slave resource\n");
return -EINVAL;
}
image = list_entry(resource->entry, struct vme_slave_resource, list);
if (bridge->slave_get == NULL) {
- printk("vme_slave_get not supported\n");
+ printk(KERN_ERR "vme_slave_get not supported\n");
return -EINVAL;
}
@@ -356,14 +356,14 @@ void vme_slave_free(struct vme_resource *resource)
struct vme_slave_resource *slave_image;
if (resource->type != VME_SLAVE) {
- printk("Not a slave resource\n");
+ printk(KERN_ERR "Not a slave resource\n");
return;
}
slave_image = list_entry(resource->entry, struct vme_slave_resource,
list);
if (slave_image == NULL) {
- printk("Can't find slave resource\n");
+ printk(KERN_ERR "Can't find slave resource\n");
return;
}
@@ -384,7 +384,7 @@ EXPORT_SYMBOL(vme_slave_free);
* Request a master image with specific attributes, return some unique
* identifier.
*/
-struct vme_resource * vme_master_request(struct device *dev,
+struct vme_resource *vme_master_request(struct device *dev,
vme_address_t address, vme_cycle_t cycle, vme_width_t dwidth)
{
struct vme_bridge *bridge;
@@ -411,7 +411,7 @@ struct vme_resource * vme_master_request(struct device *dev,
/* Find an unlocked and compatible image */
spin_lock(&(master_image->lock));
- if(((master_image->address_attr & address) == address) &&
+ if (((master_image->address_attr & address) == address) &&
((master_image->cycle_attr & cycle) == cycle) &&
((master_image->width_attr & dwidth) == dwidth) &&
(master_image->locked == 0)) {
@@ -452,7 +452,7 @@ err_bus:
}
EXPORT_SYMBOL(vme_master_request);
-int vme_master_set (struct vme_resource *resource, int enabled,
+int vme_master_set(struct vme_resource *resource, int enabled,
unsigned long long vme_base, unsigned long long size,
vme_address_t aspace, vme_cycle_t cycle, vme_width_t dwidth)
{
@@ -461,26 +461,26 @@ int vme_master_set (struct vme_resource *resource, int enabled,
int retval;
if (resource->type != VME_MASTER) {
- printk("Not a master resource\n");
+ printk(KERN_ERR "Not a master resource\n");
return -EINVAL;
}
image = list_entry(resource->entry, struct vme_master_resource, list);
if (bridge->master_set == NULL) {
- printk("vme_master_set not supported\n");
+ printk(KERN_WARNING "vme_master_set not supported\n");
return -EINVAL;
}
- if(!(((image->address_attr & aspace) == aspace) &&
+ if (!(((image->address_attr & aspace) == aspace) &&
((image->cycle_attr & cycle) == cycle) &&
((image->width_attr & dwidth) == dwidth))) {
- printk("Invalid attributes\n");
+ printk(KERN_WARNING "Invalid attributes\n");
return -EINVAL;
}
retval = vme_check_window(aspace, vme_base, size);
- if(retval)
+ if (retval)
return retval;
return bridge->master_set(image, enabled, vme_base, size, aspace,
@@ -488,7 +488,7 @@ int vme_master_set (struct vme_resource *resource, int enabled,
}
EXPORT_SYMBOL(vme_master_set);
-int vme_master_get (struct vme_resource *resource, int *enabled,
+int vme_master_get(struct vme_resource *resource, int *enabled,
unsigned long long *vme_base, unsigned long long *size,
vme_address_t *aspace, vme_cycle_t *cycle, vme_width_t *dwidth)
{
@@ -496,14 +496,14 @@ int vme_master_get (struct vme_resource *resource, int *enabled,
struct vme_master_resource *image;
if (resource->type != VME_MASTER) {
- printk("Not a master resource\n");
+ printk(KERN_ERR "Not a master resource\n");
return -EINVAL;
}
image = list_entry(resource->entry, struct vme_master_resource, list);
if (bridge->master_get == NULL) {
- printk("vme_master_set not supported\n");
+ printk(KERN_WARNING "vme_master_set not supported\n");
return -EINVAL;
}
@@ -515,7 +515,7 @@ EXPORT_SYMBOL(vme_master_get);
/*
* Read data out of VME space into a buffer.
*/
-ssize_t vme_master_read (struct vme_resource *resource, void *buf, size_t count,
+ssize_t vme_master_read(struct vme_resource *resource, void *buf, size_t count,
loff_t offset)
{
struct vme_bridge *bridge = find_bridge(resource);
@@ -523,12 +523,12 @@ ssize_t vme_master_read (struct vme_resource *resource, void *buf, size_t count,
size_t length;
if (bridge->master_read == NULL) {
- printk("Reading from resource not supported\n");
+ printk(KERN_WARNING "Reading from resource not supported\n");
return -EINVAL;
}
if (resource->type != VME_MASTER) {
- printk("Not a master resource\n");
+ printk(KERN_ERR "Not a master resource\n");
return -EINVAL;
}
@@ -537,7 +537,7 @@ ssize_t vme_master_read (struct vme_resource *resource, void *buf, size_t count,
length = vme_get_size(resource);
if (offset > length) {
- printk("Invalid Offset\n");
+ printk(KERN_WARNING "Invalid Offset\n");
return -EFAULT;
}
@@ -552,7 +552,7 @@ EXPORT_SYMBOL(vme_master_read);
/*
* Write data out to VME space from a buffer.
*/
-ssize_t vme_master_write (struct vme_resource *resource, void *buf,
+ssize_t vme_master_write(struct vme_resource *resource, void *buf,
size_t count, loff_t offset)
{
struct vme_bridge *bridge = find_bridge(resource);
@@ -560,12 +560,12 @@ ssize_t vme_master_write (struct vme_resource *resource, void *buf,
size_t length;
if (bridge->master_write == NULL) {
- printk("Writing to resource not supported\n");
+ printk(KERN_WARNING "Writing to resource not supported\n");
return -EINVAL;
}
if (resource->type != VME_MASTER) {
- printk("Not a master resource\n");
+ printk(KERN_ERR "Not a master resource\n");
return -EINVAL;
}
@@ -574,7 +574,7 @@ ssize_t vme_master_write (struct vme_resource *resource, void *buf,
length = vme_get_size(resource);
if (offset > length) {
- printk("Invalid Offset\n");
+ printk(KERN_WARNING "Invalid Offset\n");
return -EFAULT;
}
@@ -588,19 +588,19 @@ EXPORT_SYMBOL(vme_master_write);
/*
* Perform RMW cycle to provided location.
*/
-unsigned int vme_master_rmw (struct vme_resource *resource, unsigned int mask,
+unsigned int vme_master_rmw(struct vme_resource *resource, unsigned int mask,
unsigned int compare, unsigned int swap, loff_t offset)
{
struct vme_bridge *bridge = find_bridge(resource);
struct vme_master_resource *image;
if (bridge->master_rmw == NULL) {
- printk("Writing to resource not supported\n");
+ printk(KERN_WARNING "Writing to resource not supported\n");
return -EINVAL;
}
if (resource->type != VME_MASTER) {
- printk("Not a master resource\n");
+ printk(KERN_ERR "Not a master resource\n");
return -EINVAL;
}
@@ -615,14 +615,14 @@ void vme_master_free(struct vme_resource *resource)
struct vme_master_resource *master_image;
if (resource->type != VME_MASTER) {
- printk("Not a master resource\n");
+ printk(KERN_ERR "Not a master resource\n");
return;
}
master_image = list_entry(resource->entry, struct vme_master_resource,
list);
if (master_image == NULL) {
- printk("Can't find master resource\n");
+ printk(KERN_ERR "Can't find master resource\n");
return;
}
@@ -643,7 +643,7 @@ EXPORT_SYMBOL(vme_master_free);
* Request a DMA controller with specific attributes, return some unique
* identifier.
*/
-struct vme_resource *vme_dma_request(struct device *dev)
+struct vme_resource *vme_dma_request(struct device *dev, vme_dma_route_t route)
{
struct vme_bridge *bridge;
struct list_head *dma_pos = NULL;
@@ -666,13 +666,15 @@ struct vme_resource *vme_dma_request(struct device *dev)
struct vme_dma_resource, list);
if (dma_ctrlr == NULL) {
- printk("Registered NULL DMA resource\n");
+ printk(KERN_ERR "Registered NULL DMA resource\n");
continue;
}
- /* Find an unlocked controller */
+ /* Find an unlocked and compatible controller */
mutex_lock(&(dma_ctrlr->mtx));
- if(dma_ctrlr->locked == 0) {
+ if (((dma_ctrlr->route_attr & route) == route) &&
+ (dma_ctrlr->locked == 0)) {
+
dma_ctrlr->locked = 1;
mutex_unlock(&(dma_ctrlr->mtx));
allocated_ctrlr = dma_ctrlr;
@@ -715,16 +717,15 @@ struct vme_dma_list *vme_new_dma_list(struct vme_resource *resource)
struct vme_dma_list *dma_list;
if (resource->type != VME_DMA) {
- printk("Not a DMA resource\n");
+ printk(KERN_ERR "Not a DMA resource\n");
return NULL;
}
ctrlr = list_entry(resource->entry, struct vme_dma_resource, list);
- dma_list = (struct vme_dma_list *)kmalloc(
- sizeof(struct vme_dma_list), GFP_KERNEL);
- if(dma_list == NULL) {
- printk("Unable to allocate memory for new dma list\n");
+ dma_list = kmalloc(sizeof(struct vme_dma_list), GFP_KERNEL);
+ if (dma_list == NULL) {
+ printk(KERN_ERR "Unable to allocate memory for new dma list\n");
return NULL;
}
INIT_LIST_HEAD(&(dma_list->entries));
@@ -744,17 +745,17 @@ struct vme_dma_attr *vme_dma_pattern_attribute(u32 pattern,
struct vme_dma_attr *attributes;
struct vme_dma_pattern *pattern_attr;
- attributes = (struct vme_dma_attr *)kmalloc(
- sizeof(struct vme_dma_attr), GFP_KERNEL);
- if(attributes == NULL) {
- printk("Unable to allocate memory for attributes structure\n");
+ attributes = kmalloc(sizeof(struct vme_dma_attr), GFP_KERNEL);
+ if (attributes == NULL) {
+ printk(KERN_ERR "Unable to allocate memory for attributes "
+ "structure\n");
goto err_attr;
}
- pattern_attr = (struct vme_dma_pattern *)kmalloc(
- sizeof(struct vme_dma_pattern), GFP_KERNEL);
- if(pattern_attr == NULL) {
- printk("Unable to allocate memory for pattern attributes\n");
+ pattern_attr = kmalloc(sizeof(struct vme_dma_pattern), GFP_KERNEL);
+ if (pattern_attr == NULL) {
+ printk(KERN_ERR "Unable to allocate memory for pattern "
+ "attributes\n");
goto err_pat;
}
@@ -784,17 +785,17 @@ struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t address)
/* XXX Run some sanity checks here */
- attributes = (struct vme_dma_attr *)kmalloc(
- sizeof(struct vme_dma_attr), GFP_KERNEL);
- if(attributes == NULL) {
- printk("Unable to allocate memory for attributes structure\n");
+ attributes = kmalloc(sizeof(struct vme_dma_attr), GFP_KERNEL);
+ if (attributes == NULL) {
+ printk(KERN_ERR "Unable to allocate memory for attributes "
+ "structure\n");
goto err_attr;
}
- pci_attr = (struct vme_dma_pci *)kmalloc(sizeof(struct vme_dma_pci),
- GFP_KERNEL);
- if(pci_attr == NULL) {
- printk("Unable to allocate memory for pci attributes\n");
+ pci_attr = kmalloc(sizeof(struct vme_dma_pci), GFP_KERNEL);
+ if (pci_attr == NULL) {
+ printk(KERN_ERR "Unable to allocate memory for pci "
+ "attributes\n");
goto err_pci;
}
@@ -824,19 +825,18 @@ struct vme_dma_attr *vme_dma_vme_attribute(unsigned long long address,
struct vme_dma_attr *attributes;
struct vme_dma_vme *vme_attr;
- /* XXX Run some sanity checks here */
-
- attributes = (struct vme_dma_attr *)kmalloc(
+ attributes = kmalloc(
sizeof(struct vme_dma_attr), GFP_KERNEL);
- if(attributes == NULL) {
- printk("Unable to allocate memory for attributes structure\n");
+ if (attributes == NULL) {
+ printk(KERN_ERR "Unable to allocate memory for attributes "
+ "structure\n");
goto err_attr;
}
- vme_attr = (struct vme_dma_vme *)kmalloc(sizeof(struct vme_dma_vme),
- GFP_KERNEL);
- if(vme_attr == NULL) {
- printk("Unable to allocate memory for vme attributes\n");
+ vme_attr = kmalloc(sizeof(struct vme_dma_vme), GFP_KERNEL);
+ if (vme_attr == NULL) {
+ printk(KERN_ERR "Unable to allocate memory for vme "
+ "attributes\n");
goto err_vme;
}
@@ -875,12 +875,12 @@ int vme_dma_list_add(struct vme_dma_list *list, struct vme_dma_attr *src,
int retval;
if (bridge->dma_list_add == NULL) {
- printk("Link List DMA generation not supported\n");
+ printk(KERN_WARNING "Link List DMA generation not supported\n");
return -EINVAL;
}
if (!mutex_trylock(&(list->mtx))) {
- printk("Link List already submitted\n");
+ printk(KERN_ERR "Link List already submitted\n");
return -EINVAL;
}
@@ -898,7 +898,7 @@ int vme_dma_list_exec(struct vme_dma_list *list)
int retval;
if (bridge->dma_list_exec == NULL) {
- printk("Link List DMA execution not supported\n");
+ printk(KERN_ERR "Link List DMA execution not supported\n");
return -EINVAL;
}
@@ -918,12 +918,12 @@ int vme_dma_list_free(struct vme_dma_list *list)
int retval;
if (bridge->dma_list_empty == NULL) {
- printk("Emptying of Link Lists not supported\n");
+ printk(KERN_WARNING "Emptying of Link Lists not supported\n");
return -EINVAL;
}
if (!mutex_trylock(&(list->mtx))) {
- printk("Link List in use\n");
+ printk(KERN_ERR "Link List in use\n");
return -EINVAL;
}
@@ -933,7 +933,7 @@ int vme_dma_list_free(struct vme_dma_list *list)
*/
retval = bridge->dma_list_empty(list);
if (retval) {
- printk("Unable to empty link-list entries\n");
+ printk(KERN_ERR "Unable to empty link-list entries\n");
mutex_unlock(&(list->mtx));
return retval;
}
@@ -949,19 +949,19 @@ int vme_dma_free(struct vme_resource *resource)
struct vme_dma_resource *ctrlr;
if (resource->type != VME_DMA) {
- printk("Not a DMA resource\n");
+ printk(KERN_ERR "Not a DMA resource\n");
return -EINVAL;
}
ctrlr = list_entry(resource->entry, struct vme_dma_resource, list);
if (!mutex_trylock(&(ctrlr->mtx))) {
- printk("Resource busy, can't free\n");
+ printk(KERN_ERR "Resource busy, can't free\n");
return -EBUSY;
}
if (!(list_empty(&(ctrlr->pending)) && list_empty(&(ctrlr->running)))) {
- printk("Resource still processing transfers\n");
+ printk(KERN_WARNING "Resource still processing transfers\n");
mutex_unlock(&(ctrlr->mtx));
return -EBUSY;
}
@@ -991,7 +991,7 @@ void vme_irq_handler(struct vme_bridge *bridge, int level, int statid)
EXPORT_SYMBOL(vme_irq_handler);
int vme_irq_request(struct device *dev, int level, int statid,
- void (*callback)(int level, int vector, void *priv_data),
+ void (*callback)(int, int, void *),
void *priv_data)
{
struct vme_bridge *bridge;
@@ -1002,7 +1002,7 @@ int vme_irq_request(struct device *dev, int level, int statid,
return -EINVAL;
}
- if((level < 1) || (level > 7)) {
+ if ((level < 1) || (level > 7)) {
printk(KERN_ERR "Invalid interrupt level\n");
return -EINVAL;
}
@@ -1025,7 +1025,7 @@ int vme_irq_request(struct device *dev, int level, int statid,
bridge->irq[level - 1].callback[statid].func = callback;
/* Enable IRQ level */
- bridge->irq_set(level, 1, 1);
+ bridge->irq_set(bridge, level, 1, 1);
mutex_unlock(&(bridge->irq_mtx));
@@ -1043,7 +1043,7 @@ void vme_irq_free(struct device *dev, int level, int statid)
return;
}
- if((level < 1) || (level > 7)) {
+ if ((level < 1) || (level > 7)) {
printk(KERN_ERR "Invalid interrupt level\n");
return;
}
@@ -1059,7 +1059,7 @@ void vme_irq_free(struct device *dev, int level, int statid)
/* Disable IRQ level if no more interrupts attached at this level*/
if (bridge->irq[level - 1].count == 0)
- bridge->irq_set(level, 0, 1);
+ bridge->irq_set(bridge, level, 0, 1);
bridge->irq[level - 1].callback[statid].func = NULL;
bridge->irq[level - 1].callback[statid].priv_data = NULL;
@@ -1078,17 +1078,17 @@ int vme_irq_generate(struct device *dev, int level, int statid)
return -EINVAL;
}
- if((level < 1) || (level > 7)) {
+ if ((level < 1) || (level > 7)) {
printk(KERN_WARNING "Invalid interrupt level\n");
return -EINVAL;
}
if (bridge->irq_generate == NULL) {
- printk("Interrupt generation not supported\n");
+ printk(KERN_WARNING "Interrupt generation not supported\n");
return -EINVAL;
}
- return bridge->irq_generate(level, statid);
+ return bridge->irq_generate(bridge, level, statid);
}
EXPORT_SYMBOL(vme_irq_generate);
@@ -1189,8 +1189,6 @@ int vme_lm_set(struct vme_resource *resource, unsigned long long lm_base,
return -EINVAL;
}
- /* XXX Check parameters */
-
return bridge->lm_set(lm, lm_base, aspace, cycle);
}
EXPORT_SYMBOL(vme_lm_set);
@@ -1297,11 +1295,11 @@ int vme_slot_get(struct device *bus)
}
if (bridge->slot_get == NULL) {
- printk("vme_slot_get not supported\n");
+ printk(KERN_WARNING "vme_slot_get not supported\n");
return -EINVAL;
}
- return bridge->slot_get();
+ return bridge->slot_get(bridge);
}
EXPORT_SYMBOL(vme_slot_get);
@@ -1331,7 +1329,7 @@ static void vme_free_bus_num(int bus)
mutex_unlock(&vme_bus_num_mtx);
}
-int vme_register_bridge (struct vme_bridge *bridge)
+int vme_register_bridge(struct vme_bridge *bridge)
{
struct device *dev;
int retval;
@@ -1358,7 +1356,7 @@ int vme_register_bridge (struct vme_bridge *bridge)
dev_set_name(dev, "vme-%x.%x", bridge->num, i + 1);
retval = device_register(dev);
- if(retval)
+ if (retval)
goto err_reg;
}
@@ -1375,7 +1373,7 @@ err_reg:
}
EXPORT_SYMBOL(vme_register_bridge);
-void vme_unregister_bridge (struct vme_bridge *bridge)
+void vme_unregister_bridge(struct vme_bridge *bridge)
{
int i;
struct device *dev;
@@ -1392,7 +1390,7 @@ EXPORT_SYMBOL(vme_unregister_bridge);
/* - Driver Registration --------------------------------------------------- */
-int vme_register_driver (struct vme_driver *drv)
+int vme_register_driver(struct vme_driver *drv)
{
drv->driver.name = drv->name;
drv->driver.bus = &vme_bus_type;
@@ -1401,7 +1399,7 @@ int vme_register_driver (struct vme_driver *drv)
}
EXPORT_SYMBOL(vme_register_driver);
-void vme_unregister_driver (struct vme_driver *drv)
+void vme_unregister_driver(struct vme_driver *drv)
{
driver_unregister(&drv->driver);
}
@@ -1418,10 +1416,10 @@ int vme_calc_slot(struct device *dev)
/* Determine slot number */
num = 0;
- while(num < VME_SLOTS_MAX) {
- if(&(bridge->dev[num]) == dev) {
+ while (num < VME_SLOTS_MAX) {
+ if (&(bridge->dev[num]) == dev)
break;
- }
+
num++;
}
if (num == VME_SLOTS_MAX) {
@@ -1437,8 +1435,8 @@ err_dev:
static struct vme_driver *dev_to_vme_driver(struct device *dev)
{
- if(dev->driver == NULL)
- printk("Bugger dev->driver is NULL\n");
+ if (dev->driver == NULL)
+ printk(KERN_ERR "Bugger dev->driver is NULL\n");
return container_of(dev->driver, struct vme_driver, driver);
}
@@ -1462,7 +1460,7 @@ static int vme_bus_match(struct device *dev, struct device_driver *drv)
}
i = 0;
- while((driver->bind_table[i].bus != 0) ||
+ while ((driver->bind_table[i].bus != 0) ||
(driver->bind_table[i].slot != 0)) {
if (bridge->num == driver->bind_table[i].bus) {
@@ -1493,9 +1491,8 @@ static int vme_bus_probe(struct device *dev)
driver = dev_to_vme_driver(dev);
bridge = dev_to_bridge(dev);
- if(driver->probe != NULL) {
+ if (driver->probe != NULL)
retval = driver->probe(dev, bridge->num, vme_calc_slot(dev));
- }
return retval;
}
@@ -1509,9 +1506,8 @@ static int vme_bus_remove(struct device *dev)
driver = dev_to_vme_driver(dev);
bridge = dev_to_bridge(dev);
- if(driver->remove != NULL) {
+ if (driver->remove != NULL)
retval = driver->remove(dev, bridge->num, vme_calc_slot(dev));
- }
return retval;
}
@@ -1524,18 +1520,18 @@ struct bus_type vme_bus_type = {
};
EXPORT_SYMBOL(vme_bus_type);
-static int __init vme_init (void)
+static int __init vme_init(void)
{
return bus_register(&vme_bus_type);
}
-static void __exit vme_exit (void)
+static void __exit vme_exit(void)
{
bus_unregister(&vme_bus_type);
}
MODULE_DESCRIPTION("VME bridge driver framework");
-MODULE_AUTHOR("Martyn Welch <martyn.welch@gefanuc.com");
+MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com");
MODULE_LICENSE("GPL");
module_init(vme_init);
diff --git a/drivers/staging/vme/vme.h b/drivers/staging/vme/vme.h
index 97dc22e34ca..48768ca97e1 100644
--- a/drivers/staging/vme/vme.h
+++ b/drivers/staging/vme/vme.h
@@ -68,6 +68,14 @@ typedef u32 vme_pattern_t;
#define VME_DMA_PATTERN_WORD (1<<1)
#define VME_DMA_PATTERN_INCREMENT (1<<2)
+typedef u32 vme_dma_route_t;
+#define VME_DMA_VME_TO_MEM (1<<0)
+#define VME_DMA_MEM_TO_VME (1<<1)
+#define VME_DMA_VME_TO_VME (1<<2)
+#define VME_DMA_MEM_TO_MEM (1<<3)
+#define VME_DMA_PATTERN_TO_VME (1<<4)
+#define VME_DMA_PATTERN_TO_MEM (1<<5)
+
struct vme_dma_attr {
vme_dma_t type;
void *private;
@@ -98,32 +106,33 @@ struct vme_driver {
struct device_driver driver;
};
-void * vme_alloc_consistent(struct vme_resource *, size_t, dma_addr_t *);
+void *vme_alloc_consistent(struct vme_resource *, size_t, dma_addr_t *);
void vme_free_consistent(struct vme_resource *, size_t, void *,
dma_addr_t);
size_t vme_get_size(struct vme_resource *);
-struct vme_resource * vme_slave_request(struct device *, vme_address_t, vme_cycle_t);
-int vme_slave_set (struct vme_resource *, int, unsigned long long,
+struct vme_resource *vme_slave_request(struct device *, vme_address_t,
+ vme_cycle_t);
+int vme_slave_set(struct vme_resource *, int, unsigned long long,
unsigned long long, dma_addr_t, vme_address_t, vme_cycle_t);
-int vme_slave_get (struct vme_resource *, int *, unsigned long long *,
+int vme_slave_get(struct vme_resource *, int *, unsigned long long *,
unsigned long long *, dma_addr_t *, vme_address_t *, vme_cycle_t *);
void vme_slave_free(struct vme_resource *);
-struct vme_resource * vme_master_request(struct device *, vme_address_t, vme_cycle_t,
- vme_width_t);
-int vme_master_set (struct vme_resource *, int, unsigned long long,
+struct vme_resource *vme_master_request(struct device *, vme_address_t,
+ vme_cycle_t, vme_width_t);
+int vme_master_set(struct vme_resource *, int, unsigned long long,
unsigned long long, vme_address_t, vme_cycle_t, vme_width_t);
-int vme_master_get (struct vme_resource *, int *, unsigned long long *,
+int vme_master_get(struct vme_resource *, int *, unsigned long long *,
unsigned long long *, vme_address_t *, vme_cycle_t *, vme_width_t *);
ssize_t vme_master_read(struct vme_resource *, void *, size_t, loff_t);
ssize_t vme_master_write(struct vme_resource *, void *, size_t, loff_t);
-unsigned int vme_master_rmw (struct vme_resource *, unsigned int, unsigned int,
+unsigned int vme_master_rmw(struct vme_resource *, unsigned int, unsigned int,
unsigned int, loff_t);
void vme_master_free(struct vme_resource *);
-struct vme_resource *vme_dma_request(struct device *);
+struct vme_resource *vme_dma_request(struct device *, vme_dma_route_t);
struct vme_dma_list *vme_new_dma_list(struct vme_resource *);
struct vme_dma_attr *vme_dma_pattern_attribute(u32, vme_pattern_t);
struct vme_dma_attr *vme_dma_pci_attribute(dma_addr_t);
@@ -153,8 +162,8 @@ void vme_lm_free(struct vme_resource *);
int vme_slot_get(struct device *);
-int vme_register_driver (struct vme_driver *);
-void vme_unregister_driver (struct vme_driver *);
+int vme_register_driver(struct vme_driver *);
+void vme_unregister_driver(struct vme_driver *);
#endif /* _VME_H_ */
diff --git a/drivers/staging/vme/vme_api.txt b/drivers/staging/vme/vme_api.txt
index a5c1b1cd5fc..a910a0c4388 100644
--- a/drivers/staging/vme/vme_api.txt
+++ b/drivers/staging/vme/vme_api.txt
@@ -77,16 +77,21 @@ driver in question:
struct vme_resource * vme_slave_request(struct device *dev,
vme_address_t aspace, vme_cycle_t cycle);
- struct vme_resource *vme_dma_request(struct device *dev);
+ struct vme_resource *vme_dma_request(struct device *dev,
+ vme_dma_route_t route);
For slave windows these attributes are split into those of type 'vme_address_t'
-and 'vme_cycle_t'. Master windows add a further set of attributes 'vme_cycle_t'.
-These attributes are defined as bitmasks and as such any combination of the
-attributes can be requested for a single window, the core will assign a window
-that meets the requirements, returning a pointer of type vme_resource that
-should be used to identify the allocated resource when it is used. If an
-unallocated window fitting the requirements can not be found a NULL pointer will
-be returned.
+and 'vme_cycle_t'. Master windows add a further set of attributes
+'vme_cycle_t'. These attributes are defined as bitmasks and as such any
+combination of the attributes can be requested for a single window, the core
+will assign a window that meets the requirements, returning a pointer of type
+vme_resource that should be used to identify the allocated resource when it is
+used. For DMA controllers, the request function requires the potential
+direction of any transfers to be provided in the route attributes. This is
+typically VME-to-MEM and/or MEM-to-VME, though some hardware can support
+VME-to-VME and MEM-to-MEM transfers as well as test pattern generation. If an
+unallocated window fitting the requirements can not be found a NULL pointer
+will be returned.
Functions are also provided to free window allocations once they are no longer
required. These functions should be passed the pointer to the resource provided
@@ -237,6 +242,12 @@ covered under "Transfer Attributes"):
struct vme_dma_attr *src, struct vme_dma_attr *dest,
size_t count);
+NOTE: The detailed attributes of the transfers source and destination
+ are not checked until an entry is added to a DMA list, the request
+ for a DMA channel purely checks the directions in which the
+ controller is expected to transfer data. As a result it is
+ possible for this call to return an error, for example if the
+ source or destination is in an unsupported VME address space.
Transfer Attributes
-------------------
diff --git a/drivers/staging/vme/vme_bridge.h b/drivers/staging/vme/vme_bridge.h
index 851fa92559f..b653ec02e1f 100644
--- a/drivers/staging/vme/vme_bridge.h
+++ b/drivers/staging/vme/vme_bridge.h
@@ -19,7 +19,7 @@ struct vme_master_resource {
vme_address_t address_attr;
vme_cycle_t cycle_attr;
vme_width_t width_attr;
- struct resource pci_resource; /* XXX Rename to be bus agnostic */
+ struct resource bus_resource;
void *kern_base;
};
@@ -64,6 +64,7 @@ struct vme_dma_resource {
int number;
struct list_head pending;
struct list_head running;
+ vme_dma_route_t route_attr;
};
struct vme_lm_resource {
@@ -101,7 +102,7 @@ struct vme_irq {
* Currently we assume that all chips are PCI-based
*/
struct vme_bridge {
- char name[VMENAMSIZ];
+ char name[VMENAMSIZ];
int num;
struct list_head master_resources;
struct list_head slave_resources;
@@ -112,7 +113,7 @@ struct vme_bridge {
/* Bridge Info - XXX Move to private structure? */
struct device *parent; /* Generic device struct (pdev->dev for PCI) */
- void * base; /* Base Address of device registers */
+ void *driver_priv; /* Private pointer for the bridge driver */
struct device dev[VME_SLOTS_MAX]; /* Device registered with
* device model on VME bus
@@ -151,8 +152,8 @@ struct vme_bridge {
int (*dma_list_empty) (struct vme_dma_list *);
/* Interrupt Functions */
- void (*irq_set) (int, int, int);
- int (*irq_generate) (int, int);
+ void (*irq_set) (struct vme_bridge *, int, int, int);
+ int (*irq_generate) (struct vme_bridge *, int, int);
/* Location monitor functions */
int (*lm_set) (struct vme_lm_resource *, unsigned long long,
@@ -163,102 +164,12 @@ struct vme_bridge {
int (*lm_detach) (struct vme_lm_resource *, int);
/* CR/CSR space functions */
- int (*slot_get) (void);
- /* Use standard master read and write functions to access CR/CSR */
-
-#if 0
- int (*set_prefetch) (void);
- int (*get_prefetch) (void);
- int (*set_arbiter) (void);
- int (*get_arbiter) (void);
- int (*set_requestor) (void);
- int (*get_requestor) (void);
-#endif
+ int (*slot_get) (struct vme_bridge *);
};
void vme_irq_handler(struct vme_bridge *, int, int);
-int vme_register_bridge (struct vme_bridge *);
-void vme_unregister_bridge (struct vme_bridge *);
+int vme_register_bridge(struct vme_bridge *);
+void vme_unregister_bridge(struct vme_bridge *);
#endif /* _VME_BRIDGE_H_ */
-
-#if 0
-/*
- * VMEbus GET INFO Arg Structure
- */
-struct vmeInfoCfg {
- int vmeSlotNum; /* VME slot number of interest */
- int boardResponded; /* Board responded */
- char sysConFlag; /* System controller flag */
- int vmeControllerID; /* Vendor/device ID of VME bridge */
- int vmeControllerRev; /* Revision of VME bridge */
- char osName[8]; /* Name of OS e.g. "Linux" */
- int vmeSharedDataValid; /* Validity of data struct */
- int vmeDriverRev; /* Revision of VME driver */
- unsigned int vmeAddrHi[8]; /* Address on VME bus */
- unsigned int vmeAddrLo[8]; /* Address on VME bus */
- unsigned int vmeSize[8]; /* Size on VME bus */
- unsigned int vmeAm[8]; /* Address modifier on VME bus */
- int reserved; /* For future use */
-};
-typedef struct vmeInfoCfg vmeInfoCfg_t;
-
-/*
- * VMEbus Requester Arg Structure
- */
-struct vmeRequesterCfg {
- int requestLevel; /* Requester Bus Request Level */
- char fairMode; /* Requester Fairness Mode Indicator */
- int releaseMode; /* Requester Bus Release Mode */
- int timeonTimeoutTimer; /* Master Time-on Time-out Timer */
- int timeoffTimeoutTimer; /* Master Time-off Time-out Timer */
- int reserved; /* For future use */
-};
-typedef struct vmeRequesterCfg vmeRequesterCfg_t;
-
-/*
- * VMEbus Arbiter Arg Structure
- */
-struct vmeArbiterCfg {
- vme_arbitration_t arbiterMode; /* Arbitration Scheduling Algorithm */
- char arbiterTimeoutFlag; /* Arbiter Time-out Timer Indicator */
- int globalTimeoutTimer; /* VMEbus Global Time-out Timer */
- char noEarlyReleaseFlag; /* No Early Release on BBUSY */
- int reserved; /* For future use */
-};
-typedef struct vmeArbiterCfg vmeArbiterCfg_t;
-
-
-/*
- * VMEbus RMW Configuration Data
- */
-struct vmeRmwCfg {
- unsigned int targetAddrU; /* VME Address (Upper) to trigger RMW cycle */
- unsigned int targetAddr; /* VME Address (Lower) to trigger RMW cycle */
- vme_address_t addrSpace; /* VME Address Space */
- int enableMask; /* Bit mask defining the bits of interest */
- int compareData; /* Data to be compared with the data read */
- int swapData; /* Data written to the VMEbus on success */
- int maxAttempts; /* Maximum times to try */
- int numAttempts; /* Number of attempts before success */
- int reserved; /* For future use */
-
-};
-typedef struct vmeRmwCfg vmeRmwCfg_t;
-
-/*
- * VMEbus Location Monitor Arg Structure
- */
-struct vmeLmCfg {
- unsigned int addrU; /* Location Monitor Address upper */
- unsigned int addr; /* Location Monitor Address lower */
- vme_address_t addrSpace; /* Address Space */
- int userAccessType; /* User/Supervisor Access Type */
- int dataAccessType; /* Data/Program Access Type */
- int lmWait; /* Time to wait for access */
- int lmEvents; /* Lm event mask */
- int reserved; /* For future use */
-};
-typedef struct vmeLmCfg vmeLmCfg_t;
-#endif
diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c
index db786142717..bf4fd49709d 100644
--- a/drivers/staging/vt6655/card.c
+++ b/drivers/staging/vt6655/card.c
@@ -2788,16 +2788,18 @@ void CARDvUpdateBasicTopRate (PVOID pDeviceHandler)
//Determines the highest basic rate.
for (ii = RATE_54M; ii >= RATE_6M; ii --) {
- if ( (pDevice->wBasicRate) & ((WORD)(1<<ii)) )
+ if ( (pDevice->wBasicRate) & ((WORD)(1<<ii)) ) {
byTopOFDM = ii;
break;
+ }
}
pDevice->byTopOFDMBasicRate = byTopOFDM;
for (ii = RATE_11M;; ii --) {
- if ( (pDevice->wBasicRate) & ((WORD)(1<<ii)) )
+ if ( (pDevice->wBasicRate) & ((WORD)(1<<ii)) ) {
byTopCCK = ii;
break;
+ }
if (ii == RATE_1M)
break;
}
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index 0dadb765fec..1d643653a7e 100644
--- a/drivers/staging/vt6655/device_main.c
+++ b/drivers/staging/vt6655/device_main.c
@@ -1105,10 +1105,7 @@ static void device_print_info(PSDevice pDevice)
struct net_device* dev=pDevice->dev;
DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: %s\n",dev->name, get_chip_name(pDevice->chip_id));
- DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: MAC=%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
- dev->name,
- dev->dev_addr[0],dev->dev_addr[1],dev->dev_addr[2],
- dev->dev_addr[3],dev->dev_addr[4],dev->dev_addr[5]);
+ DBG_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: MAC=%pM", dev->name, dev->dev_addr);
#ifdef IO_MAP
DBG_PRT(MSG_LEVEL_INFO, KERN_INFO" IO=0x%lx ",(ULONG) pDevice->ioaddr);
DBG_PRT(MSG_LEVEL_INFO, KERN_INFO" IRQ=%d \n", pDevice->dev->irq);
diff --git a/drivers/staging/vt6655/iwctl.c b/drivers/staging/vt6655/iwctl.c
index 108830ff3b3..78b49830a25 100644
--- a/drivers/staging/vt6655/iwctl.c
+++ b/drivers/staging/vt6655/iwctl.c
@@ -1472,7 +1472,7 @@ if((wrq->flags & IW_ENCODE_DISABLED)==0){
if ( index < 4 ) {
pDevice->byKeyIndex = index;
}
- else if(!wrq->flags & IW_ENCODE_MODE) {
+ else if(!(wrq->flags & IW_ENCODE_MODE)) {
rc = -EINVAL;
return rc;
}
diff --git a/drivers/staging/winbond/core.h b/drivers/staging/winbond/core.h
index 7d4bd5e8f69..0a2060bf4f9 100644
--- a/drivers/staging/winbond/core.h
+++ b/drivers/staging/winbond/core.h
@@ -14,7 +14,7 @@
struct wbsoft_priv {
u32 adapterIndex; // 20060703.4 Add for using padapterContext global adapter point
- WB_LOCALDESCRIPT sLocalPara; // Myself connected parameters
+ struct wb_local_para sLocalPara; // Myself connected parameters
MLME_FRAME sMlmeFrame; // connect to peerSTA parameters
diff --git a/drivers/staging/winbond/localpara.h b/drivers/staging/winbond/localpara.h
index 5626a76d69a..fcf6a0442dc 100644
--- a/drivers/staging/winbond/localpara.h
+++ b/drivers/staging/winbond/localpara.h
@@ -110,33 +110,20 @@
// 20061108 WPS IE buffer
#define MAX_IE_APPEND_SIZE 256 + 4 // Due to [E id][Length][OUI][Data] may 257 bytes
-typedef struct _EVENTLOG
-{
- u16 Count; //Total count from start
- u16 index; //Buffer index, 0 ~ 63
- u32 EventValue[64]; //BYTE 3~2 : count, BYTE 1 : Event, BYTE 0 : reason
-} Event_Log, *pEvent_Log;
-
-typedef struct _ChanInfo
+struct chan_info
{
u8 band;
u8 ChanNo;
-} ChanInfo, *pChanInfo;
+};
-typedef struct _CHAN_LIST
-{
- u16 Count;
- ChanInfo Channel[50]; // 100B
-} CHAN_LIST, *psCHAN_LIST;
-
-typedef struct _RadioOff
+struct radio_off
{
u8 boHwRadioOff;
u8 boSwRadioOff;
-} RadioOff, *psRadioOff;
+};
//===========================================================================
-typedef struct LOCAL_PARA
+struct wb_local_para
{
u8 PermanentAddress[ MAC_ADDR_LENGTH + 2 ]; // read from EPROM, manufacture set for each NetCard
u8 ThisMacAddress[ MAC_ADDR_LENGTH + 2 ]; // the driver will use actually.
@@ -186,7 +173,7 @@ typedef struct LOCAL_PARA
u16 ListenInterval; // The listen interval when SME invoking MLME_
// (Re)Associate_Request().
- RadioOff RadioOffStatus;
+ struct radio_off RadioOffStatus;
u8 Reserved0[2];
u8 boMsRadioOff; // Ndis demands to be true when set Disassoc. OID and be false when set SSID OID.
@@ -196,7 +183,7 @@ typedef struct LOCAL_PARA
u8 RoamStatus;
u8 reserved7[3];
- ChanInfo CurrentChan; //Current channel no. and channel band. It may be changed by scanning.
+ struct chan_info CurrentChan; //Current channel no. and channel band. It may be changed by scanning.
u8 boHandover; // Roaming, Hnadover to other AP.
u8 boCCAbusy;
@@ -253,19 +240,16 @@ typedef struct LOCAL_PARA
u32 _dot11WEPUndecryptableCount;
u32 _dot11FrameDuplicateCount;
- ChanInfo IbssChanSetting; // 2B. Start IBSS Channel setting by registry or WWU.
+ struct chan_info IbssChanSetting; // 2B. Start IBSS Channel setting by registry or WWU.
u8 reserved_5[2]; //It may not be used after considering RF type,
//region and modulation type.
- CHAN_LIST sSupportChanList; // 86B. It will be obtained according to RF type and region
u8 reserved_6[2]; //two variables are for wep key error detection added by ws 02/02/04
u32 bWepKeyError;
u32 bToSelfPacketReceived;
u32 WepKeyDetectTimerCount;
- Event_Log EventLog;
-
u16 SignalLostTh;
u16 SignalRoamTh;
@@ -274,6 +258,6 @@ typedef struct LOCAL_PARA
u16 IE_Append_size;
u16 reserved_7;
-} WB_LOCALDESCRIPT, *PWB_LOCALDESCRIPT;
+};
#endif
diff --git a/drivers/staging/winbond/mds_f.h b/drivers/staging/winbond/mds_f.h
index ab1ea535f7d..e09dd4b879d 100644
--- a/drivers/staging/winbond/mds_f.h
+++ b/drivers/staging/winbond/mds_f.h
@@ -11,9 +11,6 @@ void Mds_SendComplete( struct wbsoft_priv *adapter, PT02_DESCRIPTOR pT02 );
void Mds_MpduProcess( struct wbsoft_priv *adapter, struct wb35_descriptor *pRxDes );
extern void DataDmp(u8 *pdata, u32 len, u32 offset);
-// For Asynchronous indicating. The routine collocates with USB.
-void Mds_MsduProcess( struct wbsoft_priv *adapter, PRXLAYER1 pRxLayer1, u8 SlotIndex);
-
// For data frame sending 20060802
u16 MDS_GetPacketSize( struct wbsoft_priv *adapter );
void MDS_GetNextPacket( struct wbsoft_priv *adapter, struct wb35_descriptor *pDes );
diff --git a/drivers/staging/winbond/mds_s.h b/drivers/staging/winbond/mds_s.h
index e8e13bde474..217ff0819a9 100644
--- a/drivers/staging/winbond/mds_s.h
+++ b/drivers/staging/winbond/mds_s.h
@@ -133,32 +133,4 @@ struct wb35_mds {
};
-//
-// Reveive Layer 1 Format.
-//----------------------------
-typedef struct _RXLAYER1
-{
- u16 SequenceNumber; // The sequence number of the last received packet.
- u16 BufferTotalSize;
-
- u32 InUsed;
- u32 DecryptionMethod; // The desired defragment number of the next incoming packet.
-
- u8 DeFragmentNumber;
- u8 FrameType;
- u8 TypeEncapsulated;
- u8 BufferNumber;
-
- u32 FirstFrameArrivedTime;
-
- u8 LastFrameType; // 20061004 for fix intel 3945 's bug
- u8 RESERVED[3]; //@@ anson
-
- /////////////////////////////////////////////////////////////////////////////////////////////
- // For brand-new Rx system
- u8 ReservedBuffer[ 2400 ];//If Buffer ID is reserved one, it must copy the data into this area
- u8 *ReservedBufferPoint;// Point to the next availabe address of reserved buffer
-
-}RXLAYER1, * PRXLAYER1;
-
#endif
diff --git a/drivers/staging/winbond/mlme_s.h b/drivers/staging/winbond/mlme_s.h
index ea12684a2b1..1217a1c025e 100644
--- a/drivers/staging/winbond/mlme_s.h
+++ b/drivers/staging/winbond/mlme_s.h
@@ -165,14 +165,6 @@ typedef struct _AUTHREQ {
} MLME_AUTHREQ_PARA, *psMLME_AUTHREQ_PARA;
-struct _Reason_Code {
-
- u8 peerMACaddr[MAC_ADDR_LENGTH];
- u16 wReasonCode;
-};
-typedef struct _Reason_Code MLME_DEAUTHREQ_PARA, *psMLME_DEAUTHREQ_PARA;
-typedef struct _Reason_Code MLME_DISASSOCREQ_PARA, *psMLME_DISASSOCREQ_PARA;
-
typedef struct _ASSOCREQ {
u8 PeerSTAAddr[MAC_ADDR_LENGTH];
u16 CapabilityInfo;
diff --git a/drivers/staging/winbond/mto.h b/drivers/staging/winbond/mto.h
index 4fe24b0f279..fb4781d5781 100644
--- a/drivers/staging/winbond/mto.h
+++ b/drivers/staging/winbond/mto.h
@@ -141,11 +141,6 @@ extern u16 MTO_Frag_Th_Tbl[];
#define MTO_DATA_RATE() MTO_Data_Rate_Tbl[MTO_RATE_LEVEL()]
#define MTO_FRAG_TH() MTO_Frag_Th_Tbl[MTO_FRAG_TH_LEVEL()]
-typedef struct {
- u8 tx_rate;
- u8 tx_retry_rate;
-} TXRETRY_REC;
-
extern void MTO_Init(struct wbsoft_priv *);
extern void MTO_PeriodicTimerExpired(struct wbsoft_priv *);
extern void MTO_SetDTORateRange(struct wbsoft_priv *, u8 *, u8);
diff --git a/drivers/staging/winbond/reg.c b/drivers/staging/winbond/reg.c
index d915cbdd38e..5f5048af26a 100644
--- a/drivers/staging/winbond/reg.c
+++ b/drivers/staging/winbond/reg.c
@@ -1823,12 +1823,12 @@ BBProcessor_initial( struct hw_data * pHwData )
reg->SQ3_filter[i] = 0x2f; // half of Bit 0 ~ 6
}
-void set_tx_power_per_channel_max2829( struct hw_data * pHwData, ChanInfo Channel)
+void set_tx_power_per_channel_max2829( struct hw_data * pHwData, struct chan_info Channel)
{
RFSynthesizer_SetPowerIndex( pHwData, 100 ); // 20060620.1 Modify
}
-void set_tx_power_per_channel_al2230( struct hw_data * pHwData, ChanInfo Channel )
+void set_tx_power_per_channel_al2230( struct hw_data * pHwData, struct chan_info Channel )
{
u8 index = 100;
@@ -1838,7 +1838,7 @@ void set_tx_power_per_channel_al2230( struct hw_data * pHwData, ChanInfo Chann
RFSynthesizer_SetPowerIndex( pHwData, index );
}
-void set_tx_power_per_channel_al7230( struct hw_data * pHwData, ChanInfo Channel)
+void set_tx_power_per_channel_al7230( struct hw_data * pHwData, struct chan_info Channel)
{
u8 i, index = 100;
@@ -1868,7 +1868,7 @@ void set_tx_power_per_channel_al7230( struct hw_data * pHwData, ChanInfo Chann
RFSynthesizer_SetPowerIndex( pHwData, index );
}
-void set_tx_power_per_channel_wb242( struct hw_data * pHwData, ChanInfo Channel)
+void set_tx_power_per_channel_wb242( struct hw_data * pHwData, struct chan_info Channel)
{
u8 index = 100;
@@ -1901,7 +1901,7 @@ void set_tx_power_per_channel_wb242( struct hw_data * pHwData, ChanInfo Channe
// None.
//=============================================================================================================
void
-RFSynthesizer_SwitchingChannel( struct hw_data * pHwData, ChanInfo Channel )
+RFSynthesizer_SwitchingChannel( struct hw_data * pHwData, struct chan_info Channel )
{
struct wb35_reg *reg = &pHwData->reg;
u32 pltmp[16]; // The 16 is the maximum capability of hardware
diff --git a/drivers/staging/winbond/scan_s.h b/drivers/staging/winbond/scan_s.h
index 775bb81f23c..209717f5d47 100644
--- a/drivers/staging/winbond/scan_s.h
+++ b/drivers/staging/winbond/scan_s.h
@@ -35,7 +35,6 @@ typedef struct _SCAN_REQ_PARA //mandatory parameters for SCAN request
{
u32 ScanType; //passive/active scan
- CHAN_LIST sChannelList; // 86B
u8 reserved_1[2];
struct SSID_Element sSSID; // 34B. scan only for this SSID
diff --git a/drivers/staging/winbond/sme_api.h b/drivers/staging/winbond/sme_api.h
index 54987830228..b5898294eb8 100644
--- a/drivers/staging/winbond/sme_api.h
+++ b/drivers/staging/winbond/sme_api.h
@@ -193,8 +193,6 @@ s8 sme_get_cwmin_value(void *pcore_data, u8 *cwmin);
s8 sme_get_cwmax_value(void *pcore_data, u16 *cwmax);
s8 sme_get_ms_radio_mode(void *pcore_data, u8 * pMsRadioOff);
s8 sme_set_ms_radio_mode(void *pcore_data, u8 boMsRadioOff);
-s8 sme_get_radio_mode(void *pcore_data, psRadioOff pRadioOffData);
-s8 sme_set_radio_mode(void *pcore_data, RadioOff RadioOffData);
void sme_get_tx_power_level(void *pcore_data, u32 *TxPower);
u8 sme_set_tx_power_level(void *pcore_data, u32 TxPower);
@@ -203,7 +201,7 @@ void sme_get_rx_antenna(void *pcore_data, u32 *RxAntenna);
u8 sme_set_rx_antenna(void *pcore_data, u32 RxAntenna);
void sme_get_tx_antenna(void *pcore_data, u32 *TxAntenna);
s8 sme_set_tx_antenna(void *pcore_data, u32 TxAntenna);
-s8 sme_set_IBSS_chan(void *pcore_data, ChanInfo chan);
+s8 sme_set_IBSS_chan(void *pcore_data, struct chan_info chan);
//20061108 WPS
s8 sme_set_IE_append(void *pcore_data, u8 *buffer, u16 buf_len);
diff --git a/drivers/staging/winbond/wb35reg_f.h b/drivers/staging/winbond/wb35reg_f.h
index 30f5b5ad63a..d352bce5c17 100644
--- a/drivers/staging/winbond/wb35reg_f.h
+++ b/drivers/staging/winbond/wb35reg_f.h
@@ -14,7 +14,7 @@ void Dxx_initial( struct hw_data * pHwData );
void Mxx_initial( struct hw_data * pHwData );
void RFSynthesizer_initial( struct hw_data * pHwData );
//void RFSynthesizer_SwitchingChannel( struct hw_data * pHwData, s8 Channel );
-void RFSynthesizer_SwitchingChannel( struct hw_data * pHwData, ChanInfo Channel );
+void RFSynthesizer_SwitchingChannel( struct hw_data * pHwData, struct chan_info Channel );
void BBProcessor_initial( struct hw_data * pHwData );
void BBProcessor_RateChanging( struct hw_data * pHwData, u8 rate ); // 20060613.1
//void RF_RateChanging( struct hw_data * pHwData, u8 rate ); // 20060626.5.c Add
diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c
index 067082a7d75..3482eec1865 100644
--- a/drivers/staging/winbond/wbusb.c
+++ b/drivers/staging/winbond/wbusb.c
@@ -23,7 +23,7 @@ MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.1");
-static struct usb_device_id wb35_table[] __devinitdata = {
+static const struct usb_device_id wb35_table[] __devinitconst = {
{ USB_DEVICE(0x0416, 0x0035) },
{ USB_DEVICE(0x18E8, 0x6201) },
{ USB_DEVICE(0x18E8, 0x6206) },
@@ -65,17 +65,17 @@ static void hal_set_beacon_period(struct hw_data *pHwData, u16 beacon_period)
}
static int wbsoft_add_interface(struct ieee80211_hw *dev,
- struct ieee80211_if_init_conf *conf)
+ struct ieee80211_vif *vif)
{
struct wbsoft_priv *priv = dev->priv;
- hal_set_beacon_period(&priv->sHwData, conf->vif->bss_conf.beacon_int);
+ hal_set_beacon_period(&priv->sHwData, vif->bss_conf.beacon_int);
return 0;
}
static void wbsoft_remove_interface(struct ieee80211_hw *dev,
- struct ieee80211_if_init_conf *conf)
+ struct ieee80211_vif *vif)
{
printk("wbsoft_remove interface called\n");
}
@@ -92,13 +92,6 @@ static int wbsoft_get_stats(struct ieee80211_hw *hw,
return 0;
}
-static int wbsoft_get_tx_stats(struct ieee80211_hw *hw,
- struct ieee80211_tx_queue_stats *stats)
-{
- printk(KERN_INFO "%s called\n", __func__);
- return 0;
-}
-
static u64 wbsoft_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
struct dev_addr_list *mc_list)
{
@@ -161,7 +154,7 @@ static void hal_set_radio_mode(struct hw_data *pHwData, unsigned char radio_off)
}
static void
-hal_set_current_channel_ex(struct hw_data *pHwData, ChanInfo channel)
+hal_set_current_channel_ex(struct hw_data *pHwData, struct chan_info channel)
{
struct wb35_reg *reg = &pHwData->reg;
@@ -180,10 +173,10 @@ hal_set_current_channel_ex(struct hw_data *pHwData, ChanInfo channel)
reg->M28_MacControl &= ~0xff; // Clean channel information field
reg->M28_MacControl |= channel.ChanNo;
Wb35Reg_WriteWithCallbackValue(pHwData, 0x0828, reg->M28_MacControl,
- (s8 *) & channel, sizeof(ChanInfo));
+ (s8 *) & channel, sizeof(struct chan_info));
}
-static void hal_set_current_channel(struct hw_data *pHwData, ChanInfo channel)
+static void hal_set_current_channel(struct hw_data *pHwData, struct chan_info channel)
{
hal_set_current_channel_ex(pHwData, channel);
}
@@ -253,7 +246,7 @@ static void hal_set_accept_beacon(struct hw_data *pHwData, u8 enable)
static int wbsoft_config(struct ieee80211_hw *dev, u32 changed)
{
struct wbsoft_priv *priv = dev->priv;
- ChanInfo ch;
+ struct chan_info ch;
printk("wbsoft_config called\n");
@@ -287,7 +280,6 @@ static const struct ieee80211_ops wbsoft_ops = {
.prepare_multicast = wbsoft_prepare_multicast,
.configure_filter = wbsoft_configure_filter,
.get_stats = wbsoft_get_stats,
- .get_tx_stats = wbsoft_get_tx_stats,
.get_tsf = wbsoft_get_tsf,
};
diff --git a/drivers/staging/wlags49_h2/wl_main.c b/drivers/staging/wlags49_h2/wl_main.c
index 16764a00094..cf0c38468b2 100644
--- a/drivers/staging/wlags49_h2/wl_main.c
+++ b/drivers/staging/wlags49_h2/wl_main.c
@@ -3792,7 +3792,7 @@ static int write_int(struct file *file, const char *buffer, unsigned long count,
}
if (count > 0 ) {
proc_number[count] = 0;
- nr = wl_atoi( proc_number );
+ nr = simple_strtoul(proc_number , NULL, 0);
*(unsigned int *)data = nr;
if ( nr & 0x8000 ) { //;?kludgy but it is unclear to me were else to place this
#if DBG
diff --git a/drivers/staging/wlags49_h2/wl_netdev.c b/drivers/staging/wlags49_h2/wl_netdev.c
index c33e225bc0e..fa082d90fca 100644
--- a/drivers/staging/wlags49_h2/wl_netdev.c
+++ b/drivers/staging/wlags49_h2/wl_netdev.c
@@ -360,7 +360,7 @@ int wl_open(struct net_device *dev)
wl_lock( lp, &flags );
if( status != HCF_SUCCESS ) {
- // Unsuccesfull, try reset of the card to recover
+ // Unsuccessful, try reset of the card to recover
status = wl_reset( dev );
}
diff --git a/drivers/staging/wlags49_h2/wl_pci.c b/drivers/staging/wlags49_h2/wl_pci.c
index a3db111d4a9..01e4bec9fd5 100644
--- a/drivers/staging/wlags49_h2/wl_pci.c
+++ b/drivers/staging/wlags49_h2/wl_pci.c
@@ -81,7 +81,6 @@
#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h>
-#include <asm/system.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
diff --git a/drivers/staging/wlags49_h2/wl_profile.c b/drivers/staging/wlags49_h2/wl_profile.c
index 715f027a923..1e0c75f2855 100644
--- a/drivers/staging/wlags49_h2/wl_profile.c
+++ b/drivers/staging/wlags49_h2/wl_profile.c
@@ -383,15 +383,15 @@ void translate_option( char *buffer, struct wl_private *lp )
DbgInfo->DebugFlag |= DBG_DEFAULTS;
}
} else {
- DbgInfo->DebugFlag = wl_atoi( value ); //;?DebugFlag;
+ DbgInfo->DebugFlag = simple_strtoul(value, NULL, 0); //;?DebugFlag;
}
- DbgInfo->DebugFlag = wl_atoi( value ); //;?Delete ASAP
+ DbgInfo->DebugFlag = simple_strtoul(value, NULL, 0); //;?Delete ASAP
}
#endif /* DBG */
if ( strcmp( key, PARM_NAME_AUTH_KEY_MGMT_SUITE ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_AUTH_KEY_MGMT_SUITE, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_AUTH_KEY_MGMT_SUITE ) || ( value_convert <= PARM_MAX_AUTH_KEY_MGMT_SUITE )) {
lp->AuthKeyMgmtSuite = value_convert;
} else {
@@ -401,7 +401,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_BRSC_2GHZ ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_BRSC_2GHZ, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_BRSC ) || ( value_convert <= PARM_MAX_BRSC )) {
lp->brsc[0] = value_convert;
} else {
@@ -411,7 +411,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_BRSC_5GHZ ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_BRSC_5GHZ, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_BRSC ) || ( value_convert <= PARM_MAX_BRSC )) {
lp->brsc[1] = value_convert;
} else {
@@ -448,7 +448,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_ENABLE_ENCRYPTION ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_ENABLE_ENCRYPTION, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_ENABLE_ENCRYPTION ) && ( value_convert <= PARM_MAX_ENABLE_ENCRYPTION )) {
lp->EnableEncryption = value_convert;
} else {
@@ -529,7 +529,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_MULTICAST_RATE ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_MULTICAST_RATE, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_MULTICAST_RATE ) && ( value_convert <= PARM_MAX_MULTICAST_RATE )) {
lp->MulticastRate[0] = value_convert;
@@ -540,7 +540,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_OWN_CHANNEL ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_OWN_CHANNEL, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if ( wl_is_a_valid_chan( value_convert )) {
if ( value_convert > 14 ) {
value_convert = value_convert | 0x100;
@@ -567,7 +567,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) {
lp->RTSThreshold = value_convert;
} else {
@@ -577,7 +577,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_SRSC_2GHZ ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_SRSC_2GHZ, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_SRSC ) || ( value_convert <= PARM_MAX_SRSC )) {
lp->srsc[0] = value_convert;
} else {
@@ -587,7 +587,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_SRSC_5GHZ ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_SRSC_5GHZ, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_SRSC ) || ( value_convert <= PARM_MAX_SRSC )) {
lp->srsc[1] = value_convert;
} else {
@@ -597,7 +597,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_SYSTEM_SCALE ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_SYSTEM_SCALE, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_SYSTEM_SCALE ) && ( value_convert <= PARM_MAX_SYSTEM_SCALE )) {
lp->DistanceBetweenAPs = value_convert;
} else {
@@ -607,9 +607,9 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_TX_KEY ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_KEY, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_TX_KEY ) && ( value_convert <= PARM_MAX_TX_KEY )) {
- lp->TransmitKeyID = wl_atoi( value );
+ lp->TransmitKeyID = simple_strtoul(value, NULL, 0);
} else {
DBG_WARNING( DbgInfo, "%s invalid; will be ignored\n", PARM_NAME_TX_KEY );
}
@@ -617,7 +617,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_TX_RATE ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) {
lp->TxRateControl[0] = value_convert;
} else {
@@ -627,7 +627,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_TX_POW_LEVEL ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_POW_LEVEL, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_TX_POW_LEVEL ) || ( value_convert <= PARM_MAX_TX_POW_LEVEL )) {
lp->txPowLevel = value_convert;
} else {
@@ -645,7 +645,7 @@ void translate_option( char *buffer, struct wl_private *lp )
if ( strcmp( key, PARM_NAME_PORT_TYPE ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_PORT_TYPE, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert == PARM_MIN_PORT_TYPE ) || ( value_convert == PARM_MAX_PORT_TYPE )) {
lp->PortType = value_convert;
} else {
@@ -654,7 +654,7 @@ void translate_option( char *buffer, struct wl_private *lp )
}
else if ( strcmp( key, PARM_NAME_PM_ENABLED ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_PM_ENABLED, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
/* ;? how about wl_main.c containing
* VALID_PARAM( PARM_PM_ENABLED <= WVLAN_PM_STATE_STANDARD ||
* ( PARM_PM_ENABLED & 0x7FFF ) <= WVLAN_PM_STATE_STANDARD );
@@ -677,7 +677,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_MAX_SLEEP ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_MAX_SLEEP, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= 0 ) && ( value_convert <= 65535 )) {
lp->MaxSleepDuration = value_convert;
} else {
@@ -696,7 +696,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_AUTHENTICATION ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_AUTHENTICATION, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_AUTHENTICATION ) && ( value_convert <= PARM_MAX_AUTHENTICATION )) {
lp->authentication = value_convert;
} else {
@@ -706,7 +706,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_OWN_ATIM_WINDOW ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_OWN_ATIM_WINDOW, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_OWN_ATIM_WINDOW ) && ( value_convert <= PARM_MAX_OWN_ATIM_WINDOW )) {
lp->atimWindow = value_convert;
} else {
@@ -716,7 +716,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_PM_HOLDOVER_DURATION ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_PM_HOLDOVER_DURATION, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_PM_HOLDOVER_DURATION ) && ( value_convert <= PARM_MAX_PM_HOLDOVER_DURATION )) {
lp->holdoverDuration = value_convert;
} else {
@@ -730,7 +730,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_CONNECTION_CONTROL ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_CONNECTION_CONTROL, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_CONNECTION_CONTROL ) && ( value_convert <= PARM_MAX_CONNECTION_CONTROL )) {
lp->connectionControl = value_convert;
} else {
@@ -749,7 +749,7 @@ void translate_option( char *buffer, struct wl_private *lp )
if ( strcmp( key, PARM_NAME_OWN_DTIM_PERIOD ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_OWN_DTIM_PERIOD, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if ( value_convert >= PARM_MIN_OWN_DTIM_PERIOD ) {
lp->DTIMPeriod = value_convert;
} else {
@@ -775,7 +775,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_OWN_BEACON_INTERVAL ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_OWN_BEACON_INTERVAL, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if ( value_convert >= PARM_MIN_OWN_BEACON_INTERVAL ) {
lp->ownBeaconInterval = value_convert;
} else {
@@ -785,7 +785,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_COEXISTENCE ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_COEXISTENCE, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if ( value_convert >= PARM_MIN_COEXISTENCE ) {
lp->coexistence = value_convert;
} else {
@@ -797,7 +797,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD1 ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD1, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) {
lp->wds_port[0].rtsThreshold = value_convert;
} else {
@@ -807,7 +807,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD2 ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD2, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) {
lp->wds_port[1].rtsThreshold = value_convert;
} else {
@@ -817,7 +817,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD3 ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD3, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) {
lp->wds_port[2].rtsThreshold = value_convert;
} else {
@@ -827,7 +827,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD4 ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD4, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) {
lp->wds_port[3].rtsThreshold = value_convert;
} else {
@@ -837,7 +837,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD5 ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD5, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) {
lp->wds_port[4].rtsThreshold = value_convert;
} else {
@@ -847,7 +847,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_RTS_THRESHOLD6 ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_RTS_THRESHOLD6, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_RTS_THRESHOLD ) && ( value_convert <= PARM_MAX_RTS_THRESHOLD )) {
lp->wds_port[5].rtsThreshold = value_convert;
} else {
@@ -857,7 +857,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_TX_RATE1 ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE1, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) {
lp->wds_port[0].txRateCntl = value_convert;
} else {
@@ -867,7 +867,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_TX_RATE2 ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE2, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) {
lp->wds_port[1].txRateCntl = value_convert;
} else {
@@ -877,7 +877,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_TX_RATE3 ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE3, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) {
lp->wds_port[2].txRateCntl = value_convert;
} else {
@@ -887,7 +887,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_TX_RATE4 ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE4, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) {
lp->wds_port[3].txRateCntl = value_convert;
} else {
@@ -897,7 +897,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_TX_RATE5 ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE5, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) {
lp->wds_port[4].txRateCntl = value_convert;
} else {
@@ -907,7 +907,7 @@ void translate_option( char *buffer, struct wl_private *lp )
else if ( strcmp( key, PARM_NAME_TX_RATE6 ) == 0 ) {
DBG_TRACE( DbgInfo, "%s, value: %s\n", PARM_NAME_TX_RATE6, value );
- value_convert = wl_atoi( value );
+ value_convert = simple_strtoul(value, NULL, 0);
if (( value_convert >= PARM_MIN_TX_RATE ) && ( value_convert <= PARM_MAX_TX_RATE )) {
lp->wds_port[5].txRateCntl = value_convert;
} else {
diff --git a/drivers/staging/wlags49_h2/wl_util.c b/drivers/staging/wlags49_h2/wl_util.c
index ac1e7f38f98..bbdb9973d1e 100644
--- a/drivers/staging/wlags49_h2/wl_util.c
+++ b/drivers/staging/wlags49_h2/wl_util.c
@@ -1536,52 +1536,3 @@ int wl_get_tallies(struct wl_private *lp,
return ret;
}
-/*******************************************************************************
- * wl_atoi()
- *******************************************************************************
- *
- * DESCRIPTION:
- *
- * Believe it or not, we need our own implementation of atoi in the kernel.
- *
- * PARAMETERS:
- *
- * string - the ASCII string to convert to an integer
- *
- * RETURNS:
- *
- * unsigned integer
- *
- ******************************************************************************/
-unsigned int wl_atoi( char *string )
-{
-unsigned int base = 10; //default to decimal
-unsigned int value = 0;
-unsigned int c;
-int i = strlen( string );
-
- if ( i > 2 && string[0] == '0' && ( string[1] | ('X'^'x') ) == 'x' ) {
- base = 16;
- string +=2;
- }
- while ( ( c = *string++ ) != '\0' ) {
- if ( value > UINT_MAX / base ) { //test for overrun
- DBG_FUNC( "wl_atoi" ); //don't overload the log file with good messages
- DBG_ENTER( DbgInfo );
- DBG_ERROR( DbgInfo, "string \"%s\", lenght exceeds expectations\n", string );
- printk( "<1>string \"%s\", lenght exceeds expectations\n", string );
- DBG_LEAVE( DbgInfo );
- break;
- }
- c -= '0';
- if ( 0 <= c && c <= 9 ) value = base * value + c;
- else if ( base == 16 ) {
- c += '0';
- c |= 'A'^'a';
- c = c - 'a'+ 10;
- if ( 10 <= c && c <= 15 ) value = base * value + c;
- }
- }
- return value;
-} // wl_atoi
-
diff --git a/drivers/staging/wlags49_h2/wl_util.h b/drivers/staging/wlags49_h2/wl_util.h
index 16cd6c578ad..561e85b5c9b 100644
--- a/drivers/staging/wlags49_h2/wl_util.h
+++ b/drivers/staging/wlags49_h2/wl_util.h
@@ -100,6 +100,4 @@ void wl_process_updated_record( struct wl_private *lp );
void wl_process_assoc_status( struct wl_private *lp );
void wl_process_security_status( struct wl_private *lp );
-unsigned int wl_atoi( char *string );
-
#endif // __WL_UTIL_H__
diff --git a/drivers/staging/wlan-ng/Kconfig b/drivers/staging/wlan-ng/Kconfig
index f44294b0d8d..82fcc1665e9 100644
--- a/drivers/staging/wlan-ng/Kconfig
+++ b/drivers/staging/wlan-ng/Kconfig
@@ -1,6 +1,8 @@
config PRISM2_USB
tristate "Prism2.5/3 USB driver"
- depends on WLAN && USB && WIRELESS_EXT
+ depends on WLAN && USB
+ select WIRELESS_EXT
+ select WEXT_PRIV
default n
---help---
This is the wlan-ng prism 2.5/3 USB driver for a wide range of
diff --git a/drivers/staging/wlan-ng/hfa384x.h b/drivers/staging/wlan-ng/hfa384x.h
index 46cce8159e5..1fa42e01e8c 100644
--- a/drivers/staging/wlan-ng/hfa384x.h
+++ b/drivers/staging/wlan-ng/hfa384x.h
@@ -61,17 +61,17 @@
#include <linux/if_ether.h>
/*--- Mins & Maxs -----------------------------------*/
-#define HFA384x_PORTID_MAX ((u16)7)
-#define HFA384x_NUMPORTS_MAX ((u16)(HFA384x_PORTID_MAX+1))
-#define HFA384x_PDR_LEN_MAX ((u16)512) /* in bytes, from EK */
-#define HFA384x_PDA_RECS_MAX ((u16)200) /* a guess */
-#define HFA384x_PDA_LEN_MAX ((u16)1024) /* in bytes, from EK */
-#define HFA384x_SCANRESULT_MAX ((u16)31)
-#define HFA384x_HSCANRESULT_MAX ((u16)31)
-#define HFA384x_CHINFORESULT_MAX ((u16)16)
-#define HFA384x_RID_GUESSING_MAXLEN 2048 /* I'm not really sure */
-#define HFA384x_RIDDATA_MAXLEN HFA384x_RID_GUESSING_MAXLEN
-#define HFA384x_USB_RWMEM_MAXLEN 2048
+#define HFA384x_PORTID_MAX ((u16)7)
+#define HFA384x_NUMPORTS_MAX ((u16)(HFA384x_PORTID_MAX+1))
+#define HFA384x_PDR_LEN_MAX ((u16)512) /* in bytes, from EK */
+#define HFA384x_PDA_RECS_MAX ((u16)200) /* a guess */
+#define HFA384x_PDA_LEN_MAX ((u16)1024) /* in bytes, from EK*/
+#define HFA384x_SCANRESULT_MAX ((u16)31)
+#define HFA384x_HSCANRESULT_MAX ((u16)31)
+#define HFA384x_CHINFORESULT_MAX ((u16)16)
+#define HFA384x_RID_GUESSING_MAXLEN 2048 /* I'm not really sure */
+#define HFA384x_RIDDATA_MAXLEN HFA384x_RID_GUESSING_MAXLEN
+#define HFA384x_USB_RWMEM_MAXLEN 2048
/*--- Support Constants -----------------------------*/
#define HFA384x_PORTTYPE_IBSS ((u16)0)
@@ -115,8 +115,8 @@
/* Make a 32-bit flat address from AUX format 16-bit page and offset */
#define HFA384x_ADDR_AUX_MKFLAT(p, o) \
- (((u32)(((u16)(p))&HFA384x_ADDR_AUX_PAGE_MASK)) << 7) | \
- ((u32)(((u16)(o))&HFA384x_ADDR_AUX_OFF_MASK))
+ ((((u32)(((u16)(p))&HFA384x_ADDR_AUX_PAGE_MASK)) << 7) | \
+ ((u32)(((u16)(o))&HFA384x_ADDR_AUX_OFF_MASK)))
/* Make CMD format offset and page from a 32-bit flat address */
#define HFA384x_ADDR_CMD_MKPAGE(f) \
@@ -135,12 +135,21 @@
#define HFA384x_DLSTATE_FLASHENABLED 2
/*--- Register Field Masks --------------------------*/
-#define HFA384x_CMD_AINFO ((u16)(BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10) | BIT(9) | BIT(8)))
-#define HFA384x_CMD_MACPORT ((u16)(BIT(10) | BIT(9) | BIT(8)))
+#define HFA384x_CMD_AINFO ((u16)(BIT(14) | BIT(13) \
+ | BIT(12) | BIT(11) \
+ | BIT(10) | BIT(9) \
+ | BIT(8)))
+#define HFA384x_CMD_MACPORT ((u16)(BIT(10) | BIT(9) | \
+ BIT(8)))
#define HFA384x_CMD_PROGMODE ((u16)(BIT(9) | BIT(8)))
-#define HFA384x_CMD_CMDCODE ((u16)(BIT(5) | BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0)))
+#define HFA384x_CMD_CMDCODE ((u16)(BIT(5) | BIT(4) | \
+ BIT(3) | BIT(2) | \
+ BIT(1) | BIT(0)))
-#define HFA384x_STATUS_RESULT ((u16)(BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10) | BIT(9) | BIT(8)))
+#define HFA384x_STATUS_RESULT ((u16)(BIT(14) | BIT(13) \
+ | BIT(12) | BIT(11) \
+ | BIT(10) | BIT(9) \
+ | BIT(8)))
/*--- Command Code Constants --------------------------*/
/*--- Controller Commands --------------------------*/
@@ -244,8 +253,10 @@ Information RID Lengths: MAC Information
This is the length of JUST the DATA part of the RID (does not
include the len or code fields)
--------------------------------------------------------------------*/
-#define HFA384x_RID_DBMCOMMSQUALITY_LEN ((u16)sizeof(hfa384x_dbmcommsquality_t))
-#define HFA384x_RID_JOINREQUEST_LEN ((u16)sizeof(hfa384x_JoinRequest_data_t))
+#define HFA384x_RID_DBMCOMMSQUALITY_LEN \
+ ((u16) sizeof(hfa384x_dbmcommsquality_t))
+#define HFA384x_RID_JOINREQUEST_LEN \
+ ((u16)sizeof(hfa384x_JoinRequest_data_t))
/*--------------------------------------------------------------------
Information RIDs: Modem Information
@@ -322,9 +333,11 @@ PD Record codes
/*--- Register Test/Get/Set Field macros ------------------------*/
-#define HFA384x_CMD_AINFO_SET(value) ((u16)((u16)(value) << 8))
-#define HFA384x_CMD_MACPORT_SET(value) ((u16)HFA384x_CMD_AINFO_SET(value))
-#define HFA384x_CMD_PROGMODE_SET(value) ((u16)HFA384x_CMD_AINFO_SET((u16)value))
+#define HFA384x_CMD_AINFO_SET(value) ((u16)((u16)(value) << 8))
+#define HFA384x_CMD_MACPORT_SET(value) \
+ ((u16)HFA384x_CMD_AINFO_SET(value))
+#define HFA384x_CMD_PROGMODE_SET(value) \
+ ((u16)HFA384x_CMD_AINFO_SET((u16)value))
#define HFA384x_CMD_CMDCODE_SET(value) ((u16)(value))
#define HFA384x_STATUS_RESULT_SET(value) (((u16)(value)) << 8)
@@ -402,7 +415,7 @@ typedef struct hfa384x_authenticateStation_data {
/*-- Configuration Record: WPAData (data portion only) --*/
typedef struct hfa384x_WPAData {
u16 datalen;
- u8 data[0]; // max 80
+ u8 data[0]; /* max 80 */
} __attribute__ ((packed)) hfa384x_WPAData_t;
/*--------------------------------------------------------------------
@@ -479,7 +492,8 @@ Communication Frames: Field Masks for Transmit Frames
#define HFA384x_TXSTATUS_AGEDERR ((u16)BIT(1))
#define HFA384x_TXSTATUS_RETRYERR ((u16)BIT(0))
/*-- Transmit Control Field --*/
-#define HFA384x_TX_MACPORT ((u16)(BIT(10) | BIT(9) | BIT(8)))
+#define HFA384x_TX_MACPORT ((u16)(BIT(10) | \
+ BIT(9) | BIT(8)))
#define HFA384x_TX_STRUCTYPE ((u16)(BIT(4) | BIT(3)))
#define HFA384x_TX_TXEX ((u16)BIT(2))
#define HFA384x_TX_TXOK ((u16)BIT(1))
@@ -496,7 +510,8 @@ Communication Frames: Test/Get/Set Field Values for Transmit Frames
#define HFA384x_TX_SET(v, m, s) ((((u16)(v))<<((u16)(s)))&((u16)(m)))
#define HFA384x_TX_MACPORT_SET(v) HFA384x_TX_SET(v, HFA384x_TX_MACPORT, 8)
-#define HFA384x_TX_STRUCTYPE_SET(v) HFA384x_TX_SET(v, HFA384x_TX_STRUCTYPE, 3)
+#define HFA384x_TX_STRUCTYPE_SET(v) HFA384x_TX_SET(v, \
+ HFA384x_TX_STRUCTYPE, 3)
#define HFA384x_TX_TXEX_SET(v) HFA384x_TX_SET(v, HFA384x_TX_TXEX, 2)
#define HFA384x_TX_TXOK_SET(v) HFA384x_TX_SET(v, HFA384x_TX_TXOK, 1)
/*--------------------------------------------------------------------
@@ -534,13 +549,17 @@ Communication Frames: Field Masks for Receive Frames
--------------------------------------------------------------------*/
/*-- Status Fields --*/
-#define HFA384x_RXSTATUS_MACPORT ((u16)(BIT(10) | BIT(9) | BIT(8)))
+#define HFA384x_RXSTATUS_MACPORT ((u16)(BIT(10) | \
+ BIT(9) | \
+ BIT(8)))
#define HFA384x_RXSTATUS_FCSERR ((u16)BIT(0))
/*--------------------------------------------------------------------
Communication Frames: Test/Get/Set Field Values for Receive Frames
--------------------------------------------------------------------*/
-#define HFA384x_RXSTATUS_MACPORT_GET(value) ((u16)((((u16)(value)) & HFA384x_RXSTATUS_MACPORT) >> 8))
-#define HFA384x_RXSTATUS_ISFCSERR(value) ((u16)(((u16)(value)) & HFA384x_RXSTATUS_FCSERR))
+#define HFA384x_RXSTATUS_MACPORT_GET(value) ((u16)((((u16)(value)) \
+ & HFA384x_RXSTATUS_MACPORT) >> 8))
+#define HFA384x_RXSTATUS_ISFCSERR(value) ((u16)(((u16)(value)) \
+ & HFA384x_RXSTATUS_FCSERR))
/*--------------------------------------------------------------------
FRAME STRUCTURES: Information Types and Information Frame Structures
----------------------------------------------------------------------
@@ -1133,7 +1152,7 @@ struct hfa384x;
typedef void (*ctlx_cmdcb_t) (struct hfa384x *, const struct hfa384x_usbctlx *);
-typedef void (*ctlx_usercb_t) (struct hfa384x * hw,
+typedef void (*ctlx_usercb_t) (struct hfa384x *hw,
void *ctlxresult, void *usercb_data);
typedef struct hfa384x_usbctlx {
@@ -1174,14 +1193,14 @@ typedef struct hfa484x_metacmd {
} hfa384x_metacmd_t;
#define MAX_GRP_ADDR 32
-#define WLAN_COMMENT_MAX 80 /* Max. length of user comment string. */
+#define WLAN_COMMENT_MAX 80 /* Max. length of user comment string. */
-#define WLAN_AUTH_MAX 60 /* Max. # of authenticated stations. */
-#define WLAN_ACCESS_MAX 60 /* Max. # of stations in an access list. */
-#define WLAN_ACCESS_NONE 0 /* No stations may be authenticated. */
-#define WLAN_ACCESS_ALL 1 /* All stations may be authenticated. */
-#define WLAN_ACCESS_ALLOW 2 /* Authenticate only "allowed" stations. */
-#define WLAN_ACCESS_DENY 3 /* Do not authenticate "denied" stations. */
+#define WLAN_AUTH_MAX 60 /* Max. # of authenticated stations. */
+#define WLAN_ACCESS_MAX 60 /* Max. # of stations in an access list. */
+#define WLAN_ACCESS_NONE 0 /* No stations may be authenticated. */
+#define WLAN_ACCESS_ALL 1 /* All stations may be authenticated. */
+#define WLAN_ACCESS_ALLOW 2 /* Authenticate only "allowed" stations. */
+#define WLAN_ACCESS_DENY 3 /* Do not authenticate "denied" stations. */
/* XXX These are going away ASAP */
typedef struct prism2sta_authlist {
@@ -1294,10 +1313,23 @@ typedef struct hfa384x {
hfa384x_caplevel_t cap_sup_ap;
/* Actor compatibility ranges */
- hfa384x_caplevel_t cap_act_pri_cfi; /* pri f/w to controller interface */
- hfa384x_caplevel_t cap_act_sta_cfi; /* sta f/w to controller interface */
+ hfa384x_caplevel_t cap_act_pri_cfi; /*
+ * pri f/w to controller
+ * interface
+ */
+
+ hfa384x_caplevel_t cap_act_sta_cfi; /*
+ * sta f/w to controller
+ * interface
+ */
+
hfa384x_caplevel_t cap_act_sta_mfi; /* sta f/w to modem interface */
- hfa384x_caplevel_t cap_act_ap_cfi; /* ap f/w to controller interface */
+
+ hfa384x_caplevel_t cap_act_ap_cfi; /*
+ * ap f/w to controller
+ * interface
+ */
+
hfa384x_caplevel_t cap_act_ap_mfi; /* ap f/w to modem interface */
u32 psusercount; /* Power save user count. */
@@ -1320,25 +1352,25 @@ typedef struct hfa384x {
} hfa384x_t;
-void hfa384x_create(hfa384x_t * hw, struct usb_device *usb);
-void hfa384x_destroy(hfa384x_t * hw);
+void hfa384x_create(hfa384x_t *hw, struct usb_device *usb);
+void hfa384x_destroy(hfa384x_t *hw);
int
-hfa384x_corereset(hfa384x_t * hw, int holdtime, int settletime, int genesis);
-int hfa384x_drvr_commtallies(hfa384x_t * hw);
-int hfa384x_drvr_disable(hfa384x_t * hw, u16 macport);
-int hfa384x_drvr_enable(hfa384x_t * hw, u16 macport);
-int hfa384x_drvr_flashdl_enable(hfa384x_t * hw);
-int hfa384x_drvr_flashdl_disable(hfa384x_t * hw);
-int hfa384x_drvr_flashdl_write(hfa384x_t * hw, u32 daddr, void *buf, u32 len);
-int hfa384x_drvr_getconfig(hfa384x_t * hw, u16 rid, void *buf, u16 len);
-int hfa384x_drvr_ramdl_enable(hfa384x_t * hw, u32 exeaddr);
-int hfa384x_drvr_ramdl_disable(hfa384x_t * hw);
-int hfa384x_drvr_ramdl_write(hfa384x_t * hw, u32 daddr, void *buf, u32 len);
-int hfa384x_drvr_readpda(hfa384x_t * hw, void *buf, unsigned int len);
-int hfa384x_drvr_setconfig(hfa384x_t * hw, u16 rid, void *buf, u16 len);
-
-static inline int hfa384x_drvr_getconfig16(hfa384x_t * hw, u16 rid, void *val)
+hfa384x_corereset(hfa384x_t *hw, int holdtime, int settletime, int genesis);
+int hfa384x_drvr_commtallies(hfa384x_t *hw);
+int hfa384x_drvr_disable(hfa384x_t *hw, u16 macport);
+int hfa384x_drvr_enable(hfa384x_t *hw, u16 macport);
+int hfa384x_drvr_flashdl_enable(hfa384x_t *hw);
+int hfa384x_drvr_flashdl_disable(hfa384x_t *hw);
+int hfa384x_drvr_flashdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len);
+int hfa384x_drvr_getconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len);
+int hfa384x_drvr_ramdl_enable(hfa384x_t *hw, u32 exeaddr);
+int hfa384x_drvr_ramdl_disable(hfa384x_t *hw);
+int hfa384x_drvr_ramdl_write(hfa384x_t *hw, u32 daddr, void *buf, u32 len);
+int hfa384x_drvr_readpda(hfa384x_t *hw, void *buf, unsigned int len);
+int hfa384x_drvr_setconfig(hfa384x_t *hw, u16 rid, void *buf, u16 len);
+
+static inline int hfa384x_drvr_getconfig16(hfa384x_t *hw, u16 rid, void *val)
{
int result = 0;
result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(u16));
@@ -1347,46 +1379,46 @@ static inline int hfa384x_drvr_getconfig16(hfa384x_t * hw, u16 rid, void *val)
return result;
}
-static inline int hfa384x_drvr_setconfig16(hfa384x_t * hw, u16 rid, u16 val)
+static inline int hfa384x_drvr_setconfig16(hfa384x_t *hw, u16 rid, u16 val)
{
u16 value = cpu_to_le16(val);
return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(value));
}
int
-hfa384x_drvr_getconfig_async(hfa384x_t * hw,
+hfa384x_drvr_getconfig_async(hfa384x_t *hw,
u16 rid, ctlx_usercb_t usercb, void *usercb_data);
int
-hfa384x_drvr_setconfig_async(hfa384x_t * hw,
+hfa384x_drvr_setconfig_async(hfa384x_t *hw,
u16 rid,
void *buf,
u16 len, ctlx_usercb_t usercb, void *usercb_data);
static inline int
-hfa384x_drvr_setconfig16_async(hfa384x_t * hw, u16 rid, u16 val)
+hfa384x_drvr_setconfig16_async(hfa384x_t *hw, u16 rid, u16 val)
{
u16 value = cpu_to_le16(val);
return hfa384x_drvr_setconfig_async(hw, rid, &value, sizeof(value),
NULL, NULL);
}
-int hfa384x_drvr_start(hfa384x_t * hw);
-int hfa384x_drvr_stop(hfa384x_t * hw);
+int hfa384x_drvr_start(hfa384x_t *hw);
+int hfa384x_drvr_stop(hfa384x_t *hw);
int
-hfa384x_drvr_txframe(hfa384x_t * hw, struct sk_buff *skb,
- p80211_hdr_t * p80211_hdr, p80211_metawep_t * p80211_wep);
-void hfa384x_tx_timeout(wlandevice_t * wlandev);
-
-int hfa384x_cmd_initialize(hfa384x_t * hw);
-int hfa384x_cmd_enable(hfa384x_t * hw, u16 macport);
-int hfa384x_cmd_disable(hfa384x_t * hw, u16 macport);
-int hfa384x_cmd_allocate(hfa384x_t * hw, u16 len);
-int hfa384x_cmd_monitor(hfa384x_t * hw, u16 enable);
+hfa384x_drvr_txframe(hfa384x_t *hw, struct sk_buff *skb,
+ p80211_hdr_t *p80211_hdr, p80211_metawep_t *p80211_wep);
+void hfa384x_tx_timeout(wlandevice_t *wlandev);
+
+int hfa384x_cmd_initialize(hfa384x_t *hw);
+int hfa384x_cmd_enable(hfa384x_t *hw, u16 macport);
+int hfa384x_cmd_disable(hfa384x_t *hw, u16 macport);
+int hfa384x_cmd_allocate(hfa384x_t *hw, u16 len);
+int hfa384x_cmd_monitor(hfa384x_t *hw, u16 enable);
int
-hfa384x_cmd_download(hfa384x_t * hw,
+hfa384x_cmd_download(hfa384x_t *hw,
u16 mode, u16 lowaddr, u16 highaddr, u16 codelen);
-#endif /* __KERNEL__ */
+#endif /*__KERNEL__ */
-#endif /* _HFA384x_H */
+#endif /*_HFA384x_H */
diff --git a/drivers/staging/wlan-ng/hfa384x_usb.c b/drivers/staging/wlan-ng/hfa384x_usb.c
index 925678babd9..5df56f0238d 100644
--- a/drivers/staging/wlan-ng/hfa384x_usb.c
+++ b/drivers/staging/wlan-ng/hfa384x_usb.c
@@ -52,7 +52,7 @@
* around the register accesses. The next higher level represents C-callable
* prism2 API functions that match the Intersil documentation as closely
* as is reasonable. The next higher layer implements common sequences
-* of invokations of the API layer (e.g. write to bap, followed by cmd).
+* of invocations of the API layer (e.g. write to bap, followed by cmd).
*
* Common sequences:
* hfa384x_drvr_xxx Highest level abstractions provided by the
@@ -118,15 +118,15 @@
#include <linux/wireless.h>
#include <linux/netdevice.h>
#include <linux/timer.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <linux/delay.h>
#include <asm/byteorder.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
#include <linux/list.h>
#include <linux/usb.h>
#include <linux/byteorder/generic.h>
-#define SUBMIT_URB(u,f) usb_submit_urb(u,f)
+#define SUBMIT_URB(u, f) usb_submit_urb(u, f)
#include "p80211types.h"
#include "p80211hdr.h"
@@ -627,7 +627,7 @@ static hfa384x_usbctlx_t *usbctlx_alloc(void)
{
hfa384x_usbctlx_t *ctlx;
- ctlx = kmalloc(sizeof(*ctlx), in_interrupt()? GFP_ATOMIC : GFP_KERNEL);
+ ctlx = kmalloc(sizeof(*ctlx), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
if (ctlx != NULL) {
memset(ctlx, 0, sizeof(*ctlx));
init_completion(&ctlx->done);
@@ -675,7 +675,7 @@ struct usbctlx_cmd_completor {
};
typedef struct usbctlx_cmd_completor usbctlx_cmd_completor_t;
-static int usbctlx_cmd_completor_fn(usbctlx_completor_t * head)
+static int usbctlx_cmd_completor_fn(usbctlx_completor_t *head)
{
usbctlx_cmd_completor_t *complete = (usbctlx_cmd_completor_t *) head;
return usbctlx_get_status(complete->cmdresp, complete->result);
@@ -1909,18 +1909,19 @@ int hfa384x_drvr_flashdl_enable(hfa384x_t *hw)
return -EINVAL;
/* Retrieve the buffer loc&size and timeout */
- if ((result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DOWNLOADBUFFER,
- &(hw->bufinfo),
- sizeof(hw->bufinfo)))) {
+ result = hfa384x_drvr_getconfig(hw, HFA384x_RID_DOWNLOADBUFFER,
+ &(hw->bufinfo), sizeof(hw->bufinfo));
+ if (result)
return result;
- }
+
hw->bufinfo.page = le16_to_cpu(hw->bufinfo.page);
hw->bufinfo.offset = le16_to_cpu(hw->bufinfo.offset);
hw->bufinfo.len = le16_to_cpu(hw->bufinfo.len);
- if ((result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_MAXLOADTIME,
- &(hw->dltimeout)))) {
+ result = hfa384x_drvr_getconfig16(hw, HFA384x_RID_MAXLOADTIME,
+ &(hw->dltimeout));
+ if (result)
return result;
- }
+
hw->dltimeout = le16_to_cpu(hw->dltimeout);
pr_debug("flashdl_enable\n");
@@ -3071,9 +3072,9 @@ static void hfa384x_usbctlxq_run(hfa384x_t *hw)
hfa384x_ctlxout_callback, hw);
hw->ctlx_urb.transfer_flags |= USB_QUEUE_BULK;
- /* Now submit the URB and update the CTLX's state
- */
- if ((result = SUBMIT_URB(&hw->ctlx_urb, GFP_ATOMIC)) == 0) {
+ /* Now submit the URB and update the CTLX's state */
+ result = SUBMIT_URB(&hw->ctlx_urb, GFP_ATOMIC);
+ if (result == 0) {
/* This CTLX is now running on the active queue */
head->state = CTLX_REQ_SUBMITTED;
@@ -3599,7 +3600,8 @@ static void hfa384x_int_rxmonitor(wlandevice_t *wlandev,
skblen - sizeof(p80211_caphdr_t));
}
- if ((skb = dev_alloc_skb(skblen)) == NULL) {
+ skb = dev_alloc_skb(skblen);
+ if (skb == NULL) {
printk(KERN_ERR
"alloc_skb failed trying to allocate %d bytes\n",
skblen);
@@ -3642,7 +3644,7 @@ static void hfa384x_int_rxmonitor(wlandevice_t *wlandev,
/* check for unencrypted stuff if WEP bit set. */
if (*(datap - hdrlen + 1) & 0x40) /* wep set */
if ((*(datap) == 0xaa) && (*(datap + 1) == 0xaa))
- *(datap - hdrlen + 1) &= 0xbf; // clear wep; it's the 802.2 header!
+ *(datap - hdrlen + 1) &= 0xbf; /* clear wep; it's the 802.2 header! */
}
if (hw->sniff_fcs) {
@@ -3870,9 +3872,9 @@ retry:
delresp:
if (delete_resptimer) {
- if ((timer_ok = del_timer(&hw->resptimer)) != 0) {
+ timer_ok = del_timer(&hw->resptimer);
+ if (timer_ok != 0)
hw->resp_timer_done = 1;
- }
}
spin_unlock_irqrestore(&hw->ctlxq.lock, flags);
diff --git a/drivers/staging/wlan-ng/p80211conv.c b/drivers/staging/wlan-ng/p80211conv.c
index 5952c671073..a1605fbc809 100644
--- a/drivers/staging/wlan-ng/p80211conv.c
+++ b/drivers/staging/wlan-ng/p80211conv.c
@@ -206,12 +206,11 @@ int skb_ether_to_p80211(wlandevice_t *wlandev, u32 ethconv,
/* XXXX need to pick keynum other than default? */
p80211_wep->data = kmalloc(skb->len, GFP_ATOMIC);
-
- if ((foo = wep_encrypt(wlandev, skb->data, p80211_wep->data,
- skb->len,
- (wlandev->hostwep &
- HOSTWEP_DEFAULTKEY_MASK),
- p80211_wep->iv, p80211_wep->icv))) {
+ foo = wep_encrypt(wlandev, skb->data, p80211_wep->data,
+ skb->len,
+ (wlandev->hostwep &HOSTWEP_DEFAULTKEY_MASK),
+ p80211_wep->iv, p80211_wep->icv);
+ if (foo) {
printk(KERN_WARNING
"Host en-WEP failed, dropping frame (%d).\n",
foo);
@@ -323,11 +322,12 @@ int skb_p80211_to_ether(wlandevice_t *wlandev, u32 ethconv,
skb->len);
return 1;
}
- if ((foo = wep_decrypt(wlandev, skb->data + payload_offset + 4,
+ foo = wep_decrypt(wlandev, skb->data + payload_offset + 4,
payload_length - 8, -1,
skb->data + payload_offset,
skb->data + payload_offset +
- payload_length - 4))) {
+ payload_length - 4);
+ if (foo) {
/* de-wep failed, drop skb. */
pr_debug("Host de-WEP failed, dropping frame (%d).\n",
foo);
diff --git a/drivers/staging/wlan-ng/p80211conv.h b/drivers/staging/wlan-ng/p80211conv.h
index 0c62df19fa7..6fe163be24f 100644
--- a/drivers/staging/wlan-ng/p80211conv.h
+++ b/drivers/staging/wlan-ng/p80211conv.h
@@ -153,8 +153,8 @@ struct wlandevice;
int skb_p80211_to_ether(struct wlandevice *wlandev, u32 ethconv,
struct sk_buff *skb);
int skb_ether_to_p80211(struct wlandevice *wlandev, u32 ethconv,
- struct sk_buff *skb, p80211_hdr_t * p80211_hdr,
- p80211_metawep_t * p80211_wep);
+ struct sk_buff *skb, p80211_hdr_t *p80211_hdr,
+ p80211_metawep_t *p80211_wep);
int p80211_stt_findproto(u16 proto);
diff --git a/drivers/staging/wlan-ng/p80211metadef.h b/drivers/staging/wlan-ng/p80211metadef.h
index da8b6f53c74..0ccfba1294d 100644
--- a/drivers/staging/wlan-ng/p80211metadef.h
+++ b/drivers/staging/wlan-ng/p80211metadef.h
@@ -190,9 +190,9 @@
(P80211DID_MKSECTION(2) | \
P80211DID_MKGROUP(1))
#define DIDmib_dot11mac_dot11OperationTable_dot11MACAddress \
- (P80211DID_MKSECTION(2) | \
- P80211DID_MKGROUP(1) | \
- P80211DID_MKITEM(1) | 0x18000000)
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(1) | 0x18000000)
#define DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold \
(P80211DID_MKSECTION(2) | \
P80211DID_MKGROUP(1) | \
@@ -210,18 +210,18 @@
P80211DID_MKGROUP(1) | \
P80211DID_MKITEM(5) | 0x18000000)
#define DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime \
- (P80211DID_MKSECTION(2) | \
- P80211DID_MKGROUP(1) | \
- P80211DID_MKITEM(6) | 0x10000000)
+ (P80211DID_MKSECTION(2) | \
+ P80211DID_MKGROUP(1) | \
+ P80211DID_MKITEM(6) | 0x10000000)
#define DIDmib_cat_dot11phy \
P80211DID_MKSECTION(3)
#define DIDmib_dot11phy_dot11PhyOperationTable \
(P80211DID_MKSECTION(3) | \
P80211DID_MKGROUP(1))
#define DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel \
- (P80211DID_MKSECTION(3) | \
- P80211DID_MKGROUP(3) | \
- P80211DID_MKITEM(10) | 0x18000000)
+ (P80211DID_MKSECTION(3) | \
+ P80211DID_MKGROUP(3) | \
+ P80211DID_MKITEM(10) | 0x18000000)
#define DIDmib_dot11phy_dot11PhyDSSSTable \
(P80211DID_MKSECTION(3) | \
P80211DID_MKGROUP(5))
diff --git a/drivers/staging/wlan-ng/p80211mgmt.h b/drivers/staging/wlan-ng/p80211mgmt.h
index 14cdc86d167..deb52f5fd78 100644
--- a/drivers/staging/wlan-ng/p80211mgmt.h
+++ b/drivers/staging/wlan-ng/p80211mgmt.h
@@ -100,7 +100,7 @@
#ifndef _P80211MGMT_H
#define _P80211MGMT_H
-#ifndef _P80211HDR_H
+#ifndef _P80211HDR_H
#include "p80211hdr.h"
#endif
@@ -496,25 +496,25 @@ typedef struct wlan_fr_deauthen {
} wlan_fr_deauthen_t;
-void wlan_mgmt_encode_beacon(wlan_fr_beacon_t * f);
-void wlan_mgmt_decode_beacon(wlan_fr_beacon_t * f);
-void wlan_mgmt_encode_disassoc(wlan_fr_disassoc_t * f);
-void wlan_mgmt_decode_disassoc(wlan_fr_disassoc_t * f);
-void wlan_mgmt_encode_assocreq(wlan_fr_assocreq_t * f);
-void wlan_mgmt_decode_assocreq(wlan_fr_assocreq_t * f);
-void wlan_mgmt_encode_assocresp(wlan_fr_assocresp_t * f);
-void wlan_mgmt_decode_assocresp(wlan_fr_assocresp_t * f);
-void wlan_mgmt_encode_reassocreq(wlan_fr_reassocreq_t * f);
-void wlan_mgmt_decode_reassocreq(wlan_fr_reassocreq_t * f);
-void wlan_mgmt_encode_reassocresp(wlan_fr_reassocresp_t * f);
-void wlan_mgmt_decode_reassocresp(wlan_fr_reassocresp_t * f);
-void wlan_mgmt_encode_probereq(wlan_fr_probereq_t * f);
-void wlan_mgmt_decode_probereq(wlan_fr_probereq_t * f);
-void wlan_mgmt_encode_proberesp(wlan_fr_proberesp_t * f);
-void wlan_mgmt_decode_proberesp(wlan_fr_proberesp_t * f);
-void wlan_mgmt_encode_authen(wlan_fr_authen_t * f);
-void wlan_mgmt_decode_authen(wlan_fr_authen_t * f);
-void wlan_mgmt_encode_deauthen(wlan_fr_deauthen_t * f);
-void wlan_mgmt_decode_deauthen(wlan_fr_deauthen_t * f);
+void wlan_mgmt_encode_beacon(wlan_fr_beacon_t *f);
+void wlan_mgmt_decode_beacon(wlan_fr_beacon_t *f);
+void wlan_mgmt_encode_disassoc(wlan_fr_disassoc_t *f);
+void wlan_mgmt_decode_disassoc(wlan_fr_disassoc_t *f);
+void wlan_mgmt_encode_assocreq(wlan_fr_assocreq_t *f);
+void wlan_mgmt_decode_assocreq(wlan_fr_assocreq_t *f);
+void wlan_mgmt_encode_assocresp(wlan_fr_assocresp_t *f);
+void wlan_mgmt_decode_assocresp(wlan_fr_assocresp_t *f);
+void wlan_mgmt_encode_reassocreq(wlan_fr_reassocreq_t *f);
+void wlan_mgmt_decode_reassocreq(wlan_fr_reassocreq_t *f);
+void wlan_mgmt_encode_reassocresp(wlan_fr_reassocresp_t *f);
+void wlan_mgmt_decode_reassocresp(wlan_fr_reassocresp_t *f);
+void wlan_mgmt_encode_probereq(wlan_fr_probereq_t *f);
+void wlan_mgmt_decode_probereq(wlan_fr_probereq_t *f);
+void wlan_mgmt_encode_proberesp(wlan_fr_proberesp_t *f);
+void wlan_mgmt_decode_proberesp(wlan_fr_proberesp_t *f);
+void wlan_mgmt_encode_authen(wlan_fr_authen_t *f);
+void wlan_mgmt_decode_authen(wlan_fr_authen_t *f);
+void wlan_mgmt_encode_deauthen(wlan_fr_deauthen_t *f);
+void wlan_mgmt_decode_deauthen(wlan_fr_deauthen_t *f);
#endif /* _P80211MGMT_H */
diff --git a/drivers/staging/wlan-ng/p80211netdev.c b/drivers/staging/wlan-ng/p80211netdev.c
index 22424c8903e..763ab1187a1 100644
--- a/drivers/staging/wlan-ng/p80211netdev.c
+++ b/drivers/staging/wlan-ng/p80211netdev.c
@@ -586,7 +586,8 @@ static int p80211knetdev_do_ioctl(netdevice_t *dev, struct ifreq *ifr, int cmd)
}
/* Allocate a buf of size req->len */
- if ((msgbuf = kmalloc(req->len, GFP_KERNEL))) {
+ msgbuf = kmalloc(req->len, GFP_KERNEL);
+ if (msgbuf) {
if (copy_from_user(msgbuf, (void __user *)req->data, req->len))
result = -EFAULT;
else
@@ -646,7 +647,7 @@ static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr)
/* Set up some convenience pointers. */
mibattr = &dot11req.mibattribute;
- macaddr = (p80211item_pstr6_t *) & mibattr->data;
+ macaddr = (p80211item_pstr6_t *) &mibattr->data;
resultcode = &dot11req.resultcode;
/* Set up a dot11req_mibset */
@@ -674,7 +675,7 @@ static int p80211knetdev_set_mac_address(netdevice_t *dev, void *addr)
resultcode->data = 0;
/* now fire the request */
- result = p80211req_dorequest(dev->ml_priv, (u8 *) & dot11req);
+ result = p80211req_dorequest(dev->ml_priv, (u8 *) &dot11req);
/* If the request wasn't successful, report an error and don't
* change the netdev address
diff --git a/drivers/staging/wlan-ng/p80211netdev.h b/drivers/staging/wlan-ng/p80211netdev.h
index 8bd9dfb3b9b..3c8c6480056 100644
--- a/drivers/staging/wlan-ng/p80211netdev.h
+++ b/drivers/staging/wlan-ng/p80211netdev.h
@@ -179,16 +179,16 @@ typedef struct wlandevice {
unsigned int ethconv;
/* device methods (init by MSD, used by p80211 */
- int (*open) (struct wlandevice * wlandev);
- int (*close) (struct wlandevice * wlandev);
- void (*reset) (struct wlandevice * wlandev);
- int (*txframe) (struct wlandevice * wlandev, struct sk_buff * skb,
- p80211_hdr_t * p80211_hdr,
- p80211_metawep_t * p80211_wep);
- int (*mlmerequest) (struct wlandevice * wlandev, p80211msg_t * msg);
- int (*set_multicast_list) (struct wlandevice * wlandev,
- netdevice_t * dev);
- void (*tx_timeout) (struct wlandevice * wlandev);
+ int (*open) (struct wlandevice *wlandev);
+ int (*close) (struct wlandevice *wlandev);
+ void (*reset) (struct wlandevice *wlandev);
+ int (*txframe) (struct wlandevice *wlandev, struct sk_buff *skb,
+ p80211_hdr_t *p80211_hdr,
+ p80211_metawep_t *p80211_wep);
+ int (*mlmerequest) (struct wlandevice *wlandev, p80211msg_t *msg);
+ int (*set_multicast_list) (struct wlandevice *wlandev,
+ netdevice_t *dev);
+ void (*tx_timeout) (struct wlandevice *wlandev);
/* 802.11 State */
u8 bssid[WLAN_BSSID_LEN];
@@ -227,16 +227,16 @@ typedef struct wlandevice {
} wlandevice_t;
/* WEP stuff */
-int wep_change_key(wlandevice_t * wlandev, int keynum, u8 * key, int keylen);
-int wep_decrypt(wlandevice_t * wlandev, u8 * buf, u32 len, int key_override,
- u8 * iv, u8 * icv);
-int wep_encrypt(wlandevice_t * wlandev, u8 * buf, u8 * dst, u32 len, int keynum,
- u8 * iv, u8 * icv);
-
-int wlan_setup(wlandevice_t * wlandev);
-int wlan_unsetup(wlandevice_t * wlandev);
-int register_wlandev(wlandevice_t * wlandev);
-int unregister_wlandev(wlandevice_t * wlandev);
-void p80211netdev_rx(wlandevice_t * wlandev, struct sk_buff *skb);
-void p80211netdev_hwremoved(wlandevice_t * wlandev);
+int wep_change_key(wlandevice_t *wlandev, int keynum, u8 *key, int keylen);
+int wep_decrypt(wlandevice_t *wlandev, u8 *buf, u32 len, int key_override,
+ u8 *iv, u8 *icv);
+int wep_encrypt(wlandevice_t *wlandev, u8 *buf, u8 *dst, u32 len, int keynum,
+ u8 *iv, u8 *icv);
+
+int wlan_setup(wlandevice_t *wlandev);
+int wlan_unsetup(wlandevice_t *wlandev);
+int register_wlandev(wlandevice_t *wlandev);
+int unregister_wlandev(wlandevice_t *wlandev);
+void p80211netdev_rx(wlandevice_t *wlandev, struct sk_buff *skb);
+void p80211netdev_hwremoved(wlandevice_t *wlandev);
#endif
diff --git a/drivers/staging/wlan-ng/p80211req.c b/drivers/staging/wlan-ng/p80211req.c
index c88156cdf68..c2e95f16682 100644
--- a/drivers/staging/wlan-ng/p80211req.c
+++ b/drivers/staging/wlan-ng/p80211req.c
@@ -94,7 +94,7 @@ static int p80211req_mibset_mibget(wlandevice_t *wlandev,
* Potentially blocks the caller, so it's a good idea to
* not call this function from an interrupt context.
----------------------------------------------------------------*/
-int p80211req_dorequest(wlandevice_t * wlandev, u8 * msgbuf)
+int p80211req_dorequest(wlandevice_t *wlandev, u8 *msgbuf)
{
int result = 0;
p80211msg_t *msg = (p80211msg_t *) msgbuf;
diff --git a/drivers/staging/wlan-ng/p80211req.h b/drivers/staging/wlan-ng/p80211req.h
index 5d9176762ba..a95a45a6814 100644
--- a/drivers/staging/wlan-ng/p80211req.h
+++ b/drivers/staging/wlan-ng/p80211req.h
@@ -48,6 +48,6 @@
#ifndef _LINUX_P80211REQ_H
#define _LINUX_P80211REQ_H
-int p80211req_dorequest(wlandevice_t * wlandev, u8 * msgbuf);
+int p80211req_dorequest(wlandevice_t *wlandev, u8 *msgbuf);
#endif
diff --git a/drivers/staging/wlan-ng/p80211types.h b/drivers/staging/wlan-ng/p80211types.h
index 2b83ab0c711..41a99c59c6c 100644
--- a/drivers/staging/wlan-ng/p80211types.h
+++ b/drivers/staging/wlan-ng/p80211types.h
@@ -168,12 +168,12 @@
P80211DID_MASK_ISTABLE, \
P80211DID_LSB_ISTABLE)
-#define P80211DID_MKID(s,g,i,n,t,a) (P80211DID_MKSECTION(s) | \
- P80211DID_MKGROUP(g) | \
- P80211DID_MKITEM(i) | \
- P80211DID_MKINDEX(n) | \
- P80211DID_MKISTABLE(t) | \
- (a))
+#define P80211DID_MKID(s, g, i, n, t, a) (P80211DID_MKSECTION(s) | \
+ P80211DID_MKGROUP(g) | \
+ P80211DID_MKITEM(i) | \
+ P80211DID_MKINDEX(n) | \
+ P80211DID_MKISTABLE(t) | \
+ (a))
#define P80211DID_GET(a, m, l) ((((u32)(a)) >> (l)) & (m))
@@ -340,11 +340,11 @@ struct catlistitem;
/* metadata items. Some components may choose to use more, */
/* less or different metadata items. */
-typedef void (*p80211_totext_t) (struct catlistitem *, u32 did, u8 * itembuf,
+typedef void (*p80211_totext_t) (struct catlistitem *, u32 did, u8 *itembuf,
char *textbuf);
-typedef void (*p80211_fromtext_t) (struct catlistitem *, u32 did, u8 * itembuf,
+typedef void (*p80211_fromtext_t) (struct catlistitem *, u32 did, u8 *itembuf,
char *textbuf);
-typedef u32(*p80211_valid_t) (struct catlistitem *, u32 did, u8 * itembuf);
+typedef u32(*p80211_valid_t) (struct catlistitem *, u32 did, u8 *itembuf);
/*----------------------------------------------------------------*/
/* Enumeration Lists */
diff --git a/drivers/staging/wlan-ng/p80211wext.c b/drivers/staging/wlan-ng/p80211wext.c
index 74d8022adb2..2fa1dfa2378 100644
--- a/drivers/staging/wlan-ng/p80211wext.c
+++ b/drivers/staging/wlan-ng/p80211wext.c
@@ -46,8 +46,8 @@
#include <linux/wireless.h>
#include <net/iw_handler.h>
#include <linux/if_arp.h>
-#include <asm/bitops.h>
-#include <asm/uaccess.h>
+#include <linux/bitops.h>
+#include <linux/uaccess.h>
#include <asm/byteorder.h>
#include <linux/if_ether.h>
#include <linux/bitops.h>
@@ -134,10 +134,11 @@ static int p80211wext_dorequest(wlandevice_t *wlandev, u32 did, u32 data)
int result;
msg.msgcode = DIDmsg_dot11req_mibset;
+ memset(&mibitem, 0, sizeof(mibitem));
mibitem.did = did;
mibitem.data = data;
memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
return result;
}
@@ -174,7 +175,7 @@ static int p80211wext_autojoin(wlandevice_t *wlandev)
memcpy(msg.ssid.data.data, ssid, data.length);
msg.ssid.data.len = data.length;
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
if (result) {
err = -EFAULT;
@@ -211,7 +212,7 @@ struct iw_statistics *p80211wext_get_wireless_stats(netdevice_t *dev)
if (wlandev->mlmerequest == NULL)
return NULL;
- retval = wlandev->mlmerequest(wlandev, (p80211msg_t *) & quality);
+ retval = wlandev->mlmerequest(wlandev, (p80211msg_t *) &quality);
wstats->qual.qual = qual_as_percent(quality.link.data); /* overall link quality */
wstats->qual.level = quality.level.data; /* instant signal level */
@@ -269,9 +270,10 @@ static int p80211wext_giwfreq(netdevice_t *dev,
int err = 0;
msg.msgcode = DIDmsg_dot11req_mibget;
+ memset(&mibitem, 0, sizeof(mibitem));
mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
if (result) {
err = -EFAULT;
@@ -309,6 +311,7 @@ static int p80211wext_siwfreq(netdevice_t *dev,
}
msg.msgcode = DIDmsg_dot11req_mibset;
+ memset(&mibitem, 0, sizeof(mibitem));
mibitem.did = DIDmib_dot11phy_dot11PhyDSSSTable_dot11CurrentChannel;
mibitem.status = P80211ENUM_msgitem_status_data_ok;
@@ -318,7 +321,7 @@ static int p80211wext_siwfreq(netdevice_t *dev,
mibitem.data = p80211_mhz_to_channel(freq->m);
memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
if (result) {
err = -EFAULT;
@@ -396,10 +399,11 @@ static int p80211wext_siwmode(netdevice_t *dev,
/* Set Operation mode to the PORT TYPE RID */
msg.msgcode = DIDmsg_dot11req_mibset;
+ memset(&mibitem, 0, sizeof(mibitem));
mibitem.did = DIDmib_p2_p2Static_p2CnfPortType;
mibitem.data = (*mode == IW_MODE_ADHOC) ? 0 : 1;
memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
if (result)
err = -EFAULT;
@@ -549,14 +553,14 @@ static int p80211wext_siwencode(netdevice_t *dev,
}
/* Check the Key index first. */
- if ((i = (erq->flags & IW_ENCODE_INDEX))) {
-
+ i = (erq->flags & IW_ENCODE_INDEX);
+ if (i) {
if ((i < 1) || (i > NUM_WEPKEYS)) {
err = -EINVAL;
goto exit;
- } else
+ } else {
i--;
-
+ }
/* Set current key number only if no keys are given */
if (erq->flags & IW_ENCODE_NOKEY) {
result =
@@ -621,7 +625,7 @@ static int p80211wext_siwencode(netdevice_t *dev,
msg.msgcode = DIDmsg_dot11req_mibset;
memcpy(&msg.mibattribute.data, &pstr, sizeof(pstr));
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
if (result) {
err = -EFAULT;
@@ -729,7 +733,7 @@ static int p80211wext_siwessid(netdevice_t *dev,
msg.ssid.data.len = length;
pr_debug("autojoin_ssid for %s \n", essid);
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
pr_debug("autojoin_ssid %d\n", result);
if (result) {
@@ -771,9 +775,10 @@ static int p80211wext_giwrate(netdevice_t *dev,
int err = 0;
msg.msgcode = DIDmsg_dot11req_mibget;
+ memset(&mibitem, 0, sizeof(mibitem));
mibitem.did = DIDmib_p2_p2MAC_p2CurrentTxRate;
memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
if (result) {
err = -EFAULT;
@@ -822,9 +827,10 @@ static int p80211wext_giwrts(netdevice_t *dev,
int err = 0;
msg.msgcode = DIDmsg_dot11req_mibget;
+ memset(&mibitem, 0, sizeof(mibitem));
mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
if (result) {
err = -EFAULT;
@@ -857,6 +863,7 @@ static int p80211wext_siwrts(netdevice_t *dev,
}
msg.msgcode = DIDmsg_dot11req_mibget;
+ memset(&mibitem, 0, sizeof(mibitem));
mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11RTSThreshold;
if (rts->disabled)
mibitem.data = 2347;
@@ -864,7 +871,7 @@ static int p80211wext_siwrts(netdevice_t *dev,
mibitem.data = rts->value;
memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
if (result) {
err = -EFAULT;
@@ -886,10 +893,11 @@ static int p80211wext_giwfrag(netdevice_t *dev,
int err = 0;
msg.msgcode = DIDmsg_dot11req_mibget;
+ memset(&mibitem, 0, sizeof(mibitem));
mibitem.did =
DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
if (result) {
err = -EFAULT;
@@ -922,6 +930,7 @@ static int p80211wext_siwfrag(netdevice_t *dev,
}
msg.msgcode = DIDmsg_dot11req_mibset;
+ memset(&mibitem, 0, sizeof(mibitem));
mibitem.did =
DIDmib_dot11mac_dot11OperationTable_dot11FragmentationThreshold;
@@ -931,7 +940,7 @@ static int p80211wext_siwfrag(netdevice_t *dev,
mibitem.data = frag->value;
memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
if (result) {
err = -EFAULT;
@@ -962,10 +971,11 @@ static int p80211wext_giwretry(netdevice_t *dev,
u16 shortretry, longretry, lifetime;
msg.msgcode = DIDmsg_dot11req_mibget;
+ memset(&mibitem, 0, sizeof(mibitem));
mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11ShortRetryLimit;
memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
if (result) {
err = -EFAULT;
@@ -979,7 +989,7 @@ static int p80211wext_giwretry(netdevice_t *dev,
mibitem.did = DIDmib_dot11mac_dot11OperationTable_dot11LongRetryLimit;
memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
if (result) {
err = -EFAULT;
@@ -994,7 +1004,7 @@ static int p80211wext_giwretry(netdevice_t *dev,
DIDmib_dot11mac_dot11OperationTable_dot11MaxTransmitMSDULifetime;
memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
if (result) {
err = -EFAULT;
@@ -1037,6 +1047,8 @@ static int p80211wext_siwretry(netdevice_t *dev,
int result;
int err = 0;
+ memset(&mibitem, 0, sizeof(mibitem));
+
if (!wlan_wext_write) {
err = (-EOPNOTSUPP);
goto exit;
@@ -1055,7 +1067,7 @@ static int p80211wext_siwretry(netdevice_t *dev,
mibitem.data = rrq->value /= 1024;
memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
if (result) {
err = -EFAULT;
@@ -1069,7 +1081,7 @@ static int p80211wext_siwretry(netdevice_t *dev,
memcpy(&msg.mibattribute.data, &mibitem,
sizeof(mibitem));
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
if (result) {
err = -EFAULT;
@@ -1084,7 +1096,7 @@ static int p80211wext_siwretry(netdevice_t *dev,
memcpy(&msg.mibattribute.data, &mibitem,
sizeof(mibitem));
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
if (result) {
err = -EFAULT;
@@ -1114,6 +1126,7 @@ static int p80211wext_siwtxpow(netdevice_t *dev,
}
msg.msgcode = DIDmsg_dot11req_mibset;
+ memset(&mibitem, 0, sizeof(mibitem));
mibitem.did =
DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
if (rrq->fixed == 0)
@@ -1121,7 +1134,7 @@ static int p80211wext_siwtxpow(netdevice_t *dev,
else
mibitem.data = rrq->value;
memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
if (result) {
err = -EFAULT;
@@ -1143,11 +1156,13 @@ static int p80211wext_giwtxpow(netdevice_t *dev,
int err = 0;
msg.msgcode = DIDmsg_dot11req_mibget;
+
+ memset(&mibitem, 0, sizeof(mibitem));
mibitem.did =
DIDmib_dot11phy_dot11PhyTxPowerTable_dot11CurrentTxPowerLevel;
memcpy(&msg.mibattribute.data, &mibitem, sizeof(mibitem));
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
if (result) {
err = -EFAULT;
@@ -1295,7 +1310,7 @@ static int p80211wext_siwscan(netdevice_t *dev,
msg.maxchanneltime.data = 250;
msg.minchanneltime.data = 200;
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
if (result)
err = prism2_result2err(msg.resultcode.data);
@@ -1414,7 +1429,7 @@ static int p80211wext_giwscan(netdevice_t *dev,
msg.msgcode = DIDmsg_dot11req_scan_results;
msg.bssindex.data = i;
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
if ((result != 0) ||
(msg.resultcode.data != P80211ENUM_resultcode_success)) {
break;
@@ -1489,7 +1504,7 @@ static int p80211wext_set_encodeext(struct net_device *dev,
memcpy(wlandev->wep_keys[idx], ext->key, ext->key_len);
memset(&msg, 0, sizeof(msg));
- pstr = (p80211item_pstr32_t *) & msg.mibattribute.data;
+ pstr = (p80211item_pstr32_t *) &msg.mibattribute.data;
memcpy(pstr->data.data, ext->key, ext->key_len);
pstr->data.len = ext->key_len;
switch (idx) {
@@ -1513,7 +1528,7 @@ static int p80211wext_set_encodeext(struct net_device *dev,
break;
}
msg.msgcode = DIDmsg_dot11req_mibset;
- result = p80211req_dorequest(wlandev, (u8 *) & msg);
+ result = p80211req_dorequest(wlandev, (u8 *) &msg);
pr_debug("result (%d)\n", result);
}
return result;
@@ -1729,15 +1744,11 @@ static iw_handler p80211wext_handlers[] = {
struct iw_handler_def p80211wext_handler_def = {
.num_standard = ARRAY_SIZE(p80211wext_handlers),
- .num_private = 0,
- .num_private_args = 0,
.standard = p80211wext_handlers,
- .private = NULL,
- .private_args = NULL,
.get_wireless_stats = p80211wext_get_wireless_stats
};
-int p80211wext_event_associated(wlandevice_t * wlandev, int assoc)
+int p80211wext_event_associated(wlandevice_t *wlandev, int assoc)
{
union iwreq_data data;
diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c
index aaa70ed5771..4be54cea6ad 100644
--- a/drivers/staging/wlan-ng/prism2fw.c
+++ b/drivers/staging/wlan-ng/prism2fw.c
@@ -53,6 +53,7 @@
/* Local Constants */
#define PRISM2_USB_FWFILE "prism2_ru.fw"
+MODULE_FIRMWARE(PRISM2_USB_FWFILE);
#define S3DATA_MAX 5000
#define S3PLUG_MAX 200
@@ -108,9 +109,9 @@ typedef struct pda {
} pda_t;
typedef struct imgchunk {
- u32 addr; /* start address */
- u32 len; /* in bytes */
- u16 crc; /* CRC value (if it falls at a chunk boundary) */
+ u32 addr; /* start address */
+ u32 len; /* in bytes */
+ u16 crc; /* CRC value (if it falls at a chunk boundary) */
u8 *data;
} imgchunk_t;
@@ -204,7 +205,7 @@ int prism2_fwtry(struct usb_device *udev, wlandevice_t *wlandev)
return 1;
}
- printk(KERN_INFO "prism2_usb: %s will be processed, size %d\n",
+ printk(KERN_INFO "prism2_usb: %s will be processed, size %zu\n",
PRISM2_USB_FWFILE, fw_entry->size);
prism2_fwapply((const struct ihex_binrec *)fw_entry->data, wlandev);
@@ -264,7 +265,7 @@ int prism2_fwapply(const struct ihex_binrec *rfptr, wlandevice_t *wlandev)
/* Build the PDA we're going to use. */
if (read_cardpda(&pda, wlandev)) {
printk(KERN_ERR "load_cardpda failed, exiting.\n");
- return (1);
+ return 1;
}
/* read the card's PRI-SUP */
@@ -286,9 +287,8 @@ int prism2_fwapply(const struct ihex_binrec *rfptr, wlandevice_t *wlandev)
/* DIDmsg_dot11req_mibget */
prism2mgmt_mibset_mibget(wlandev, &getmsg);
- if (getmsg.resultcode.data != P80211ENUM_resultcode_success) {
+ if (getmsg.resultcode.data != P80211ENUM_resultcode_success)
printk(KERN_ERR "Couldn't fetch PRI-SUP info\n");
- }
/* Already in host order */
priid.role = *data++;
@@ -301,19 +301,19 @@ int prism2_fwapply(const struct ihex_binrec *rfptr, wlandevice_t *wlandev)
result = read_fwfile(rfptr);
if (result) {
printk(KERN_ERR "Failed to read the data exiting.\n");
- return (1);
+ return 1;
}
result = validate_identity();
if (result) {
printk(KERN_ERR "Incompatible firmware image.\n");
- return (1);
+ return 1;
}
if (startaddr == 0x00000000) {
printk(KERN_ERR "Can't RAM download a Flash image!\n");
- return (1);
+ return 1;
}
/* Make the image chunks */
@@ -323,20 +323,20 @@ int prism2_fwapply(const struct ihex_binrec *rfptr, wlandevice_t *wlandev)
result = plugimage(fchunk, nfchunks, s3plug, ns3plug, &pda);
if (result) {
printk(KERN_ERR "Failed to plug data.\n");
- return (1);
+ return 1;
}
/* Insert any CRCs */
if (crcimage(fchunk, nfchunks, s3crc, ns3crc)) {
printk(KERN_ERR "Failed to insert all CRCs\n");
- return (1);
+ return 1;
}
/* Write the image */
result = writeimage(wlandev, fchunk, nfchunks);
if (result) {
printk(KERN_ERR "Failed to ramwrite image data.\n");
- return (1);
+ return 1;
}
/* clear any allocated memory */
@@ -434,9 +434,8 @@ void free_chunks(imgchunk_t *fchunk, unsigned int *nfchunks)
{
int i;
for (i = 0; i < *nfchunks; i++) {
- if (fchunk[i].data != NULL) {
+ if (fchunk[i].data != NULL)
kfree(fchunk[i].data);
- }
}
*nfchunks = 0;
memset(fchunk, 0, sizeof(*fchunk));
@@ -531,7 +530,7 @@ int mkimage(imgchunk_t *clist, unsigned int *ccnt)
if (clist[i].data == NULL) {
printk(KERN_ERR
"failed to allocate image space, exitting.\n");
- return (1);
+ return 1;
}
memset(clist[i].data, 0, clist[i].len);
pr_debug("chunk[%d]: addr=0x%06x len=%d\n",
@@ -545,15 +544,14 @@ int mkimage(imgchunk_t *clist, unsigned int *ccnt)
for (j = 0; j < *ccnt; j++) {
cstart = clist[j].addr;
cend = cstart + clist[j].len - 1;
- if (s3start >= cstart && s3end <= cend) {
+ if (s3start >= cstart && s3end <= cend)
break;
- }
}
if (((unsigned int)j) >= (*ccnt)) {
printk(KERN_ERR
"s3rec(a=0x%06x,l=%d), no chunk match, exiting.\n",
s3start, s3data[i].len);
- return (1);
+ return 1;
}
coffset = s3start - cstart;
memcpy(clist[j].data + coffset, s3data[i].data, s3data[i].len);
@@ -586,7 +584,7 @@ int mkpdrlist(pda_t *pda)
curroff = 0;
while (curroff < (HFA384x_PDA_LEN_MAX / 2) &&
le16_to_cpu(pda16[curroff + 1]) != HFA384x_PDR_END_OF_PDA) {
- pda->rec[pda->nrec] = (hfa384x_pdrec_t *) & (pda16[curroff]);
+ pda->rec[pda->nrec] = (hfa384x_pdrec_t *) &(pda16[curroff]);
if (le16_to_cpu(pda->rec[pda->nrec]->code) == HFA384x_PDR_NICID) {
memcpy(&nicid, &pda->rec[pda->nrec]->data.nicid,
@@ -623,10 +621,10 @@ int mkpdrlist(pda_t *pda)
printk(KERN_ERR
"no end record found or invalid lengths in "
"PDR data, exiting. %x %d\n", curroff, pda->nrec);
- return (1);
+ return 1;
}
if (le16_to_cpu(pda16[curroff + 1]) == HFA384x_PDR_END_OF_PDA) {
- pda->rec[pda->nrec] = (hfa384x_pdrec_t *) & (pda16[curroff]);
+ pda->rec[pda->nrec] = (hfa384x_pdrec_t *) &(pda16[curroff]);
(pda->nrec)++;
}
return result;
@@ -869,7 +867,7 @@ int read_fwfile(const struct ihex_binrec *record)
ptr16 = (u16 *) record->data;
/* parse what was an S3 srec and put it in the right array */
- switch(addr) {
+ switch (addr) {
case S3ADDR_START:
startaddr = *ptr32;
pr_debug(" S7 start addr, record=%d "
@@ -890,7 +888,7 @@ int read_fwfile(const struct ihex_binrec *record)
s3plug[ns3plug].len);
ns3plug++;
- if ( ns3plug == S3PLUG_MAX ) {
+ if (ns3plug == S3PLUG_MAX) {
printk(KERN_ERR "S3 plugrec limit reached - aborting\n");
return 1;
}
@@ -907,7 +905,7 @@ int read_fwfile(const struct ihex_binrec *record)
s3crc[ns3crc].len,
s3crc[ns3crc].dowrite);
ns3crc++;
- if ( ns3crc == S3CRC_MAX ) {
+ if (ns3crc == S3CRC_MAX) {
printk(KERN_ERR "S3 crcrec limit reached - aborting\n");
return 1;
}
@@ -921,12 +919,12 @@ int read_fwfile(const struct ihex_binrec *record)
rcnt,
s3info[ns3info].len,
s3info[ns3info].type);
- if ( ((s3info[ns3info].len - 1) * sizeof(u16)) > sizeof(s3info[ns3info].info) ) {
+ if (((s3info[ns3info].len - 1) * sizeof(u16)) > sizeof(s3info[ns3info].info)) {
printk(KERN_ERR " S3 inforec length too long - aborting\n");
return 1;
}
- tmpinfo = (u16*)&(s3info[ns3info].info.version);
+ tmpinfo = (u16 *)&(s3info[ns3info].info.version);
pr_debug(" info=");
for (i = 0; i < s3info[ns3info].len - 1; i++) {
tmpinfo[i] = *(ptr16 + 2 + i);
@@ -935,7 +933,7 @@ int read_fwfile(const struct ihex_binrec *record)
pr_debug("\n");
ns3info++;
- if ( ns3info == S3INFO_MAX ) {
+ if (ns3info == S3INFO_MAX) {
printk(KERN_ERR "S3 inforec limit reached - aborting\n");
return 1;
}
@@ -945,7 +943,7 @@ int read_fwfile(const struct ihex_binrec *record)
s3data[ns3data].len = len;
s3data[ns3data].data = (uint8_t *) record->data;
ns3data++;
- if ( ns3data == S3DATA_MAX ) {
+ if (ns3data == S3DATA_MAX) {
printk(KERN_ERR "S3 datarec limit reached - aborting\n");
return 1;
}
@@ -1023,7 +1021,7 @@ int writeimage(wlandevice_t *wlandev, imgchunk_t *fchunk,
rstatemsg.enable.data = P80211ENUM_truth_true;
rstatemsg.exeaddr.data = startaddr;
- msgp = (p80211msg_t *) & rstatemsg;
+ msgp = (p80211msg_t *) &rstatemsg;
result = prism2mgmt_ramdl_state(wlandev, msgp);
if (result) {
printk(KERN_ERR
@@ -1063,7 +1061,7 @@ int writeimage(wlandevice_t *wlandev, imgchunk_t *fchunk,
("Sending xxxdl_write message addr=%06x len=%d.\n",
currdaddr, currlen);
- msgp = (p80211msg_t *) & rwritemsg;
+ msgp = (p80211msg_t *) &rwritemsg;
result = prism2mgmt_ramdl_write(wlandev, msgp);
/* Check the results */
@@ -1090,7 +1088,7 @@ int writeimage(wlandevice_t *wlandev, imgchunk_t *fchunk,
rstatemsg.enable.data = P80211ENUM_truth_false;
rstatemsg.exeaddr.data = 0;
- msgp = (p80211msg_t *) & rstatemsg;
+ msgp = (p80211msg_t *) &rstatemsg;
result = prism2mgmt_ramdl_state(wlandev, msgp);
if (result) {
printk(KERN_ERR
@@ -1161,7 +1159,7 @@ int validate_identity(void)
/* SEC compat range */
if ((s3info[i].info.compat.role == 1) &&
(s3info[i].info.compat.id == 4)) {
-
+ /* FIXME: isn't something missing here? */
}
break;
@@ -1196,8 +1194,9 @@ int validate_identity(void)
pr_debug("Unknown inforec type %d\n", s3info[i].type);
}
}
- // walk through
+ /* walk through */
- if (trump && (result != 2)) result = 0;
+ if (trump && (result != 2))
+ result = 0;
return result;
}
diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c
index 9f7d96cae8e..ad163da72ae 100644
--- a/drivers/staging/wlan-ng/prism2mgmt.c
+++ b/drivers/staging/wlan-ng/prism2mgmt.c
@@ -67,7 +67,7 @@
#include <linux/wireless.h>
#include <linux/netdevice.h>
#include <linux/delay.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <asm/byteorder.h>
#include <linux/random.h>
#include <linux/usb.h>
@@ -541,7 +541,7 @@ int prism2mgmt_start(wlandevice_t *wlandev, void *msgp)
/*** STATION ***/
/* Set the REQUIRED config items */
/* SSID */
- pstr = (p80211pstrd_t *) & (msg->ssid.data);
+ pstr = (p80211pstrd_t *) &(msg->ssid.data);
prism2mgmt_pstr2bytestr(p2bytestr, pstr);
result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFOWNSSID,
bytebuf, HFA384x_RID_CNFOWNSSID_LEN);
@@ -1034,7 +1034,7 @@ int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp)
/* Set the ssid */
memset(bytebuf, 0, 256);
- pstr = (p80211pstrd_t *) & (msg->ssid.data);
+ pstr = (p80211pstrd_t *) &(msg->ssid.data);
prism2mgmt_pstr2bytestr(p2bytestr, pstr);
result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID,
bytebuf,
@@ -1123,8 +1123,8 @@ int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp)
if (hw->presniff_port_type != 0) {
word = hw->presniff_port_type;
result = hfa384x_drvr_setconfig16(hw,
- HFA384x_RID_CNFPORTTYPE,
- word);
+ HFA384x_RID_CNFPORTTYPE,
+ word);
if (result) {
pr_debug
("failed to restore porttype, result=%d\n",
@@ -1156,10 +1156,8 @@ int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp)
if (wlandev->netdev->type == ARPHRD_ETHER) {
/* Save macport 0 state */
result = hfa384x_drvr_getconfig16(hw,
- HFA384x_RID_CNFPORTTYPE,
- &
- (hw->
- presniff_port_type));
+ HFA384x_RID_CNFPORTTYPE,
+ &(hw->presniff_port_type));
if (result) {
pr_debug
("failed to read porttype, result=%d\n",
@@ -1168,10 +1166,8 @@ int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp)
}
/* Save the wepflags state */
result = hfa384x_drvr_getconfig16(hw,
- HFA384x_RID_CNFWEPFLAGS,
- &
- (hw->
- presniff_wepflags));
+ HFA384x_RID_CNFWEPFLAGS,
+ &(hw->presniff_wepflags));
if (result) {
pr_debug
("failed to read wepflags, result=%d\n",
@@ -1218,8 +1214,8 @@ int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp)
/* Set the port type to pIbss */
word = HFA384x_PORTTYPE_PSUEDOIBSS;
result = hfa384x_drvr_setconfig16(hw,
- HFA384x_RID_CNFPORTTYPE,
- word);
+ HFA384x_RID_CNFPORTTYPE,
+ word);
if (result) {
pr_debug
("failed to set porttype %d, result=%d\n",
@@ -1235,8 +1231,8 @@ int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp)
HFA384x_WEPFLAGS_DISABLE_RXCRYPT;
result =
hfa384x_drvr_setconfig16(hw,
- HFA384x_RID_CNFWEPFLAGS,
- word);
+ HFA384x_RID_CNFWEPFLAGS,
+ word);
}
if (result) {
diff --git a/drivers/staging/wlan-ng/prism2mgmt.h b/drivers/staging/wlan-ng/prism2mgmt.h
index bdf2b3e0325..07eecebeb6c 100644
--- a/drivers/staging/wlan-ng/prism2mgmt.h
+++ b/drivers/staging/wlan-ng/prism2mgmt.h
@@ -63,43 +63,43 @@
extern int prism2_reset_holdtime;
extern int prism2_reset_settletime;
-u32 prism2sta_ifstate(wlandevice_t * wlandev, u32 ifstate);
+u32 prism2sta_ifstate(wlandevice_t *wlandev, u32 ifstate);
-void prism2sta_ev_info(wlandevice_t * wlandev, hfa384x_InfFrame_t * inf);
-void prism2sta_ev_txexc(wlandevice_t * wlandev, u16 status);
-void prism2sta_ev_tx(wlandevice_t * wlandev, u16 status);
-void prism2sta_ev_rx(wlandevice_t * wlandev, struct sk_buff *skb);
-void prism2sta_ev_alloc(wlandevice_t * wlandev);
+void prism2sta_ev_info(wlandevice_t *wlandev, hfa384x_InfFrame_t *inf);
+void prism2sta_ev_txexc(wlandevice_t *wlandev, u16 status);
+void prism2sta_ev_tx(wlandevice_t *wlandev, u16 status);
+void prism2sta_ev_rx(wlandevice_t *wlandev, struct sk_buff *skb);
+void prism2sta_ev_alloc(wlandevice_t *wlandev);
-int prism2mgmt_mibset_mibget(wlandevice_t * wlandev, void *msgp);
-int prism2mgmt_scan(wlandevice_t * wlandev, void *msgp);
-int prism2mgmt_scan_results(wlandevice_t * wlandev, void *msgp);
-int prism2mgmt_start(wlandevice_t * wlandev, void *msgp);
-int prism2mgmt_wlansniff(wlandevice_t * wlandev, void *msgp);
-int prism2mgmt_readpda(wlandevice_t * wlandev, void *msgp);
-int prism2mgmt_ramdl_state(wlandevice_t * wlandev, void *msgp);
-int prism2mgmt_ramdl_write(wlandevice_t * wlandev, void *msgp);
-int prism2mgmt_flashdl_state(wlandevice_t * wlandev, void *msgp);
-int prism2mgmt_flashdl_write(wlandevice_t * wlandev, void *msgp);
-int prism2mgmt_autojoin(wlandevice_t * wlandev, void *msgp);
+int prism2mgmt_mibset_mibget(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_scan(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_start(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_wlansniff(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_readpda(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_ramdl_state(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_ramdl_write(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_flashdl_state(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_flashdl_write(wlandevice_t *wlandev, void *msgp);
+int prism2mgmt_autojoin(wlandevice_t *wlandev, void *msgp);
/*---------------------------------------------------------------
* conversion functions going between wlan message data types and
* Prism2 data types
---------------------------------------------------------------*/
/* byte area conversion functions*/
-void prism2mgmt_pstr2bytearea(u8 * bytearea, p80211pstrd_t * pstr);
-void prism2mgmt_bytearea2pstr(u8 * bytearea, p80211pstrd_t * pstr, int len);
+void prism2mgmt_pstr2bytearea(u8 *bytearea, p80211pstrd_t *pstr);
+void prism2mgmt_bytearea2pstr(u8 *bytearea, p80211pstrd_t *pstr, int len);
/* byte string conversion functions*/
-void prism2mgmt_pstr2bytestr(hfa384x_bytestr_t * bytestr, p80211pstrd_t * pstr);
-void prism2mgmt_bytestr2pstr(hfa384x_bytestr_t * bytestr, p80211pstrd_t * pstr);
+void prism2mgmt_pstr2bytestr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr);
+void prism2mgmt_bytestr2pstr(hfa384x_bytestr_t *bytestr, p80211pstrd_t *pstr);
/* functions to convert Group Addresses */
-void prism2mgmt_get_grpaddr(u32 did, p80211pstrd_t * pstr, hfa384x_t * priv);
+void prism2mgmt_get_grpaddr(u32 did, p80211pstrd_t *pstr, hfa384x_t *priv);
int prism2mgmt_set_grpaddr(u32 did,
- u8 * prism2buf, p80211pstrd_t * pstr,
- hfa384x_t * priv);
+ u8 *prism2buf, p80211pstrd_t *pstr,
+ hfa384x_t *priv);
int prism2mgmt_get_grpaddr_index(u32 did);
void prism2sta_processing_defer(struct work_struct *data);
diff --git a/drivers/staging/wlan-ng/prism2mib.c b/drivers/staging/wlan-ng/prism2mib.c
index 2fff0a110bc..98a5d58c3f5 100644
--- a/drivers/staging/wlan-ng/prism2mib.c
+++ b/drivers/staging/wlan-ng/prism2mib.c
@@ -114,7 +114,7 @@ static int prism2mib_flag(mibrec_t *mib,
static int prism2mib_wepdefaultkey(mibrec_t *mib,
int isget,
- wlandevice_t * wlandev,
+ wlandevice_t *wlandev,
hfa384x_t *hw,
p80211msg_dot11req_mibset_t *msg,
void *data);
@@ -726,7 +726,7 @@ static int prism2mib_priv(mibrec_t *mib,
if (isget) {
hfa384x_drvr_getconfig(hw,
HFA384x_RID_CNFWPADATA,
- (u8 *) & wpa,
+ (u8 *) &wpa,
sizeof(wpa));
pstr->len = le16_to_cpu(wpa.datalen);
memcpy(pstr->data, wpa.data, pstr->len);
@@ -736,9 +736,9 @@ static int prism2mib_priv(mibrec_t *mib,
result =
hfa384x_drvr_setconfig(hw,
- HFA384x_RID_CNFWPADATA,
- (u8 *) & wpa,
- sizeof(wpa));
+ HFA384x_RID_CNFWPADATA,
+ (u8 *) &wpa,
+ sizeof(wpa));
}
break;
}
diff --git a/drivers/staging/wlan-ng/prism2sta.c b/drivers/staging/wlan-ng/prism2sta.c
index 50f301d6521..31ac8da39c8 100644
--- a/drivers/staging/wlan-ng/prism2sta.c
+++ b/drivers/staging/wlan-ng/prism2sta.c
@@ -64,7 +64,7 @@
#include <linux/byteorder/generic.h>
#include <linux/ctype.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <linux/delay.h>
#include <asm/byteorder.h>
#include <linux/if_arp.h>
@@ -1023,13 +1023,13 @@ static void prism2sta_inf_tallies(wlandevice_t *wlandev,
cnt = sizeof(hfa384x_CommTallies32_t) / sizeof(u32);
if (inf->framelen > 22) {
- dst = (u32 *) & hw->tallies;
- src32 = (u32 *) & inf->info.commtallies32;
+ dst = (u32 *) &hw->tallies;
+ src32 = (u32 *) &inf->info.commtallies32;
for (i = 0; i < cnt; i++, dst++, src32++)
*dst += le32_to_cpu(*src32);
} else {
- dst = (u32 *) & hw->tallies;
- src16 = (u16 *) & inf->info.commtallies16;
+ dst = (u32 *) &hw->tallies;
+ src16 = (u16 *) &inf->info.commtallies16;
for (i = 0; i < cnt; i++, dst++, src16++)
*dst += le16_to_cpu(*src16);
}
@@ -1280,7 +1280,7 @@ void prism2sta_processing_defer(struct work_struct *data)
HFA384x_RID_CURRENTSSID, result);
goto failed;
}
- prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *) & ssid,
+ prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *) &ssid,
(p80211pstrd_t *) &
wlandev->ssid);
@@ -1368,8 +1368,8 @@ void prism2sta_processing_defer(struct work_struct *data)
HFA384x_RID_CURRENTSSID, result);
goto failed;
}
- prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *) & ssid,
- (p80211pstrd_t *) & wlandev->ssid);
+ prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *) &ssid,
+ (p80211pstrd_t *) &wlandev->ssid);
hw->link_status = HFA384x_LINK_CONNECTED;
netif_carrier_on(wlandev->netdev);
@@ -2028,8 +2028,8 @@ void prism2sta_commsqual_defer(struct work_struct *data)
HFA384x_RID_CURRENTSSID, result);
goto done;
}
- prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *) & ssid,
- (p80211pstrd_t *) & wlandev->ssid);
+ prism2mgmt_bytestr2pstr((hfa384x_bytestr_t *) &ssid,
+ (p80211pstrd_t *) &wlandev->ssid);
/* Reschedule timer */
mod_timer(&hw->commsqual_timer, jiffies + HZ);
diff --git a/drivers/staging/wlan-ng/prism2usb.c b/drivers/staging/wlan-ng/prism2usb.c
index 9dde68be8d7..501d27f74c7 100644
--- a/drivers/staging/wlan-ng/prism2usb.c
+++ b/drivers/staging/wlan-ng/prism2usb.c
@@ -24,8 +24,9 @@ static struct usb_device_id usb_prism_tbl[] = {
(0x066b, 0x2213, "Linksys WUSB12v1.1 11Mbps WLAN USB Adapter")},
{PRISM_USB_DEVICE
(0x067c, 0x1022, "Siemens SpeedStream 1022 11Mbps WLAN USB Adapter")},
- {PRISM_USB_DEVICE(0x049f, 0x0033,
- "Compaq/Intel W100 PRO/Wireless 11Mbps multiport WLAN Adapter")},
+ {PRISM_USB_DEVICE
+ (0x049f, 0x0033,
+ "Compaq/Intel W100 PRO/Wireless 11Mbps multiport WLAN Adapter")},
{PRISM_USB_DEVICE
(0x0411, 0x0016, "Melco WLI-USB-S11 11Mbps WLAN Adapter")},
{PRISM_USB_DEVICE
@@ -55,7 +56,6 @@ static struct usb_device_id usb_prism_tbl[] = {
(0x04f1, 0x3009, "JVC MP-XP7250 Builtin USB WLAN Adapter")},
{PRISM_USB_DEVICE(0x0846, 0x4110, "NetGear MA111")},
{PRISM_USB_DEVICE(0x03f3, 0x0020, "Adaptec AWN-8020 USB WLAN Adapter")},
-/* {PRISM_USB_DEVICE(0x0ace, 0x1201, "ZyDAS ZD1201 Wireless USB Adapter")}, */
{PRISM_USB_DEVICE(0x2821, 0x3300, "ASUS-WL140 Wireless USB Adapter")},
{PRISM_USB_DEVICE(0x2001, 0x3700, "DWL-122 Wireless USB Adapter")},
{PRISM_USB_DEVICE
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index 8aa1955f35e..1da73ecd979 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -44,17 +44,6 @@ config UIO_PDRV_GENIRQ
If you don't know what to do here, say N.
-config UIO_SMX
- tristate "SMX cryptengine UIO interface"
- help
- Userspace IO interface to the Cryptography engine found on the
- Nias Digital SMX boards. These will be available from Q4 2008
- from http://www.niasdigital.com. The userspace part of this
- driver will be released under the GPL at the same time as the
- hardware and will be able to be downloaded from the same site.
-
- If you compile this as a module, it will be called uio_smx.
-
config UIO_AEC
tristate "AEC video timestamp device"
depends on PCI
@@ -74,6 +63,7 @@ config UIO_AEC
config UIO_SERCOS3
tristate "Automata Sercos III PCI card driver"
+ depends on PCI
help
Userspace I/O interface for the Sercos III PCI card from
Automata GmbH. The userspace part of this driver will be
@@ -87,11 +77,21 @@ config UIO_SERCOS3
config UIO_PCI_GENERIC
tristate "Generic driver for PCI 2.3 and PCI Express cards"
depends on PCI
- default n
help
Generic driver that you can bind, dynamically, to any
PCI 2.3 compliant and PCI Express card. It is useful,
primarily, for virtualization scenarios.
If you compile this as a module, it will be called uio_pci_generic.
+config UIO_NETX
+ tristate "Hilscher NetX Card driver"
+ depends on PCI
+ help
+ Driver for Hilscher NetX based fieldbus cards (cifX, comX).
+ This driver requires a userspace component that comes with the card
+ or is available from Hilscher (http://www.hilscher.com).
+
+ To compile this driver as a module, choose M here; the module
+ will be called uio_netx.
+
endif
diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile
index 73b2e751672..18fd818c5b9 100644
--- a/drivers/uio/Makefile
+++ b/drivers/uio/Makefile
@@ -2,7 +2,7 @@ obj-$(CONFIG_UIO) += uio.o
obj-$(CONFIG_UIO_CIF) += uio_cif.o
obj-$(CONFIG_UIO_PDRV) += uio_pdrv.o
obj-$(CONFIG_UIO_PDRV_GENIRQ) += uio_pdrv_genirq.o
-obj-$(CONFIG_UIO_SMX) += uio_smx.o
obj-$(CONFIG_UIO_AEC) += uio_aec.o
obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o
obj-$(CONFIG_UIO_PCI_GENERIC) += uio_pci_generic.o
+obj-$(CONFIG_UIO_NETX) += uio_netx.o
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index e941367dd28..4de382acd8f 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -129,7 +129,7 @@ static ssize_t map_type_show(struct kobject *kobj, struct attribute *attr,
return entry->show(mem, buf);
}
-static struct sysfs_ops map_sysfs_ops = {
+static const struct sysfs_ops map_sysfs_ops = {
.show = map_type_show,
};
@@ -217,7 +217,7 @@ static ssize_t portio_type_show(struct kobject *kobj, struct attribute *attr,
return entry->show(port, buf);
}
-static struct sysfs_ops portio_sysfs_ops = {
+static const struct sysfs_ops portio_sysfs_ops = {
.show = portio_type_show,
};
diff --git a/drivers/uio/uio_netx.c b/drivers/uio/uio_netx.c
new file mode 100644
index 00000000000..afbf0bd55cc
--- /dev/null
+++ b/drivers/uio/uio_netx.c
@@ -0,0 +1,172 @@
+/*
+ * UIO driver for Hilscher NetX based fieldbus cards (cifX, comX).
+ * See http://www.hilscher.com for details.
+ *
+ * (C) 2007 Hans J. Koch <hjk@linutronix.de>
+ * (C) 2008 Manuel Traut <manut@linutronix.de>
+ *
+ * Licensed under GPL version 2 only.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/uio_driver.h>
+
+#define PCI_VENDOR_ID_HILSCHER 0x15CF
+#define PCI_DEVICE_ID_HILSCHER_NETX 0x0000
+#define PCI_SUBDEVICE_ID_NXSB_PCA 0x3235
+#define PCI_SUBDEVICE_ID_NXPCA 0x3335
+
+#define DPM_HOST_INT_EN0 0xfff0
+#define DPM_HOST_INT_STAT0 0xffe0
+
+#define DPM_HOST_INT_MASK 0xe600ffff
+#define DPM_HOST_INT_GLOBAL_EN 0x80000000
+
+static irqreturn_t netx_handler(int irq, struct uio_info *dev_info)
+{
+ void __iomem *int_enable_reg = dev_info->mem[0].internal_addr
+ + DPM_HOST_INT_EN0;
+ void __iomem *int_status_reg = dev_info->mem[0].internal_addr
+ + DPM_HOST_INT_STAT0;
+
+ /* Is one of our interrupts enabled and active ? */
+ if (!(ioread32(int_enable_reg) & ioread32(int_status_reg)
+ & DPM_HOST_INT_MASK))
+ return IRQ_NONE;
+
+ /* Disable interrupt */
+ iowrite32(ioread32(int_enable_reg) & ~DPM_HOST_INT_GLOBAL_EN,
+ int_enable_reg);
+ return IRQ_HANDLED;
+}
+
+static int __devinit netx_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
+{
+ struct uio_info *info;
+ int bar;
+
+ info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ if (pci_enable_device(dev))
+ goto out_free;
+
+ if (pci_request_regions(dev, "netx"))
+ goto out_disable;
+
+ switch (id->device) {
+ case PCI_DEVICE_ID_HILSCHER_NETX:
+ bar = 0;
+ info->name = "netx";
+ break;
+ default:
+ bar = 2;
+ info->name = "netx_plx";
+ }
+
+ /* BAR0 or 2 points to the card's dual port memory */
+ info->mem[0].addr = pci_resource_start(dev, bar);
+ if (!info->mem[0].addr)
+ goto out_release;
+ info->mem[0].internal_addr = ioremap(pci_resource_start(dev, bar),
+ pci_resource_len(dev, bar));
+
+ if (!info->mem[0].internal_addr)
+ goto out_release;
+
+ info->mem[0].size = pci_resource_len(dev, bar);
+ info->mem[0].memtype = UIO_MEM_PHYS;
+ info->irq = dev->irq;
+ info->irq_flags = IRQF_SHARED;
+ info->handler = netx_handler;
+ info->version = "0.0.1";
+
+ /* Make sure all interrupts are disabled */
+ iowrite32(0, info->mem[0].internal_addr + DPM_HOST_INT_EN0);
+
+ if (uio_register_device(&dev->dev, info))
+ goto out_unmap;
+
+ pci_set_drvdata(dev, info);
+ dev_info(&dev->dev, "Found %s card, registered UIO device.\n",
+ info->name);
+
+ return 0;
+
+out_unmap:
+ iounmap(info->mem[0].internal_addr);
+out_release:
+ pci_release_regions(dev);
+out_disable:
+ pci_disable_device(dev);
+out_free:
+ kfree(info);
+ return -ENODEV;
+}
+
+static void netx_pci_remove(struct pci_dev *dev)
+{
+ struct uio_info *info = pci_get_drvdata(dev);
+
+ /* Disable all interrupts */
+ iowrite32(0, info->mem[0].internal_addr + DPM_HOST_INT_EN0);
+ uio_unregister_device(info);
+ pci_release_regions(dev);
+ pci_disable_device(dev);
+ pci_set_drvdata(dev, NULL);
+ iounmap(info->mem[0].internal_addr);
+
+ kfree(info);
+}
+
+static struct pci_device_id netx_pci_ids[] = {
+ {
+ .vendor = PCI_VENDOR_ID_HILSCHER,
+ .device = PCI_DEVICE_ID_HILSCHER_NETX,
+ .subvendor = 0,
+ .subdevice = 0,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_PLX,
+ .device = PCI_DEVICE_ID_PLX_9030,
+ .subvendor = PCI_VENDOR_ID_PLX,
+ .subdevice = PCI_SUBDEVICE_ID_NXSB_PCA,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_PLX,
+ .device = PCI_DEVICE_ID_PLX_9030,
+ .subvendor = PCI_VENDOR_ID_PLX,
+ .subdevice = PCI_SUBDEVICE_ID_NXPCA,
+ },
+ { 0, }
+};
+
+static struct pci_driver netx_pci_driver = {
+ .name = "netx",
+ .id_table = netx_pci_ids,
+ .probe = netx_pci_probe,
+ .remove = netx_pci_remove,
+};
+
+static int __init netx_init_module(void)
+{
+ return pci_register_driver(&netx_pci_driver);
+}
+
+static void __exit netx_exit_module(void)
+{
+ pci_unregister_driver(&netx_pci_driver);
+}
+
+module_init(netx_init_module);
+module_exit(netx_exit_module);
+
+MODULE_DEVICE_TABLE(pci, netx_pci_ids);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Hans J. Koch, Manuel Traut");
diff --git a/drivers/uio/uio_smx.c b/drivers/uio/uio_smx.c
deleted file mode 100644
index 44054a650a8..00000000000
--- a/drivers/uio/uio_smx.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * UIO SMX Cryptengine driver.
- *
- * (C) 2008 Nias Digital P/L <bn@niasdigital.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/device.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/uio_driver.h>
-#include <linux/io.h>
-
-#define DRV_NAME "smx-ce"
-#define DRV_VERSION "0.03"
-
-#define SMX_CSR 0x00000000
-#define SMX_EnD 0x00000001
-#define SMX_RUN 0x00000002
-#define SMX_DRDY 0x00000004
-#define SMX_ERR 0x00000008
-
-static irqreturn_t smx_handler(int irq, struct uio_info *dev_info)
-{
- void __iomem *csr = dev_info->mem[0].internal_addr + SMX_CSR;
-
- u32 status = ioread32(csr);
-
- if (!(status & SMX_DRDY))
- return IRQ_NONE;
-
- /* Disable interrupt */
- iowrite32(status & ~SMX_DRDY, csr);
- return IRQ_HANDLED;
-}
-
-static int __devinit smx_ce_probe(struct platform_device *dev)
-{
-
- int ret = -ENODEV;
- struct uio_info *info;
- struct resource *regs;
-
- info = kzalloc(sizeof(struct uio_info), GFP_KERNEL);
- if (!info)
- return -ENOMEM;
-
- regs = platform_get_resource(dev, IORESOURCE_MEM, 0);
- if (!regs) {
- dev_err(&dev->dev, "No memory resource specified\n");
- goto out_free;
- }
-
- info->mem[0].addr = regs->start;
- if (!info->mem[0].addr) {
- dev_err(&dev->dev, "Invalid memory resource\n");
- goto out_free;
- }
-
- info->mem[0].size = regs->end - regs->start + 1;
- info->mem[0].internal_addr = ioremap(regs->start, info->mem[0].size);
-
- if (!info->mem[0].internal_addr) {
- dev_err(&dev->dev, "Can't remap memory address range\n");
- goto out_free;
- }
-
- info->mem[0].memtype = UIO_MEM_PHYS;
-
- info->name = "smx-ce";
- info->version = "0.03";
-
- info->irq = platform_get_irq(dev, 0);
- if (info->irq < 0) {
- ret = info->irq;
- dev_err(&dev->dev, "No (or invalid) IRQ resource specified\n");
- goto out_unmap;
- }
-
- info->irq_flags = IRQF_SHARED;
- info->handler = smx_handler;
-
- platform_set_drvdata(dev, info);
-
- ret = uio_register_device(&dev->dev, info);
-
- if (ret)
- goto out_unmap;
-
- return 0;
-
-out_unmap:
- iounmap(info->mem[0].internal_addr);
-out_free:
- kfree(info);
-
- return ret;
-}
-
-static int __devexit smx_ce_remove(struct platform_device *dev)
-{
- struct uio_info *info = platform_get_drvdata(dev);
-
- uio_unregister_device(info);
- platform_set_drvdata(dev, NULL);
- iounmap(info->mem[0].internal_addr);
-
- kfree(info);
-
- return 0;
-}
-
-static struct platform_driver smx_ce_driver = {
- .probe = smx_ce_probe,
- .remove = __devexit_p(smx_ce_remove),
- .driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
- },
-};
-
-static int __init smx_ce_init_module(void)
-{
- return platform_driver_register(&smx_ce_driver);
-}
-module_init(smx_ce_init_module);
-
-static void __exit smx_ce_exit_module(void)
-{
- platform_driver_unregister(&smx_ce_driver);
-}
-module_exit(smx_ce_exit_module);
-
-MODULE_LICENSE("GPL v2");
-MODULE_VERSION(DRV_VERSION);
-MODULE_AUTHOR("Ben Nizette <bn@niasdigital.com>");
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index c83c975152a..d41811bfef2 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -117,13 +117,20 @@ static const char *format_endpt =
* However, these will come from functions that return ptrs to each of them.
*/
-static DECLARE_WAIT_QUEUE_HEAD(deviceconndiscwq);
-/* guarded by usbfs_mutex */
-static unsigned int conndiscevcnt;
-
-/* this struct stores the poll state for <mountpoint>/devices pollers */
-struct usb_device_status {
- unsigned int lastev;
+/*
+ * Wait for an connect/disconnect event to happen. We initialize
+ * the event counter with an odd number, and each event will increment
+ * the event counter by two, so it will always _stay_ odd. That means
+ * that it will never be zero, so "event 0" will never match a current
+ * event, and thus 'poll' will always trigger as readable for the first
+ * time it gets called.
+ */
+static struct device_connect_event {
+ atomic_t count;
+ wait_queue_head_t wait;
+} device_event = {
+ .count = ATOMIC_INIT(1),
+ .wait = __WAIT_QUEUE_HEAD_INITIALIZER(device_event.wait)
};
struct class_info {
@@ -157,10 +164,8 @@ static const struct class_info clas_info[] =
void usbfs_conn_disc_event(void)
{
- mutex_lock(&usbfs_mutex);
- conndiscevcnt++;
- mutex_unlock(&usbfs_mutex);
- wake_up(&deviceconndiscwq);
+ atomic_add(2, &device_event.count);
+ wake_up(&device_event.wait);
}
static const char *class_decode(const int class)
@@ -632,42 +637,16 @@ static ssize_t usb_device_read(struct file *file, char __user *buf,
static unsigned int usb_device_poll(struct file *file,
struct poll_table_struct *wait)
{
- struct usb_device_status *st;
- unsigned int mask = 0;
-
- mutex_lock(&usbfs_mutex);
- st = file->private_data;
- if (!st) {
- st = kmalloc(sizeof(struct usb_device_status), GFP_KERNEL);
- if (!st) {
- mutex_unlock(&usbfs_mutex);
- return POLLIN;
- }
-
- st->lastev = conndiscevcnt;
- file->private_data = st;
- mask = POLLIN;
- }
+ unsigned int event_count;
- if (file->f_mode & FMODE_READ)
- poll_wait(file, &deviceconndiscwq, wait);
- if (st->lastev != conndiscevcnt)
- mask |= POLLIN;
- st->lastev = conndiscevcnt;
- mutex_unlock(&usbfs_mutex);
- return mask;
-}
+ poll_wait(file, &device_event.wait, wait);
-static int usb_device_open(struct inode *inode, struct file *file)
-{
- file->private_data = NULL;
- return 0;
-}
+ event_count = atomic_read(&device_event.count);
+ if (file->f_version != event_count) {
+ file->f_version = event_count;
+ return POLLIN | POLLRDNORM;
+ }
-static int usb_device_release(struct inode *inode, struct file *file)
-{
- kfree(file->private_data);
- file->private_data = NULL;
return 0;
}
@@ -699,6 +678,4 @@ const struct file_operations usbfs_devices_fops = {
.llseek = usb_device_lseek,
.read = usb_device_read,
.poll = usb_device_poll,
- .open = usb_device_open,
- .release = usb_device_release,
};
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index a7037bf8168..f3c233806fa 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -489,10 +489,10 @@ void usb_driver_release_interface(struct usb_driver *driver,
if (device_is_registered(dev)) {
device_release_driver(dev);
} else {
- down(&dev->sem);
+ device_lock(dev);
usb_unbind_interface(dev);
dev->driver = NULL;
- up(&dev->sem);
+ device_unlock(dev);
}
}
EXPORT_SYMBOL_GPL(usb_driver_release_interface);
diff --git a/drivers/uwb/driver.c b/drivers/uwb/driver.c
index da77e41de99..08bd6dbfd4a 100644
--- a/drivers/uwb/driver.c
+++ b/drivers/uwb/driver.c
@@ -74,13 +74,16 @@
unsigned long beacon_timeout_ms = 500;
static
-ssize_t beacon_timeout_ms_show(struct class *class, char *buf)
+ssize_t beacon_timeout_ms_show(struct class *class,
+ struct class_attribute *attr,
+ char *buf)
{
return scnprintf(buf, PAGE_SIZE, "%lu\n", beacon_timeout_ms);
}
static
ssize_t beacon_timeout_ms_store(struct class *class,
+ struct class_attribute *attr,
const char *buf, size_t size)
{
unsigned long bt;
diff --git a/drivers/uwb/umc-bus.c b/drivers/uwb/umc-bus.c
index cdd6c8efc9f..5fad4e791b3 100644
--- a/drivers/uwb/umc-bus.c
+++ b/drivers/uwb/umc-bus.c
@@ -62,12 +62,12 @@ int umc_controller_reset(struct umc_dev *umc)
struct device *parent = umc->dev.parent;
int ret = 0;
- if(down_trylock(&parent->sem))
+ if (device_trylock(parent))
return -EAGAIN;
ret = device_for_each_child(parent, parent, umc_bus_pre_reset_helper);
if (ret >= 0)
ret = device_for_each_child(parent, parent, umc_bus_post_reset_helper);
- up(&parent->sem);
+ device_unlock(parent);
return ret;
}
diff --git a/drivers/uwb/uwb-internal.h b/drivers/uwb/uwb-internal.h
index d5bcfc1c227..157485c862c 100644
--- a/drivers/uwb/uwb-internal.h
+++ b/drivers/uwb/uwb-internal.h
@@ -366,12 +366,12 @@ struct dentry *uwb_dbg_create_pal_dir(struct uwb_pal *pal);
static inline void uwb_dev_lock(struct uwb_dev *uwb_dev)
{
- down(&uwb_dev->dev.sem);
+ device_lock(&uwb_dev->dev);
}
static inline void uwb_dev_unlock(struct uwb_dev *uwb_dev)
{
- up(&uwb_dev->dev.sem);
+ device_unlock(&uwb_dev->dev);
}
#endif /* #ifndef __UWB_INTERNAL_H__ */
diff --git a/drivers/uwb/wlp/sysfs.c b/drivers/uwb/wlp/sysfs.c
index 0370399ff4b..6627c94cc85 100644
--- a/drivers/uwb/wlp/sysfs.c
+++ b/drivers/uwb/wlp/sysfs.c
@@ -615,8 +615,7 @@ ssize_t wlp_wss_attr_store(struct kobject *kobj, struct attribute *attr,
return ret;
}
-static
-struct sysfs_ops wss_sysfs_ops = {
+static const struct sysfs_ops wss_sysfs_ops = {
.show = wlp_wss_attr_show,
.store = wlp_wss_attr_store,
};
diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c
index 0bcc59eb37f..43d7d506736 100644
--- a/drivers/video/acornfb.c
+++ b/drivers/video/acornfb.c
@@ -1221,7 +1221,7 @@ free_unused_pages(unsigned int virtual_start, unsigned int virtual_end)
printk("acornfb: freed %dK memory\n", mb_freed);
}
-static int __init acornfb_probe(struct platform_device *dev)
+static int __devinit acornfb_probe(struct platform_device *dev)
{
unsigned long size;
u_int h_sync, v_sync;
diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c
index c3431691c9f..01554d69652 100644
--- a/drivers/video/arcfb.c
+++ b/drivers/video/arcfb.c
@@ -504,7 +504,7 @@ static struct fb_ops arcfb_ops = {
.fb_ioctl = arcfb_ioctl,
};
-static int __init arcfb_probe(struct platform_device *dev)
+static int __devinit arcfb_probe(struct platform_device *dev)
{
struct fb_info *info;
int retval = -ENOMEM;
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c
new file mode 100644
index 00000000000..b8f705cca43
--- /dev/null
+++ b/drivers/video/backlight/88pm860x_bl.c
@@ -0,0 +1,304 @@
+/*
+ * Backlight driver for Marvell Semiconductor 88PM8606
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ * Haojian Zhuang <haojian.zhuang@marvell.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/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/i2c.h>
+#include <linux/backlight.h>
+#include <linux/mfd/88pm860x.h>
+
+#define MAX_BRIGHTNESS (0xFF)
+#define MIN_BRIGHTNESS (0)
+
+#define CURRENT_MASK (0x1F << 1)
+
+struct pm860x_backlight_data {
+ struct pm860x_chip *chip;
+ struct i2c_client *i2c;
+ int current_brightness;
+ int port;
+ int pwm;
+ int iset;
+};
+
+static inline int wled_a(int port)
+{
+ int ret;
+
+ ret = ((port - PM8606_BACKLIGHT1) << 1) + 2;
+ return ret;
+}
+
+static inline int wled_b(int port)
+{
+ int ret;
+
+ ret = ((port - PM8606_BACKLIGHT1) << 1) + 3;
+ return ret;
+}
+
+/* WLED2 & WLED3 share the same IDC */
+static inline int wled_idc(int port)
+{
+ int ret;
+
+ switch (port) {
+ case PM8606_BACKLIGHT1:
+ case PM8606_BACKLIGHT2:
+ ret = ((port - PM8606_BACKLIGHT1) << 1) + 3;
+ break;
+ case PM8606_BACKLIGHT3:
+ default:
+ ret = ((port - PM8606_BACKLIGHT2) << 1) + 3;
+ break;
+ }
+ return ret;
+}
+
+static int pm860x_backlight_set(struct backlight_device *bl, int brightness)
+{
+ struct pm860x_backlight_data *data = bl_get_data(bl);
+ struct pm860x_chip *chip = data->chip;
+ unsigned char value;
+ int ret;
+
+ if (brightness > MAX_BRIGHTNESS)
+ value = MAX_BRIGHTNESS;
+ else
+ value = brightness;
+
+ ret = pm860x_reg_write(data->i2c, wled_a(data->port), value);
+ if (ret < 0)
+ goto out;
+
+ if ((data->current_brightness == 0) && brightness) {
+ if (data->iset) {
+ ret = pm860x_set_bits(data->i2c, wled_idc(data->port),
+ CURRENT_MASK, data->iset);
+ if (ret < 0)
+ goto out;
+ }
+ if (data->pwm) {
+ ret = pm860x_set_bits(data->i2c, PM8606_PWM,
+ PM8606_PWM_FREQ_MASK, data->pwm);
+ if (ret < 0)
+ goto out;
+ }
+ if (brightness == MAX_BRIGHTNESS) {
+ /* set WLED_ON bit as 100% */
+ ret = pm860x_set_bits(data->i2c, wled_b(data->port),
+ PM8606_WLED_ON, PM8606_WLED_ON);
+ }
+ } else {
+ if (brightness == MAX_BRIGHTNESS) {
+ /* set WLED_ON bit as 100% */
+ ret = pm860x_set_bits(data->i2c, wled_b(data->port),
+ PM8606_WLED_ON, PM8606_WLED_ON);
+ } else {
+ /* clear WLED_ON bit since it's not 100% */
+ ret = pm860x_set_bits(data->i2c, wled_b(data->port),
+ PM8606_WLED_ON, 0);
+ }
+ }
+ if (ret < 0)
+ goto out;
+
+ dev_dbg(chip->dev, "set brightness %d\n", value);
+ data->current_brightness = value;
+ return 0;
+out:
+ dev_dbg(chip->dev, "set brightness %d failure with return "
+ "value:%d\n", value, ret);
+ return ret;
+}
+
+static int pm860x_backlight_update_status(struct backlight_device *bl)
+{
+ int brightness = bl->props.brightness;
+
+ if (bl->props.power != FB_BLANK_UNBLANK)
+ brightness = 0;
+
+ if (bl->props.fb_blank != FB_BLANK_UNBLANK)
+ brightness = 0;
+
+ if (bl->props.state & BL_CORE_SUSPENDED)
+ brightness = 0;
+
+ return pm860x_backlight_set(bl, brightness);
+}
+
+static int pm860x_backlight_get_brightness(struct backlight_device *bl)
+{
+ struct pm860x_backlight_data *data = bl_get_data(bl);
+ struct pm860x_chip *chip = data->chip;
+ int ret;
+
+ ret = pm860x_reg_read(data->i2c, wled_a(data->port));
+ if (ret < 0)
+ goto out;
+ data->current_brightness = ret;
+ dev_dbg(chip->dev, "get brightness %d\n", data->current_brightness);
+ return data->current_brightness;
+out:
+ return -EINVAL;
+}
+
+static struct backlight_ops pm860x_backlight_ops = {
+ .options = BL_CORE_SUSPENDRESUME,
+ .update_status = pm860x_backlight_update_status,
+ .get_brightness = pm860x_backlight_get_brightness,
+};
+
+static int __check_device(struct pm860x_backlight_pdata *pdata, char *name)
+{
+ struct pm860x_backlight_pdata *p = pdata;
+ int ret = -EINVAL;
+
+ while (p && p->id) {
+ if ((p->id != PM8606_ID_BACKLIGHT) || (p->flags < 0))
+ break;
+
+ if (!strncmp(name, pm860x_backlight_name[p->flags],
+ MFD_NAME_SIZE)) {
+ ret = (int)p->flags;
+ break;
+ }
+ p++;
+ }
+ return ret;
+}
+
+static int pm860x_backlight_probe(struct platform_device *pdev)
+{
+ struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ struct pm860x_platform_data *pm860x_pdata;
+ struct pm860x_backlight_pdata *pdata = NULL;
+ struct pm860x_backlight_data *data;
+ struct backlight_device *bl;
+ struct resource *res;
+ unsigned char value;
+ char name[MFD_NAME_SIZE];
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "No I/O resource!\n");
+ return -EINVAL;
+ }
+
+ if (pdev->dev.parent->platform_data) {
+ pm860x_pdata = pdev->dev.parent->platform_data;
+ pdata = pm860x_pdata->backlight;
+ }
+ if (pdata == NULL) {
+ dev_err(&pdev->dev, "platform data isn't assigned to "
+ "backlight\n");
+ return -EINVAL;
+ }
+
+ data = kzalloc(sizeof(struct pm860x_backlight_data), GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+ strncpy(name, res->name, MFD_NAME_SIZE);
+ data->chip = chip;
+ data->i2c = (chip->id == CHIP_PM8606) ? chip->client \
+ : chip->companion;
+ data->current_brightness = MAX_BRIGHTNESS;
+ data->pwm = pdata->pwm;
+ data->iset = pdata->iset;
+ data->port = __check_device(pdata, name);
+ if (data->port < 0) {
+ dev_err(&pdev->dev, "wrong platform data is assigned");
+ return -EINVAL;
+ }
+
+ bl = backlight_device_register(name, &pdev->dev, data,
+ &pm860x_backlight_ops);
+ if (IS_ERR(bl)) {
+ dev_err(&pdev->dev, "failed to register backlight\n");
+ kfree(data);
+ return PTR_ERR(bl);
+ }
+ bl->props.max_brightness = MAX_BRIGHTNESS;
+ bl->props.brightness = MAX_BRIGHTNESS;
+
+ platform_set_drvdata(pdev, bl);
+
+ /* Enable reference VSYS */
+ ret = pm860x_reg_read(data->i2c, PM8606_VSYS);
+ if (ret < 0)
+ goto out;
+ if ((ret & PM8606_VSYS_EN) == 0) {
+ value = ret | PM8606_VSYS_EN;
+ ret = pm860x_reg_write(data->i2c, PM8606_VSYS, value);
+ if (ret < 0)
+ goto out;
+ }
+ /* Enable reference OSC */
+ ret = pm860x_reg_read(data->i2c, PM8606_MISC);
+ if (ret < 0)
+ goto out;
+ if ((ret & PM8606_MISC_OSC_EN) == 0) {
+ value = ret | PM8606_MISC_OSC_EN;
+ ret = pm860x_reg_write(data->i2c, PM8606_MISC, value);
+ if (ret < 0)
+ goto out;
+ }
+ /* read current backlight */
+ ret = pm860x_backlight_get_brightness(bl);
+ if (ret < 0)
+ goto out;
+
+ backlight_update_status(bl);
+ return 0;
+out:
+ kfree(data);
+ return ret;
+}
+
+static int pm860x_backlight_remove(struct platform_device *pdev)
+{
+ struct backlight_device *bl = platform_get_drvdata(pdev);
+ struct pm860x_backlight_data *data = bl_get_data(bl);
+
+ backlight_device_unregister(bl);
+ kfree(data);
+ return 0;
+}
+
+static struct platform_driver pm860x_backlight_driver = {
+ .driver = {
+ .name = "88pm860x-backlight",
+ .owner = THIS_MODULE,
+ },
+ .probe = pm860x_backlight_probe,
+ .remove = pm860x_backlight_remove,
+};
+
+static int __init pm860x_backlight_init(void)
+{
+ return platform_driver_register(&pm860x_backlight_driver);
+}
+module_init(pm860x_backlight_init);
+
+static void __exit pm860x_backlight_exit(void)
+{
+ platform_driver_unregister(&pm860x_backlight_driver);
+}
+module_exit(pm860x_backlight_exit);
+
+MODULE_DESCRIPTION("Backlight Driver for Marvell Semiconductor 88PM8606");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:88pm860x-backlight");
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 09bfa9662e4..0c77fc61021 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -212,6 +212,13 @@ config BACKLIGHT_DA903X
If you have a LCD backlight connected to the WLED output of DA9030
or DA9034 WLED output, say Y here to enable this driver.
+config BACKLIGHT_MAX8925
+ tristate "Backlight driver for MAX8925"
+ depends on BACKLIGHT_CLASS_DEVICE && MFD_MAX8925
+ help
+ If you have a LCD backlight connected to the WLED output of MAX8925
+ WLED output, say Y here to enable this driver.
+
config BACKLIGHT_MBP_NVIDIA
tristate "MacBook Pro Nvidia Backlight Driver"
depends on BACKLIGHT_CLASS_DEVICE && X86
@@ -262,3 +269,9 @@ config BACKLIGHT_ADP5520
To compile this driver as a module, choose M here: the module will
be called adp5520_bl.
+config BACKLIGHT_88PM860X
+ tristate "Backlight Driver for 88PM8606 using WLED"
+ depends on BACKLIGHT_CLASS_DEVICE && MFD_88PM860X
+ help
+ Say Y to enable the backlight driver for Marvell 88PM8606.
+
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 9a405548874..6c704d41462 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -22,10 +22,12 @@ obj-$(CONFIG_BACKLIGHT_PROGEAR) += progear_bl.o
obj-$(CONFIG_BACKLIGHT_CARILLO_RANCH) += cr_bllcd.o
obj-$(CONFIG_BACKLIGHT_PWM) += pwm_bl.o
obj-$(CONFIG_BACKLIGHT_DA903X) += da903x_bl.o
+obj-$(CONFIG_BACKLIGHT_MAX8925) += max8925_bl.o
obj-$(CONFIG_BACKLIGHT_MBP_NVIDIA) += mbp_nvidia_bl.o
obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o
obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o
obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o
obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o
obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o
+obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o
diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c
new file mode 100644
index 00000000000..c267069a52a
--- /dev/null
+++ b/drivers/video/backlight/max8925_bl.c
@@ -0,0 +1,200 @@
+/*
+ * Backlight driver for Maxim MAX8925
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ * Haojian Zhuang <haojian.zhuang@marvell.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/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/i2c.h>
+#include <linux/backlight.h>
+#include <linux/mfd/max8925.h>
+
+#define MAX_BRIGHTNESS (0xff)
+#define MIN_BRIGHTNESS (0)
+
+#define LWX_FREQ(x) (((x - 601) / 100) & 0x7)
+
+struct max8925_backlight_data {
+ struct max8925_chip *chip;
+
+ int current_brightness;
+};
+
+static int max8925_backlight_set(struct backlight_device *bl, int brightness)
+{
+ struct max8925_backlight_data *data = bl_get_data(bl);
+ struct max8925_chip *chip = data->chip;
+ unsigned char value;
+ int ret;
+
+ if (brightness > MAX_BRIGHTNESS)
+ value = MAX_BRIGHTNESS;
+ else
+ value = brightness;
+
+ ret = max8925_reg_write(chip->i2c, MAX8925_WLED_CNTL, value);
+ if (ret < 0)
+ goto out;
+
+ if (!data->current_brightness && brightness)
+ /* enable WLED output */
+ ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 1, 1);
+ else if (!brightness)
+ /* disable WLED output */
+ ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 1, 0);
+ if (ret < 0)
+ goto out;
+ dev_dbg(chip->dev, "set brightness %d\n", value);
+ data->current_brightness = value;
+ return 0;
+out:
+ dev_dbg(chip->dev, "set brightness %d failure with return value:%d\n",
+ value, ret);
+ return ret;
+}
+
+static int max8925_backlight_update_status(struct backlight_device *bl)
+{
+ int brightness = bl->props.brightness;
+
+ if (bl->props.power != FB_BLANK_UNBLANK)
+ brightness = 0;
+
+ if (bl->props.fb_blank != FB_BLANK_UNBLANK)
+ brightness = 0;
+
+ if (bl->props.state & BL_CORE_SUSPENDED)
+ brightness = 0;
+
+ return max8925_backlight_set(bl, brightness);
+}
+
+static int max8925_backlight_get_brightness(struct backlight_device *bl)
+{
+ struct max8925_backlight_data *data = bl_get_data(bl);
+ struct max8925_chip *chip = data->chip;
+ int ret;
+
+ ret = max8925_reg_read(chip->i2c, MAX8925_WLED_CNTL);
+ if (ret < 0)
+ return -EINVAL;
+ data->current_brightness = ret;
+ dev_dbg(chip->dev, "get brightness %d\n", data->current_brightness);
+ return ret;
+}
+
+static struct backlight_ops max8925_backlight_ops = {
+ .options = BL_CORE_SUSPENDRESUME,
+ .update_status = max8925_backlight_update_status,
+ .get_brightness = max8925_backlight_get_brightness,
+};
+
+static int __devinit max8925_backlight_probe(struct platform_device *pdev)
+{
+ struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ struct max8925_platform_data *max8925_pdata;
+ struct max8925_backlight_pdata *pdata = NULL;
+ struct max8925_backlight_data *data;
+ struct backlight_device *bl;
+ struct resource *res;
+ char name[MAX8925_NAME_SIZE];
+ unsigned char value;
+ int ret;
+
+ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "No I/O resource!\n");
+ return -EINVAL;
+ }
+
+ if (pdev->dev.parent->platform_data) {
+ max8925_pdata = pdev->dev.parent->platform_data;
+ pdata = max8925_pdata->backlight;
+ }
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "platform data isn't assigned to "
+ "backlight\n");
+ return -EINVAL;
+ }
+
+ data = kzalloc(sizeof(struct max8925_backlight_data), GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+ strncpy(name, res->name, MAX8925_NAME_SIZE);
+ data->chip = chip;
+ data->current_brightness = 0;
+
+ bl = backlight_device_register(name, &pdev->dev, data,
+ &max8925_backlight_ops);
+ if (IS_ERR(bl)) {
+ dev_err(&pdev->dev, "failed to register backlight\n");
+ kfree(data);
+ return PTR_ERR(bl);
+ }
+ bl->props.max_brightness = MAX_BRIGHTNESS;
+ bl->props.brightness = MAX_BRIGHTNESS;
+
+ platform_set_drvdata(pdev, bl);
+
+ value = 0;
+ if (pdata->lxw_scl)
+ value |= (1 << 7);
+ if (pdata->lxw_freq)
+ value |= (LWX_FREQ(pdata->lxw_freq) << 4);
+ if (pdata->dual_string)
+ value |= (1 << 1);
+ ret = max8925_set_bits(chip->i2c, MAX8925_WLED_MODE_CNTL, 0xfe, value);
+ if (ret < 0)
+ goto out;
+
+ backlight_update_status(bl);
+ return 0;
+out:
+ kfree(data);
+ return ret;
+}
+
+static int __devexit max8925_backlight_remove(struct platform_device *pdev)
+{
+ struct backlight_device *bl = platform_get_drvdata(pdev);
+ struct max8925_backlight_data *data = bl_get_data(bl);
+
+ backlight_device_unregister(bl);
+ kfree(data);
+ return 0;
+}
+
+static struct platform_driver max8925_backlight_driver = {
+ .driver = {
+ .name = "max8925-backlight",
+ .owner = THIS_MODULE,
+ },
+ .probe = max8925_backlight_probe,
+ .remove = __devexit_p(max8925_backlight_remove),
+};
+
+static int __init max8925_backlight_init(void)
+{
+ return platform_driver_register(&max8925_backlight_driver);
+}
+module_init(max8925_backlight_init);
+
+static void __exit max8925_backlight_exit(void)
+{
+ platform_driver_unregister(&max8925_backlight_driver);
+};
+module_exit(max8925_backlight_exit);
+
+MODULE_DESCRIPTION("Backlight Driver for Maxim MAX8925");
+MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:max8925-backlight");
diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c
index 108b89e09a8..5eb61b5adfe 100644
--- a/drivers/video/cobalt_lcdfb.c
+++ b/drivers/video/cobalt_lcdfb.c
@@ -287,7 +287,7 @@ static struct fb_ops cobalt_lcd_fbops = {
.fb_cursor = cobalt_lcdfb_cursor,
};
-static int __init cobalt_lcdfb_probe(struct platform_device *dev)
+static int __devinit cobalt_lcdfb_probe(struct platform_device *dev)
{
struct fb_info *info;
struct resource *res;
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index fc7d9bbb548..8e8f18d29d7 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -37,6 +37,7 @@ config VGACON_SOFT_SCROLLBACK
config VGACON_SOFT_SCROLLBACK_SIZE
int "Scrollback Buffer Size (in KB)"
depends on VGACON_SOFT_SCROLLBACK
+ range 1 1024
default "64"
help
Enter the amount of System RAM to allocate for the scrollback
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index cc4bbbe44ac..182dd6f8aad 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -112,7 +112,7 @@ static int vga_video_font_height;
static int vga_scan_lines __read_mostly;
static unsigned int vga_rolled_over;
-int vgacon_text_mode_force = 0;
+static int vgacon_text_mode_force;
bool vgacon_text_force(void)
{
diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c
index d25df51bb0d..581d2dbf675 100644
--- a/drivers/video/efifb.c
+++ b/drivers/video/efifb.c
@@ -210,7 +210,7 @@ static int __init efifb_setup(char *options)
return 0;
}
-static int __init efifb_probe(struct platform_device *dev)
+static int __devinit efifb_probe(struct platform_device *dev)
{
struct fb_info *info;
int err;
diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c
index 2735b79e52a..6d755bb3a2b 100644
--- a/drivers/video/epson1355fb.c
+++ b/drivers/video/epson1355fb.c
@@ -602,7 +602,7 @@ static int epson1355fb_remove(struct platform_device *dev)
return 0;
}
-int __init epson1355fb_probe(struct platform_device *dev)
+int __devinit epson1355fb_probe(struct platform_device *dev)
{
struct epson1355_par *default_par;
struct fb_info *info;
diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c
index 695fa013fe7..5643a35c174 100644
--- a/drivers/video/gbefb.c
+++ b/drivers/video/gbefb.c
@@ -1128,7 +1128,7 @@ static int __init gbefb_setup(char *options)
return 0;
}
-static int __init gbefb_probe(struct platform_device *p_dev)
+static int __devinit gbefb_probe(struct platform_device *p_dev)
{
int i, ret = 0;
struct fb_info *info;
diff --git a/drivers/video/hgafb.c b/drivers/video/hgafb.c
index 0129c044f6d..db9b785b56e 100644
--- a/drivers/video/hgafb.c
+++ b/drivers/video/hgafb.c
@@ -551,7 +551,7 @@ static struct fb_ops hgafb_ops = {
* Initialization
*/
-static int __init hgafb_probe(struct platform_device *pdev)
+static int __devinit hgafb_probe(struct platform_device *pdev)
{
struct fb_info *info;
diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c
index 73c83a8de2d..bf78779199c 100644
--- a/drivers/video/hitfb.c
+++ b/drivers/video/hitfb.c
@@ -325,7 +325,7 @@ static struct fb_ops hitfb_ops = {
.fb_imageblit = cfb_imageblit,
};
-static int __init hitfb_probe(struct platform_device *dev)
+static int __devinit hitfb_probe(struct platform_device *dev)
{
unsigned short lcdclor, ldr3, ldvndr;
struct fb_info *info;
diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/omap2/dss/manager.c
index 913142d4cab..9acef00c47e 100644
--- a/drivers/video/omap2/dss/manager.c
+++ b/drivers/video/omap2/dss/manager.c
@@ -341,7 +341,7 @@ static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
return manager_attr->store(manager, buf, size);
}
-static struct sysfs_ops manager_sysfs_ops = {
+static const struct sysfs_ops manager_sysfs_ops = {
.show = manager_attr_show,
.store = manager_attr_store,
};
diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/omap2/dss/overlay.c
index 0c5bea263ac..aed3f319434 100644
--- a/drivers/video/omap2/dss/overlay.c
+++ b/drivers/video/omap2/dss/overlay.c
@@ -320,7 +320,7 @@ static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
return overlay_attr->store(overlay, buf, size);
}
-static struct sysfs_ops overlay_sysfs_ops = {
+static const struct sysfs_ops overlay_sysfs_ops = {
.show = overlay_attr_show,
.store = overlay_attr_store,
};
diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c
index 4beac1df617..de40a626dc7 100644
--- a/drivers/video/q40fb.c
+++ b/drivers/video/q40fb.c
@@ -85,7 +85,7 @@ static struct fb_ops q40fb_ops = {
.fb_imageblit = cfb_imageblit,
};
-static int __init q40fb_probe(struct platform_device *dev)
+static int __devinit q40fb_probe(struct platform_device *dev)
{
struct fb_info *info;
diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c
index aac661225c7..2b094dec4a5 100644
--- a/drivers/video/s3c2410fb.c
+++ b/drivers/video/s3c2410fb.c
@@ -1004,12 +1004,12 @@ dealloc_fb:
return ret;
}
-static int __init s3c2410fb_probe(struct platform_device *pdev)
+static int __devinit s3c2410fb_probe(struct platform_device *pdev)
{
return s3c24xxfb_probe(pdev, DRV_S3C2410);
}
-static int __init s3c2412fb_probe(struct platform_device *pdev)
+static int __devinit s3c2412fb_probe(struct platform_device *pdev)
{
return s3c24xxfb_probe(pdev, DRV_S3C2412);
}
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index cdaa873a605..e8b76d65a07 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -1435,7 +1435,7 @@ static struct sa1100fb_info * __init sa1100fb_init_fbinfo(struct device *dev)
return fbi;
}
-static int __init sa1100fb_probe(struct platform_device *pdev)
+static int __devinit sa1100fb_probe(struct platform_device *pdev)
{
struct sa1100fb_info *fbi;
int ret, irq;
diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c
index f86012239bf..7a3a5e28eca 100644
--- a/drivers/video/sgivwfb.c
+++ b/drivers/video/sgivwfb.c
@@ -745,7 +745,7 @@ int __init sgivwfb_setup(char *options)
/*
* Initialisation
*/
-static int __init sgivwfb_probe(struct platform_device *dev)
+static int __devinit sgivwfb_probe(struct platform_device *dev)
{
struct sgivw_par *par;
struct fb_info *info;
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index 8d7653e56df..bbd1dbf4026 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -943,7 +943,7 @@ static const struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = {
static int sh_mobile_lcdc_remove(struct platform_device *pdev);
-static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
+static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
{
struct fb_info *info;
struct sh_mobile_lcdc_priv *priv;
diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c
index bd37ee1f6a2..ef4128c8e57 100644
--- a/drivers/video/vesafb.c
+++ b/drivers/video/vesafb.c
@@ -226,7 +226,7 @@ static int __init vesafb_setup(char *options)
return 0;
}
-static int __init vesafb_probe(struct platform_device *dev)
+static int __devinit vesafb_probe(struct platform_device *dev)
{
struct fb_info *info;
int i, err;
diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c
index 050d432c7d9..b8ab995fbda 100644
--- a/drivers/video/vfb.c
+++ b/drivers/video/vfb.c
@@ -479,7 +479,7 @@ static int __init vfb_setup(char *options)
* Initialisation
*/
-static int __init vfb_probe(struct platform_device *dev)
+static int __devinit vfb_probe(struct platform_device *dev)
{
struct fb_info *info;
int retval = -ENOMEM;
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 5b2938903ac..76d8dae5b1b 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -1293,7 +1293,7 @@ static int vga16fb_setup(char *options)
}
#endif
-static int __init vga16fb_probe(struct platform_device *dev)
+static int __devinit vga16fb_probe(struct platform_device *dev)
{
struct fb_info *info;
struct vga16fb_par *par;
diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c
index 2376f688ec8..5d223959778 100644
--- a/drivers/video/w100fb.c
+++ b/drivers/video/w100fb.c
@@ -628,7 +628,7 @@ static int w100fb_resume(struct platform_device *dev)
#endif
-int __init w100fb_probe(struct platform_device *pdev)
+int __devinit w100fb_probe(struct platform_device *pdev)
{
int err = -EIO;
struct w100fb_mach_info *inf;
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
index 1b657321699..625447f645d 100644
--- a/drivers/virtio/virtio_pci.c
+++ b/drivers/virtio/virtio_pci.c
@@ -649,6 +649,7 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev,
goto out_req_regions;
pci_set_drvdata(pci_dev, vp_dev);
+ pci_set_master(pci_dev);
/* we use the subsystem vendor/device id as the virtio vendor/device
* id. this allows us to use the same PCI vendor/device id for all
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
index 0d92969404c..22977d30f89 100644
--- a/drivers/w1/masters/omap_hdq.c
+++ b/drivers/w1/masters/omap_hdq.c
@@ -72,7 +72,7 @@ struct hdq_data {
int init_trans;
};
-static int __init omap_hdq_probe(struct platform_device *pdev);
+static int __devinit omap_hdq_probe(struct platform_device *pdev);
static int omap_hdq_remove(struct platform_device *pdev);
static struct platform_driver omap_hdq_driver = {
@@ -558,7 +558,7 @@ static void omap_w1_write_byte(void *_hdq, u8 byte)
return;
}
-static int __init omap_hdq_probe(struct platform_device *pdev)
+static int __devinit omap_hdq_probe(struct platform_device *pdev)
{
struct hdq_data *hdq_data;
struct resource *res;
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 3da3f48720a..bdcdbd53da8 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -55,6 +55,11 @@ config SOFT_WATCHDOG
To compile this driver as a module, choose M here: the
module will be called softdog.
+config MAX63XX_WATCHDOG
+ tristate "Max63xx watchdog"
+ help
+ Support for memory mapped max63{69,70,71,72,73,74} watchdog timer.
+
config WM831X_WATCHDOG
tristate "WM831x watchdog"
depends on MFD_WM831X
@@ -289,6 +294,17 @@ config ADX_WATCHDOG
Say Y here if you want support for the watchdog timer on Avionic
Design Xanthos boards.
+config TS72XX_WATCHDOG
+ tristate "TS-72XX SBC Watchdog"
+ depends on MACH_TS72XX
+ help
+ Technologic Systems TS-7200, TS-7250 and TS-7260 boards have
+ watchdog timer implemented in a external CPLD chip. Say Y here
+ if you want to support for the watchdog timer on TS-72XX boards.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ts72xx_wdt.
+
# AVR32 Architecture
config AT32AP700X_WDT
@@ -845,10 +861,10 @@ config TXX9_WDT
# POWERPC Architecture
config GEF_WDT
- tristate "GE Fanuc Watchdog Timer"
+ tristate "GE Watchdog Timer"
depends on GEF_SBC610 || GEF_SBC310 || GEF_PPC9A
---help---
- Watchdog timer found in a number of GE Fanuc single board computers.
+ Watchdog timer found in a number of GE single board computers.
config MPC5200_WDT
bool "MPC52xx Watchdog Timer"
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 475c6110006..5e3cb95bb0e 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o
obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o
obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
obj-$(CONFIG_ADX_WATCHDOG) += adx_wdt.o
+obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
# AVR32 Architecture
obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
@@ -142,4 +143,5 @@ obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwd.o
# Architecture Independant
obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o
obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o
+obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o
obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
diff --git a/drivers/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c
index 4d18c874d96..2ffce4d7544 100644
--- a/drivers/watchdog/acquirewdt.c
+++ b/drivers/watchdog/acquirewdt.c
@@ -150,7 +150,7 @@ static long acq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
int options, retval = -EINVAL;
void __user *argp = (void __user *)arg;
int __user *p = argp;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
.firmware_version = 1,
.identity = WATCHDOG_NAME,
diff --git a/drivers/watchdog/advantechwdt.c b/drivers/watchdog/advantechwdt.c
index 824d076a5cd..4d40965d2c9 100644
--- a/drivers/watchdog/advantechwdt.c
+++ b/drivers/watchdog/advantechwdt.c
@@ -137,7 +137,7 @@ static long advwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
int new_timeout;
void __user *argp = (void __user *)arg;
int __user *p = argp;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING |
WDIOF_SETTIMEOUT |
WDIOF_MAGICCLOSE,
diff --git a/drivers/watchdog/adx_wdt.c b/drivers/watchdog/adx_wdt.c
index 9d7d155364f..a5ca7a6ee13 100644
--- a/drivers/watchdog/adx_wdt.c
+++ b/drivers/watchdog/adx_wdt.c
@@ -37,7 +37,7 @@ struct adx_wdt {
spinlock_t lock;
};
-static struct watchdog_info adx_wdt_info = {
+static const struct watchdog_info adx_wdt_info = {
.identity = "Avionic Design Xanthos Watchdog",
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
};
diff --git a/drivers/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c
index 937a80fb61e..1e9caea8ff8 100644
--- a/drivers/watchdog/alim1535_wdt.c
+++ b/drivers/watchdog/alim1535_wdt.c
@@ -180,7 +180,7 @@ static long ali_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
int __user *p = argp;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING |
WDIOF_SETTIMEOUT |
WDIOF_MAGICCLOSE,
diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c
index f90afdb1b25..d8d4da9a483 100644
--- a/drivers/watchdog/alim7101_wdt.c
+++ b/drivers/watchdog/alim7101_wdt.c
@@ -238,7 +238,7 @@ static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
int __user *p = argp;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT
| WDIOF_MAGICCLOSE,
.firmware_version = 1,
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c
index 2bb95cd308c..c764c52412e 100644
--- a/drivers/watchdog/ar7_wdt.c
+++ b/drivers/watchdog/ar7_wdt.c
@@ -219,7 +219,7 @@ static ssize_t ar7_wdt_write(struct file *file, const char *data,
static long ar7_wdt_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.identity = LONGNAME,
.firmware_version = 1,
.options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c
index 037847923dc..6873376f986 100644
--- a/drivers/watchdog/at32ap700x_wdt.c
+++ b/drivers/watchdog/at32ap700x_wdt.c
@@ -202,7 +202,7 @@ static int at32_wdt_get_status(void)
return status;
}
-static struct watchdog_info at32_wdt_info = {
+static const struct watchdog_info at32_wdt_info = {
.identity = "at32ap700x watchdog",
.options = WDIOF_SETTIMEOUT |
WDIOF_KEEPALIVEPING |
diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c
index b185dafe149..b3046dc4b56 100644
--- a/drivers/watchdog/at91rm9200_wdt.c
+++ b/drivers/watchdog/at91rm9200_wdt.c
@@ -121,7 +121,7 @@ static int at91_wdt_settimeout(int new_time)
return 0;
}
-static struct watchdog_info at91_wdt_info = {
+static const struct watchdog_info at91_wdt_info = {
.identity = "at91 watchdog",
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
};
diff --git a/drivers/watchdog/bcm47xx_wdt.c b/drivers/watchdog/bcm47xx_wdt.c
index 751c003864a..5f245522397 100644
--- a/drivers/watchdog/bcm47xx_wdt.c
+++ b/drivers/watchdog/bcm47xx_wdt.c
@@ -149,7 +149,7 @@ static ssize_t bcm47xx_wdt_write(struct file *file, const char __user *data,
return len;
}
-static struct watchdog_info bcm47xx_wdt_info = {
+static const struct watchdog_info bcm47xx_wdt_info = {
.identity = DRV_NAME,
.options = WDIOF_SETTIMEOUT |
WDIOF_KEEPALIVEPING |
diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c
index 2159e668751..9c7ccd1e908 100644
--- a/drivers/watchdog/bfin_wdt.c
+++ b/drivers/watchdog/bfin_wdt.c
@@ -19,8 +19,6 @@
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/fs.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/uaccess.h>
@@ -74,7 +72,7 @@
static unsigned int timeout = WATCHDOG_TIMEOUT;
static int nowayout = WATCHDOG_NOWAYOUT;
-static struct watchdog_info bfin_wdt_info;
+static const struct watchdog_info bfin_wdt_info;
static unsigned long open_check;
static char expect_close;
static DEFINE_SPINLOCK(bfin_wdt_spinlock);
@@ -309,26 +307,6 @@ static long bfin_wdt_ioctl(struct file *file,
}
}
-/**
- * bfin_wdt_notify_sys - Notifier Handler
- * @this: notifier block
- * @code: notifier event
- * @unused: unused
- *
- * Handles specific events, such as turning off the watchdog during a
- * shutdown event.
- */
-static int bfin_wdt_notify_sys(struct notifier_block *this,
- unsigned long code, void *unused)
-{
- stampit();
-
- if (code == SYS_DOWN || code == SYS_HALT)
- bfin_wdt_stop();
-
- return NOTIFY_DONE;
-}
-
#ifdef CONFIG_PM
static int state_before_suspend;
@@ -388,40 +366,28 @@ static struct miscdevice bfin_wdt_miscdev = {
.fops = &bfin_wdt_fops,
};
-static struct watchdog_info bfin_wdt_info = {
+static const struct watchdog_info bfin_wdt_info = {
.identity = "Blackfin Watchdog",
.options = WDIOF_SETTIMEOUT |
WDIOF_KEEPALIVEPING |
WDIOF_MAGICCLOSE,
};
-static struct notifier_block bfin_wdt_notifier = {
- .notifier_call = bfin_wdt_notify_sys,
-};
-
/**
* bfin_wdt_probe - Initialize module
*
- * Registers the misc device and notifier handler. Actual device
+ * Registers the misc device. Actual device
* initialization is handled by bfin_wdt_open().
*/
static int __devinit bfin_wdt_probe(struct platform_device *pdev)
{
int ret;
- ret = register_reboot_notifier(&bfin_wdt_notifier);
- if (ret) {
- pr_devinit(KERN_ERR PFX
- "cannot register reboot notifier (err=%d)\n", ret);
- return ret;
- }
-
ret = misc_register(&bfin_wdt_miscdev);
if (ret) {
pr_devinit(KERN_ERR PFX
"cannot register miscdev on minor=%d (err=%d)\n",
WATCHDOG_MINOR, ret);
- unregister_reboot_notifier(&bfin_wdt_notifier);
return ret;
}
@@ -434,21 +400,33 @@ static int __devinit bfin_wdt_probe(struct platform_device *pdev)
/**
* bfin_wdt_remove - Initialize module
*
- * Unregisters the misc device and notifier handler. Actual device
+ * Unregisters the misc device. Actual device
* deinitialization is handled by bfin_wdt_close().
*/
static int __devexit bfin_wdt_remove(struct platform_device *pdev)
{
misc_deregister(&bfin_wdt_miscdev);
- unregister_reboot_notifier(&bfin_wdt_notifier);
return 0;
}
+/**
+ * bfin_wdt_shutdown - Soft Shutdown Handler
+ *
+ * Handles the soft shutdown event.
+ */
+static void bfin_wdt_shutdown(struct platform_device *pdev)
+{
+ stampit();
+
+ bfin_wdt_stop();
+}
+
static struct platform_device *bfin_wdt_device;
static struct platform_driver bfin_wdt_driver = {
.probe = bfin_wdt_probe,
.remove = __devexit_p(bfin_wdt_remove),
+ .shutdown = bfin_wdt_shutdown,
.suspend = bfin_wdt_suspend,
.resume = bfin_wdt_resume,
.driver = {
diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c
index e8380ef65c1..8b724aad682 100644
--- a/drivers/watchdog/booke_wdt.c
+++ b/drivers/watchdog/booke_wdt.c
@@ -121,7 +121,7 @@ static ssize_t booke_wdt_write(struct file *file, const char __user *buf,
return count;
}
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
.identity = "PowerPC Book-E Watchdog",
};
diff --git a/drivers/watchdog/coh901327_wdt.c b/drivers/watchdog/coh901327_wdt.c
index 923cc68dba2..9291506b8b2 100644
--- a/drivers/watchdog/coh901327_wdt.c
+++ b/drivers/watchdog/coh901327_wdt.c
@@ -257,7 +257,7 @@ static long coh901327_ioctl(struct file *file, unsigned int cmd,
struct watchdog_info __user *ident;
int __user *i;
} uarg;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_CARDRESET |
WDIOF_SETTIMEOUT |
WDIOF_KEEPALIVEPING,
diff --git a/drivers/watchdog/cpu5wdt.c b/drivers/watchdog/cpu5wdt.c
index 71f6d7eec9a..edd3475f41d 100644
--- a/drivers/watchdog/cpu5wdt.c
+++ b/drivers/watchdog/cpu5wdt.c
@@ -154,7 +154,7 @@ static long cpu5wdt_ioctl(struct file *file, unsigned int cmd,
void __user *argp = (void __user *)arg;
int __user *p = argp;
unsigned int value;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_CARDRESET,
.identity = "CPU5 WDT",
};
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c
index 081f2955419..37ea052d4de 100644
--- a/drivers/watchdog/cpwd.c
+++ b/drivers/watchdog/cpwd.c
@@ -403,7 +403,7 @@ static int cpwd_release(struct inode *inode, struct file *file)
static long cpwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- static struct watchdog_info info = {
+ static const struct watchdog_info info = {
.options = WDIOF_SETTIMEOUT,
.firmware_version = 1,
.identity = DRIVER_NAME,
diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c
index 887136de185..56162c87f5d 100644
--- a/drivers/watchdog/davinci_wdt.c
+++ b/drivers/watchdog/davinci_wdt.c
@@ -142,7 +142,7 @@ davinci_wdt_write(struct file *file, const char *data, size_t len,
return len;
}
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING,
.identity = "DaVinci Watchdog",
};
diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c
index cdd55e0d09f..88ed54e50f7 100644
--- a/drivers/watchdog/ep93xx_wdt.c
+++ b/drivers/watchdog/ep93xx_wdt.c
@@ -131,7 +131,7 @@ ep93xx_wdt_write(struct file *file, const char __user *data, size_t len,
return len;
}
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
.options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE,
.identity = "EP93xx Watchdog",
};
diff --git a/drivers/watchdog/eurotechwdt.c b/drivers/watchdog/eurotechwdt.c
index 9add3541fb4..d1c4e55b1db 100644
--- a/drivers/watchdog/eurotechwdt.c
+++ b/drivers/watchdog/eurotechwdt.c
@@ -238,7 +238,7 @@ static long eurwdt_ioctl(struct file *file,
{
void __user *argp = (void __user *)arg;
int __user *p = argp;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT
| WDIOF_MAGICCLOSE,
.firmware_version = 1,
diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c
index 734d9806a87..abdbad034a6 100644
--- a/drivers/watchdog/gef_wdt.c
+++ b/drivers/watchdog/gef_wdt.c
@@ -1,9 +1,9 @@
/*
- * GE Fanuc watchdog userspace interface
+ * GE watchdog userspace interface
*
- * Author: Martyn Welch <martyn.welch@gefanuc.com>
+ * Author: Martyn Welch <martyn.welch@ge.com>
*
- * Copyright 2008 GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ * Copyright 2008 GE Intelligent Platforms Embedded Systems, 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
@@ -161,11 +161,11 @@ static long gef_wdt_ioctl(struct file *file, unsigned int cmd,
int timeout;
int options;
void __user *argp = (void __user *)arg;
- static struct watchdog_info info = {
+ static const struct watchdog_info info = {
.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE |
WDIOF_KEEPALIVEPING,
.firmware_version = 0,
- .identity = "GE Fanuc watchdog",
+ .identity = "GE watchdog",
};
switch (cmd) {
@@ -311,7 +311,7 @@ static struct of_platform_driver gef_wdt_driver = {
static int __init gef_wdt_init(void)
{
- printk(KERN_INFO "GE Fanuc watchdog driver\n");
+ printk(KERN_INFO "GE watchdog driver\n");
return of_register_platform_driver(&gef_wdt_driver);
}
@@ -323,8 +323,8 @@ static void __exit gef_wdt_exit(void)
module_init(gef_wdt_init);
module_exit(gef_wdt_exit);
-MODULE_AUTHOR("Martyn Welch <martyn.welch@gefanuc.com>");
-MODULE_DESCRIPTION("GE Fanuc watchdog driver");
+MODULE_AUTHOR("Martyn Welch <martyn.welch@ge.com>");
+MODULE_DESCRIPTION("GE watchdog driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
MODULE_ALIAS("platform: gef_wdt");
diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c
index 38252ff828c..9b49b125ad5 100644
--- a/drivers/watchdog/geodewdt.c
+++ b/drivers/watchdog/geodewdt.c
@@ -142,7 +142,7 @@ static long geodewdt_ioctl(struct file *file, unsigned int cmd,
int __user *p = argp;
int interval;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING
| WDIOF_MAGICCLOSE,
.firmware_version = 1,
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index a6c5674c78e..70c2c24660d 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -554,7 +554,7 @@ static ssize_t hpwdt_write(struct file *file, const char __user *data,
return len;
}
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
.options = WDIOF_SETTIMEOUT |
WDIOF_KEEPALIVEPING |
WDIOF_MAGICCLOSE,
diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c
index 7ba0b11ec52..bb9750a0394 100644
--- a/drivers/watchdog/i6300esb.c
+++ b/drivers/watchdog/i6300esb.c
@@ -34,7 +34,6 @@
#include <linux/mm.h>
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
-#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/ioport.h>
@@ -42,7 +41,7 @@
#include <linux/io.h>
/* Module and version information */
-#define ESB_VERSION "0.04"
+#define ESB_VERSION "0.05"
#define ESB_MODULE_NAME "i6300ESB timer"
#define ESB_DRIVER_NAME ESB_MODULE_NAME ", v" ESB_VERSION
#define PFX ESB_MODULE_NAME ": "
@@ -65,7 +64,7 @@
/* Config register bits */
#define ESB_WDT_REBOOT (0x01 << 5) /* Enable reboot on timeout */
#define ESB_WDT_FREQ (0x01 << 2) /* Decrement frequency */
-#define ESB_WDT_INTTYPE (0x11 << 0) /* Interrupt type on timer1 timeout */
+#define ESB_WDT_INTTYPE (0x03 << 0) /* Interrupt type on timer1 timeout */
/* Reload register bits */
#define ESB_WDT_TIMEOUT (0x01 << 9) /* Watchdog timed out */
@@ -82,7 +81,9 @@ static unsigned long timer_alive;
static struct pci_dev *esb_pci;
static unsigned short triggered; /* The status of the watchdog upon boot */
static char esb_expect_close;
-static struct platform_device *esb_platform_device;
+
+/* We can only use 1 card due to the /dev/watchdog restriction */
+static int cards_found;
/* module parameters */
/* 30 sec default heartbeat (1 < heartbeat < 2*1023) */
@@ -111,8 +112,8 @@ MODULE_PARM_DESC(nowayout,
*/
static inline void esb_unlock_registers(void)
{
- writeb(ESB_UNLOCK1, ESB_RELOAD_REG);
- writeb(ESB_UNLOCK2, ESB_RELOAD_REG);
+ writew(ESB_UNLOCK1, ESB_RELOAD_REG);
+ writew(ESB_UNLOCK2, ESB_RELOAD_REG);
}
static int esb_timer_start(void)
@@ -256,7 +257,7 @@ static long esb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
int new_heartbeat;
void __user *argp = (void __user *)arg;
int __user *p = argp;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_SETTIMEOUT |
WDIOF_KEEPALIVEPING |
WDIOF_MAGICCLOSE,
@@ -332,11 +333,6 @@ static struct miscdevice esb_miscdev = {
/*
* Data for PCI driver interface
- *
- * This data only exists for exporting the supported
- * PCI ids via MODULE_DEVICE_TABLE. We do not actually
- * register a pci_driver, because someone else might one day
- * want to register another driver on the same PCI id.
*/
static struct pci_device_id esb_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), },
@@ -348,29 +344,19 @@ MODULE_DEVICE_TABLE(pci, esb_pci_tbl);
* Init & exit routines
*/
-static unsigned char __devinit esb_getdevice(void)
+static unsigned char __devinit esb_getdevice(struct pci_dev *pdev)
{
- /*
- * Find the PCI device
- */
-
- esb_pci = pci_get_device(PCI_VENDOR_ID_INTEL,
- PCI_DEVICE_ID_INTEL_ESB_9, NULL);
-
- if (!esb_pci)
- return 0;
-
- if (pci_enable_device(esb_pci)) {
+ if (pci_enable_device(pdev)) {
printk(KERN_ERR PFX "failed to enable device\n");
goto err_devput;
}
- if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) {
+ if (pci_request_region(pdev, 0, ESB_MODULE_NAME)) {
printk(KERN_ERR PFX "failed to request region\n");
goto err_disable;
}
- BASEADDR = pci_ioremap_bar(esb_pci, 0);
+ BASEADDR = pci_ioremap_bar(pdev, 0);
if (BASEADDR == NULL) {
/* Something's wrong here, BASEADDR has to be set */
printk(KERN_ERR PFX "failed to get BASEADDR\n");
@@ -378,14 +364,14 @@ static unsigned char __devinit esb_getdevice(void)
}
/* Done */
+ esb_pci = pdev;
return 1;
err_release:
- pci_release_region(esb_pci, 0);
+ pci_release_region(pdev, 0);
err_disable:
- pci_disable_device(esb_pci);
+ pci_disable_device(pdev);
err_devput:
- pci_dev_put(esb_pci);
return 0;
}
@@ -430,12 +416,23 @@ static void __devinit esb_initdevice(void)
esb_timer_set_heartbeat(heartbeat);
}
-static int __devinit esb_probe(struct platform_device *dev)
+static int __devinit esb_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
{
int ret;
+ cards_found++;
+ if (cards_found == 1)
+ printk(KERN_INFO PFX "Intel 6300ESB WatchDog Timer Driver v%s\n",
+ ESB_VERSION);
+
+ if (cards_found > 1) {
+ printk(KERN_ERR PFX "This driver only supports 1 device\n");
+ return -ENODEV;
+ }
+
/* Check whether or not the hardware watchdog is there */
- if (!esb_getdevice() || esb_pci == NULL)
+ if (!esb_getdevice(pdev) || esb_pci == NULL)
return -ENODEV;
/* Check that the heartbeat value is within it's range;
@@ -467,11 +464,11 @@ err_unmap:
iounmap(BASEADDR);
pci_release_region(esb_pci, 0);
pci_disable_device(esb_pci);
- pci_dev_put(esb_pci);
+ esb_pci = NULL;
return ret;
}
-static int __devexit esb_remove(struct platform_device *dev)
+static void __devexit esb_remove(struct pci_dev *pdev)
{
/* Stop the timer before we leave */
if (!nowayout)
@@ -482,54 +479,30 @@ static int __devexit esb_remove(struct platform_device *dev)
iounmap(BASEADDR);
pci_release_region(esb_pci, 0);
pci_disable_device(esb_pci);
- pci_dev_put(esb_pci);
- return 0;
+ esb_pci = NULL;
}
-static void esb_shutdown(struct platform_device *dev)
+static void esb_shutdown(struct pci_dev *pdev)
{
esb_timer_stop();
}
-static struct platform_driver esb_platform_driver = {
+static struct pci_driver esb_driver = {
+ .name = ESB_MODULE_NAME,
+ .id_table = esb_pci_tbl,
.probe = esb_probe,
.remove = __devexit_p(esb_remove),
.shutdown = esb_shutdown,
- .driver = {
- .owner = THIS_MODULE,
- .name = ESB_MODULE_NAME,
- },
};
static int __init watchdog_init(void)
{
- int err;
-
- printk(KERN_INFO PFX "Intel 6300ESB WatchDog Timer Driver v%s\n",
- ESB_VERSION);
-
- err = platform_driver_register(&esb_platform_driver);
- if (err)
- return err;
-
- esb_platform_device = platform_device_register_simple(ESB_MODULE_NAME,
- -1, NULL, 0);
- if (IS_ERR(esb_platform_device)) {
- err = PTR_ERR(esb_platform_device);
- goto unreg_platform_driver;
- }
-
- return 0;
-
-unreg_platform_driver:
- platform_driver_unregister(&esb_platform_driver);
- return err;
+ return pci_register_driver(&esb_driver);
}
static void __exit watchdog_cleanup(void)
{
- platform_device_unregister(esb_platform_device);
- platform_driver_unregister(&esb_platform_driver);
+ pci_unregister_driver(&esb_driver);
printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
}
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index 4bdb7f1a907..44bc6aa46ed 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -584,7 +584,7 @@ static long iTCO_wdt_ioctl(struct file *file, unsigned int cmd,
int new_heartbeat;
void __user *argp = (void __user *)arg;
int __user *p = argp;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_SETTIMEOUT |
WDIOF_KEEPALIVEPING |
WDIOF_MAGICCLOSE,
@@ -698,7 +698,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
if (iTCO_wdt_private.iTCO_version == 2) {
pci_read_config_dword(pdev, 0xf0, &base_address);
if ((base_address & 1) == 0) {
- printk(KERN_ERR PFX "RCBA is disabled by harddware\n");
+ printk(KERN_ERR PFX "RCBA is disabled by hardware\n");
ret = -ENODEV;
goto out;
}
@@ -708,8 +708,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
/* Check chipset's NO_REBOOT bit */
if (iTCO_wdt_unset_NO_REBOOT_bit() && iTCO_vendor_check_noreboot_on()) {
- printk(KERN_ERR PFX "failed to reset NO_REBOOT flag, "
- "reboot disabled by hardware\n");
+ printk(KERN_INFO PFX "unable to reset NO_REBOOT flag, "
+ "platform may have disabled it\n");
ret = -ENODEV; /* Cannot reset NO_REBOOT bit */
goto out_unmap;
}
@@ -805,6 +805,7 @@ static void __devexit iTCO_wdt_cleanup(void)
static int __devinit iTCO_wdt_probe(struct platform_device *dev)
{
+ int ret = -ENODEV;
int found = 0;
struct pci_dev *pdev = NULL;
const struct pci_device_id *ent;
@@ -814,19 +815,17 @@ static int __devinit iTCO_wdt_probe(struct platform_device *dev)
for_each_pci_dev(pdev) {
ent = pci_match_id(iTCO_wdt_pci_tbl, pdev);
if (ent) {
- if (!(iTCO_wdt_init(pdev, ent, dev))) {
- found++;
+ found++;
+ ret = iTCO_wdt_init(pdev, ent, dev);
+ if (!ret)
break;
- }
}
}
- if (!found) {
+ if (!found)
printk(KERN_INFO PFX "No card detected\n");
- return -ENODEV;
- }
- return 0;
+ return ret;
}
static int __devexit iTCO_wdt_remove(struct platform_device *dev)
diff --git a/drivers/watchdog/ib700wdt.c b/drivers/watchdog/ib700wdt.c
index 4bef3ddff4a..0149d8dfc81 100644
--- a/drivers/watchdog/ib700wdt.c
+++ b/drivers/watchdog/ib700wdt.c
@@ -174,7 +174,7 @@ static long ibwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
void __user *argp = (void __user *)arg;
int __user *p = argp;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT
| WDIOF_MAGICCLOSE,
.firmware_version = 1,
diff --git a/drivers/watchdog/indydog.c b/drivers/watchdog/indydog.c
index bea8a124a55..1cc5609666d 100644
--- a/drivers/watchdog/indydog.c
+++ b/drivers/watchdog/indydog.c
@@ -111,7 +111,7 @@ static long indydog_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
int options, retval = -EINVAL;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING,
.firmware_version = 0,
.identity = "Hardware Watchdog for SGI IP22",
diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c
index daed48ded7f..f52c162b1be 100644
--- a/drivers/watchdog/it8712f_wdt.c
+++ b/drivers/watchdog/it8712f_wdt.c
@@ -236,7 +236,7 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd,
{
void __user *argp = (void __user *)arg;
int __user *p = argp;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.identity = "IT8712F Watchdog",
.firmware_version = 1,
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c
index cc133c531d0..b709b3b2d1e 100644
--- a/drivers/watchdog/it87_wdt.c
+++ b/drivers/watchdog/it87_wdt.c
@@ -421,7 +421,7 @@ static ssize_t wdt_write(struct file *file, const char __user *buf,
return count;
}
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
.firmware_version = 1,
.identity = WATCHDOG_NAME,
diff --git a/drivers/watchdog/ixp2000_wdt.c b/drivers/watchdog/ixp2000_wdt.c
index 3c79dc58795..e86952a7168 100644
--- a/drivers/watchdog/ixp2000_wdt.c
+++ b/drivers/watchdog/ixp2000_wdt.c
@@ -100,7 +100,7 @@ static ssize_t ixp2000_wdt_write(struct file *file, const char *data,
}
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
.options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT |
WDIOF_KEEPALIVEPING,
.identity = "IXP2000 Watchdog",
diff --git a/drivers/watchdog/ixp4xx_wdt.c b/drivers/watchdog/ixp4xx_wdt.c
index 147b4d5c63b..e02c0ecda26 100644
--- a/drivers/watchdog/ixp4xx_wdt.c
+++ b/drivers/watchdog/ixp4xx_wdt.c
@@ -89,7 +89,7 @@ ixp4xx_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
return len;
}
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
.options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE |
WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
.identity = "IXP4xx Watchdog",
diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c
index e1c82769b08..2852bb2e3fd 100644
--- a/drivers/watchdog/ks8695_wdt.c
+++ b/drivers/watchdog/ks8695_wdt.c
@@ -145,7 +145,7 @@ static int ks8695_wdt_close(struct inode *inode, struct file *file)
return 0;
}
-static struct watchdog_info ks8695_wdt_info = {
+static const struct watchdog_info ks8695_wdt_info = {
.identity = "ks8695 watchdog",
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
};
diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c
index 47d719717a3..2d118cf022f 100644
--- a/drivers/watchdog/machzwd.c
+++ b/drivers/watchdog/machzwd.c
@@ -101,7 +101,7 @@ MODULE_PARM_DESC(nowayout,
#define PFX "machzwd"
-static struct watchdog_info zf_info = {
+static const struct watchdog_info zf_info = {
.options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
.firmware_version = 1,
.identity = "ZF-Logic watchdog",
diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c
new file mode 100644
index 00000000000..6eb91d75760
--- /dev/null
+++ b/drivers/watchdog/max63xx_wdt.c
@@ -0,0 +1,397 @@
+/*
+ * drivers/char/watchdog/max63xx_wdt.c
+ *
+ * Driver for max63{69,70,71,72,73,74} watchdog timers
+ *
+ * Copyright (C) 2009 Marc Zyngier <maz@misterjones.org>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * This driver assumes the watchdog pins are memory mapped (as it is
+ * the case for the Arcom Zeus). Should it be connected over GPIOs or
+ * another interface, some abstraction will have to be introduced.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/device.h>
+
+#define DEFAULT_HEARTBEAT 60
+#define MAX_HEARTBEAT 60
+
+static int heartbeat = DEFAULT_HEARTBEAT;
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+/*
+ * Memory mapping: a single byte, 3 first lower bits to select bit 3
+ * to ping the watchdog.
+ */
+#define MAX6369_WDSET (7 << 0)
+#define MAX6369_WDI (1 << 3)
+
+static DEFINE_SPINLOCK(io_lock);
+
+static unsigned long wdt_status;
+#define WDT_IN_USE 0
+#define WDT_RUNNING 1
+#define WDT_OK_TO_CLOSE 2
+
+static int nodelay;
+static struct resource *wdt_mem;
+static void __iomem *wdt_base;
+static struct platform_device *max63xx_pdev;
+
+/*
+ * The timeout values used are actually the absolute minimum the chip
+ * offers. Typical values on my board are slightly over twice as long
+ * (10s setting ends up with a 25s timeout), and can be up to 3 times
+ * the nominal setting (according to the datasheet). So please take
+ * these values with a grain of salt. Same goes for the initial delay
+ * "feature". Only max6373/74 have a few settings without this initial
+ * delay (selected with the "nodelay" parameter).
+ *
+ * I also decided to remove from the tables any timeout smaller than a
+ * second, as it looked completly overkill...
+ */
+
+/* Timeouts in second */
+struct max63xx_timeout {
+ u8 wdset;
+ u8 tdelay;
+ u8 twd;
+};
+
+static struct max63xx_timeout max6369_table[] = {
+ { 5, 1, 1 },
+ { 6, 10, 10 },
+ { 7, 60, 60 },
+ { },
+};
+
+static struct max63xx_timeout max6371_table[] = {
+ { 6, 60, 3 },
+ { 7, 60, 60 },
+ { },
+};
+
+static struct max63xx_timeout max6373_table[] = {
+ { 2, 60, 1 },
+ { 5, 0, 1 },
+ { 1, 3, 3 },
+ { 7, 60, 10 },
+ { 6, 0, 10 },
+ { },
+};
+
+static struct max63xx_timeout *current_timeout;
+
+static struct max63xx_timeout *
+max63xx_select_timeout(struct max63xx_timeout *table, int value)
+{
+ while (table->twd) {
+ if (value <= table->twd) {
+ if (nodelay && table->tdelay == 0)
+ return table;
+
+ if (!nodelay)
+ return table;
+ }
+
+ table++;
+ }
+
+ return NULL;
+}
+
+static void max63xx_wdt_ping(void)
+{
+ u8 val;
+
+ spin_lock(&io_lock);
+
+ val = __raw_readb(wdt_base);
+
+ __raw_writeb(val | MAX6369_WDI, wdt_base);
+ __raw_writeb(val & ~MAX6369_WDI, wdt_base);
+
+ spin_unlock(&io_lock);
+}
+
+static void max63xx_wdt_enable(struct max63xx_timeout *entry)
+{
+ u8 val;
+
+ if (test_and_set_bit(WDT_RUNNING, &wdt_status))
+ return;
+
+ spin_lock(&io_lock);
+
+ val = __raw_readb(wdt_base);
+ val &= ~MAX6369_WDSET;
+ val |= entry->wdset;
+ __raw_writeb(val, wdt_base);
+
+ spin_unlock(&io_lock);
+
+ /* check for a edge triggered startup */
+ if (entry->tdelay == 0)
+ max63xx_wdt_ping();
+}
+
+static void max63xx_wdt_disable(void)
+{
+ spin_lock(&io_lock);
+
+ __raw_writeb(3, wdt_base);
+
+ spin_unlock(&io_lock);
+
+ clear_bit(WDT_RUNNING, &wdt_status);
+}
+
+static int max63xx_wdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(WDT_IN_USE, &wdt_status))
+ return -EBUSY;
+
+ max63xx_wdt_enable(current_timeout);
+ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+ return nonseekable_open(inode, file);
+}
+
+static ssize_t max63xx_wdt_write(struct file *file, const char *data,
+ size_t len, loff_t *ppos)
+{
+ if (len) {
+ if (!nowayout) {
+ size_t i;
+
+ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+ for (i = 0; i != len; i++) {
+ char c;
+
+ if (get_user(c, data + i))
+ return -EFAULT;
+
+ if (c == 'V')
+ set_bit(WDT_OK_TO_CLOSE, &wdt_status);
+ }
+ }
+
+ max63xx_wdt_ping();
+ }
+
+ return len;
+}
+
+static const struct watchdog_info ident = {
+ .options = WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+ .identity = "max63xx Watchdog",
+};
+
+static long max63xx_wdt_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret = -ENOTTY;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ ret = copy_to_user((struct watchdog_info *)arg, &ident,
+ sizeof(ident)) ? -EFAULT : 0;
+ break;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ ret = put_user(0, (int *)arg);
+ break;
+
+ case WDIOC_KEEPALIVE:
+ max63xx_wdt_ping();
+ ret = 0;
+ break;
+
+ case WDIOC_GETTIMEOUT:
+ ret = put_user(heartbeat, (int *)arg);
+ break;
+ }
+ return ret;
+}
+
+static int max63xx_wdt_release(struct inode *inode, struct file *file)
+{
+ if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
+ max63xx_wdt_disable();
+ else
+ dev_crit(&max63xx_pdev->dev,
+ "device closed unexpectedly - timer will not stop\n");
+
+ clear_bit(WDT_IN_USE, &wdt_status);
+ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
+
+ return 0;
+}
+
+static const struct file_operations max63xx_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = max63xx_wdt_write,
+ .unlocked_ioctl = max63xx_wdt_ioctl,
+ .open = max63xx_wdt_open,
+ .release = max63xx_wdt_release,
+};
+
+static struct miscdevice max63xx_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &max63xx_wdt_fops,
+};
+
+static int __devinit max63xx_wdt_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ int size;
+ struct resource *res;
+ struct device *dev = &pdev->dev;
+ struct max63xx_timeout *table;
+
+ table = (struct max63xx_timeout *)pdev->id_entry->driver_data;
+
+ if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
+ heartbeat = DEFAULT_HEARTBEAT;
+
+ dev_info(dev, "requesting %ds heartbeat\n", heartbeat);
+ current_timeout = max63xx_select_timeout(table, heartbeat);
+
+ if (!current_timeout) {
+ dev_err(dev, "unable to satisfy heartbeat request\n");
+ return -EINVAL;
+ }
+
+ dev_info(dev, "using %ds heartbeat with %ds initial delay\n",
+ current_timeout->twd, current_timeout->tdelay);
+
+ heartbeat = current_timeout->twd;
+
+ max63xx_pdev = pdev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(dev, "failed to get memory region resource\n");
+ return -ENOENT;
+ }
+
+ size = resource_size(res);
+ wdt_mem = request_mem_region(res->start, size, pdev->name);
+
+ if (wdt_mem == NULL) {
+ dev_err(dev, "failed to get memory region\n");
+ return -ENOENT;
+ }
+
+ wdt_base = ioremap(res->start, size);
+ if (!wdt_base) {
+ dev_err(dev, "failed to map memory region\n");
+ ret = -ENOMEM;
+ goto out_request;
+ }
+
+ ret = misc_register(&max63xx_wdt_miscdev);
+ if (ret < 0) {
+ dev_err(dev, "cannot register misc device\n");
+ goto out_unmap;
+ }
+
+ return 0;
+
+out_unmap:
+ iounmap(wdt_base);
+out_request:
+ release_resource(wdt_mem);
+ kfree(wdt_mem);
+
+ return ret;
+}
+
+static int __devexit max63xx_wdt_remove(struct platform_device *pdev)
+{
+ misc_deregister(&max63xx_wdt_miscdev);
+ if (wdt_mem) {
+ release_resource(wdt_mem);
+ kfree(wdt_mem);
+ wdt_mem = NULL;
+ }
+
+ if (wdt_base)
+ iounmap(wdt_base);
+
+ return 0;
+}
+
+static struct platform_device_id max63xx_id_table[] = {
+ { "max6369_wdt", (kernel_ulong_t)max6369_table, },
+ { "max6370_wdt", (kernel_ulong_t)max6369_table, },
+ { "max6371_wdt", (kernel_ulong_t)max6371_table, },
+ { "max6372_wdt", (kernel_ulong_t)max6371_table, },
+ { "max6373_wdt", (kernel_ulong_t)max6373_table, },
+ { "max6374_wdt", (kernel_ulong_t)max6373_table, },
+ { },
+};
+MODULE_DEVICE_TABLE(platform, max63xx_id_table);
+
+static struct platform_driver max63xx_wdt_driver = {
+ .probe = max63xx_wdt_probe,
+ .remove = __devexit_p(max63xx_wdt_remove),
+ .id_table = max63xx_id_table,
+ .driver = {
+ .name = "max63xx_wdt",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init max63xx_wdt_init(void)
+{
+ return platform_driver_register(&max63xx_wdt_driver);
+}
+
+static void __exit max63xx_wdt_exit(void)
+{
+ platform_driver_unregister(&max63xx_wdt_driver);
+}
+
+module_init(max63xx_wdt_init);
+module_exit(max63xx_wdt_exit);
+
+MODULE_AUTHOR("Marc Zyngier <maz@misterjones.org>");
+MODULE_DESCRIPTION("max63xx Watchdog Driver");
+
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat,
+ "Watchdog heartbeat period in seconds from 1 to "
+ __MODULE_STRING(MAX_HEARTBEAT) ", default "
+ __MODULE_STRING(DEFAULT_HEARTBEAT));
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+module_param(nodelay, int, 0);
+MODULE_PARM_DESC(nodelay,
+ "Force selection of a timeout setting without initial delay "
+ "(max6373/74 only, default=0)");
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/watchdog/mixcomwd.c b/drivers/watchdog/mixcomwd.c
index 407b025cb10..bc820d16699 100644
--- a/drivers/watchdog/mixcomwd.c
+++ b/drivers/watchdog/mixcomwd.c
@@ -201,7 +201,7 @@ static long mixcomwd_ioctl(struct file *file,
void __user *argp = (void __user *)arg;
int __user *p = argp;
int status;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
.firmware_version = 1,
.identity = "MixCOM watchdog",
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c
index 38c588ee694..4e3941c5e29 100644
--- a/drivers/watchdog/mpc8xxx_wdt.c
+++ b/drivers/watchdog/mpc8xxx_wdt.c
@@ -148,7 +148,7 @@ static long mpc8xxx_wdt_ioctl(struct file *file, unsigned int cmd,
{
void __user *argp = (void __user *)arg;
int __user *p = argp;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING,
.firmware_version = 1,
.identity = "MPC8xxx",
diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c
index a2dc07c2ed4..b0646dac924 100644
--- a/drivers/watchdog/mpcore_wdt.c
+++ b/drivers/watchdog/mpcore_wdt.c
@@ -213,7 +213,7 @@ static ssize_t mpcore_wdt_write(struct file *file, const char *data,
return len;
}
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
.options = WDIOF_SETTIMEOUT |
WDIOF_KEEPALIVEPING |
WDIOF_MAGICCLOSE,
diff --git a/drivers/watchdog/mv64x60_wdt.c b/drivers/watchdog/mv64x60_wdt.c
index a51dbe4c43d..97f8a48d8b7 100644
--- a/drivers/watchdog/mv64x60_wdt.c
+++ b/drivers/watchdog/mv64x60_wdt.c
@@ -179,7 +179,7 @@ static long mv64x60_wdt_ioctl(struct file *file,
int timeout;
int options;
void __user *argp = (void __user *)arg;
- static struct watchdog_info info = {
+ static const struct watchdog_info info = {
.options = WDIOF_SETTIMEOUT |
WDIOF_MAGICCLOSE |
WDIOF_KEEPALIVEPING,
diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c
index 1a2b916e3f8..d3aa2f1fe61 100644
--- a/drivers/watchdog/pc87413_wdt.c
+++ b/drivers/watchdog/pc87413_wdt.c
@@ -407,7 +407,7 @@ static long pc87413_ioctl(struct file *file, unsigned int cmd,
int __user *i;
} uarg;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING |
WDIOF_SETTIMEOUT |
WDIOF_MAGICCLOSE,
diff --git a/drivers/watchdog/pcwd.c b/drivers/watchdog/pcwd.c
index aa9512321f3..06f7922606c 100644
--- a/drivers/watchdog/pcwd.c
+++ b/drivers/watchdog/pcwd.c
@@ -606,7 +606,7 @@ static long pcwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
int temperature;
int new_heartbeat;
int __user *argp = (int __user *)arg;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_OVERHEAT |
WDIOF_CARDRESET |
WDIOF_KEEPALIVEPING |
diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c
index 698f51bff1b..64374d636f0 100644
--- a/drivers/watchdog/pcwd_pci.c
+++ b/drivers/watchdog/pcwd_pci.c
@@ -481,7 +481,7 @@ static long pcipcwd_ioctl(struct file *file, unsigned int cmd,
{
void __user *argp = (void __user *)arg;
int __user *p = argp;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_OVERHEAT |
WDIOF_CARDRESET |
WDIOF_KEEPALIVEPING |
diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c
index 052fe451851..8e4eacc5bb5 100644
--- a/drivers/watchdog/pcwd_usb.c
+++ b/drivers/watchdog/pcwd_usb.c
@@ -404,7 +404,7 @@ static long usb_pcwd_ioctl(struct file *file, unsigned int cmd,
{
void __user *argp = (void __user *)arg;
int __user *p = argp;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING |
WDIOF_SETTIMEOUT |
WDIOF_MAGICCLOSE,
diff --git a/drivers/watchdog/pika_wdt.c b/drivers/watchdog/pika_wdt.c
index 2d22e996e99..435ec2aed4f 100644
--- a/drivers/watchdog/pika_wdt.c
+++ b/drivers/watchdog/pika_wdt.c
@@ -52,7 +52,7 @@ static struct {
struct timer_list timer; /* The timer that pings the watchdog */
} pikawdt_private;
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
.identity = DRV_NAME,
.options = WDIOF_CARDRESET |
WDIOF_SETTIMEOUT |
diff --git a/drivers/watchdog/pnx833x_wdt.c b/drivers/watchdog/pnx833x_wdt.c
index 538ec2c0519..09102f09e68 100644
--- a/drivers/watchdog/pnx833x_wdt.c
+++ b/drivers/watchdog/pnx833x_wdt.c
@@ -141,7 +141,7 @@ static long pnx833x_wdt_ioctl(struct file *file, unsigned int cmd,
int options, new_timeout = 0;
uint32_t timeout, timeout_left = 0;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
.firmware_version = 0,
.identity = "Hardware Watchdog for PNX833x",
diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c
index bf12d06b587..d4c29b5311a 100644
--- a/drivers/watchdog/rc32434_wdt.c
+++ b/drivers/watchdog/rc32434_wdt.c
@@ -198,7 +198,7 @@ static long rc32434_wdt_ioctl(struct file *file, unsigned int cmd,
void __user *argp = (void __user *)arg;
int new_timeout;
unsigned int value;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_SETTIMEOUT |
WDIOF_KEEPALIVEPING |
WDIOF_MAGICCLOSE,
diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c
index 4976bfd1fce..69c6adbd820 100644
--- a/drivers/watchdog/rdc321x_wdt.c
+++ b/drivers/watchdog/rdc321x_wdt.c
@@ -149,7 +149,7 @@ static long rdc321x_wdt_ioctl(struct file *file, unsigned int cmd,
{
void __user *argp = (void __user *)arg;
unsigned int value;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_CARDRESET,
.identity = "RDC321x WDT",
};
diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c
index c14ae867690..ae57bf9e1b0 100644
--- a/drivers/watchdog/riowd.c
+++ b/drivers/watchdog/riowd.c
@@ -85,7 +85,7 @@ static int riowd_release(struct inode *inode, struct file *filp)
static long riowd_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
- static struct watchdog_info info = {
+ static const struct watchdog_info info = {
.options = WDIOF_SETTIMEOUT,
.firmware_version = 1,
.identity = DRIVER_NAME,
diff --git a/drivers/watchdog/sbc_fitpc2_wdt.c b/drivers/watchdog/sbc_fitpc2_wdt.c
index e6763d2a567..8d44c9b6fb5 100644
--- a/drivers/watchdog/sbc_fitpc2_wdt.c
+++ b/drivers/watchdog/sbc_fitpc2_wdt.c
@@ -111,7 +111,7 @@ out:
}
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
.options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT |
WDIOF_KEEPALIVEPING,
.identity = WATCHDOG_NAME,
diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c
index 569eb295a7a..9c40f48804f 100644
--- a/drivers/watchdog/sch311x_wdt.c
+++ b/drivers/watchdog/sch311x_wdt.c
@@ -250,7 +250,7 @@ static long sch311x_wdt_ioctl(struct file *file, unsigned int cmd,
int new_timeout;
void __user *argp = (void __user *)arg;
int __user *p = argp;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING |
WDIOF_SETTIMEOUT |
WDIOF_MAGICCLOSE,
diff --git a/drivers/watchdog/stmp3xxx_wdt.c b/drivers/watchdog/stmp3xxx_wdt.c
index 5dd952681f3..b3421fd2cda 100644
--- a/drivers/watchdog/stmp3xxx_wdt.c
+++ b/drivers/watchdog/stmp3xxx_wdt.c
@@ -94,7 +94,7 @@ static ssize_t stmp3xxx_wdt_write(struct file *file, const char __user *data,
return len;
}
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
.options = WDIOF_CARDRESET |
WDIOF_MAGICCLOSE |
WDIOF_SETTIMEOUT |
diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c
new file mode 100644
index 00000000000..565a2c3321e
--- /dev/null
+++ b/drivers/watchdog/ts72xx_wdt.c
@@ -0,0 +1,520 @@
+/*
+ * Watchdog driver for Technologic Systems TS-72xx based SBCs
+ * (TS-7200, TS-7250 and TS-7260). These boards have external
+ * glue logic CPLD chip, which includes programmable watchdog
+ * timer.
+ *
+ * Copyright (c) 2009 Mika Westerberg <mika.westerberg@iki.fi>
+ *
+ * This driver is based on ep93xx_wdt and wm831x_wdt drivers.
+ *
+ * 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/fs.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/miscdevice.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/watchdog.h>
+#include <linux/uaccess.h>
+
+#define TS72XX_WDT_FEED_VAL 0x05
+#define TS72XX_WDT_DEFAULT_TIMEOUT 8
+
+static int timeout = TS72XX_WDT_DEFAULT_TIMEOUT;
+module_param(timeout, int, 0);
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. "
+ "(1 <= timeout <= 8, default="
+ __MODULE_STRING(TS72XX_WDT_DEFAULT_TIMEOUT)
+ ")");
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
+
+/**
+ * struct ts72xx_wdt - watchdog control structure
+ * @lock: lock that protects this structure
+ * @regval: watchdog timeout value suitable for control register
+ * @flags: flags controlling watchdog device state
+ * @control_reg: watchdog control register
+ * @feed_reg: watchdog feed register
+ * @pdev: back pointer to platform dev
+ */
+struct ts72xx_wdt {
+ struct mutex lock;
+ int regval;
+
+#define TS72XX_WDT_BUSY_FLAG 1
+#define TS72XX_WDT_EXPECT_CLOSE_FLAG 2
+ int flags;
+
+ void __iomem *control_reg;
+ void __iomem *feed_reg;
+
+ struct platform_device *pdev;
+};
+
+struct platform_device *ts72xx_wdt_pdev;
+
+/*
+ * TS-72xx Watchdog supports following timeouts (value written
+ * to control register):
+ * value description
+ * -------------------------
+ * 0x00 watchdog disabled
+ * 0x01 250ms
+ * 0x02 500ms
+ * 0x03 1s
+ * 0x04 reserved
+ * 0x05 2s
+ * 0x06 4s
+ * 0x07 8s
+ *
+ * Timeouts below 1s are not very usable so we don't
+ * allow them at all.
+ *
+ * We provide two functions that convert between these:
+ * timeout_to_regval() and regval_to_timeout().
+ */
+static const struct {
+ int timeout;
+ int regval;
+} ts72xx_wdt_map[] = {
+ { 1, 3 },
+ { 2, 5 },
+ { 4, 6 },
+ { 8, 7 },
+};
+
+/**
+ * timeout_to_regval() - converts given timeout to control register value
+ * @new_timeout: timeout in seconds to be converted
+ *
+ * Function converts given @new_timeout into valid value that can
+ * be programmed into watchdog control register. When conversion is
+ * not possible, function returns %-EINVAL.
+ */
+static int timeout_to_regval(int new_timeout)
+{
+ int i;
+
+ /* first limit it to 1 - 8 seconds */
+ new_timeout = clamp_val(new_timeout, 1, 8);
+
+ for (i = 0; i < ARRAY_SIZE(ts72xx_wdt_map); i++) {
+ if (ts72xx_wdt_map[i].timeout >= new_timeout)
+ return ts72xx_wdt_map[i].regval;
+ }
+
+ return -EINVAL;
+}
+
+/**
+ * regval_to_timeout() - converts control register value to timeout
+ * @regval: control register value to be converted
+ *
+ * Function converts given @regval to timeout in seconds (1, 2, 4 or 8).
+ * If @regval cannot be converted, function returns %-EINVAL.
+ */
+static int regval_to_timeout(int regval)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ts72xx_wdt_map); i++) {
+ if (ts72xx_wdt_map[i].regval == regval)
+ return ts72xx_wdt_map[i].timeout;
+ }
+
+ return -EINVAL;
+}
+
+/**
+ * ts72xx_wdt_kick() - kick the watchdog
+ * @wdt: watchdog to be kicked
+ *
+ * Called with @wdt->lock held.
+ */
+static inline void ts72xx_wdt_kick(struct ts72xx_wdt *wdt)
+{
+ __raw_writeb(TS72XX_WDT_FEED_VAL, wdt->feed_reg);
+}
+
+/**
+ * ts72xx_wdt_start() - starts the watchdog timer
+ * @wdt: watchdog to be started
+ *
+ * This function programs timeout to watchdog timer
+ * and starts it.
+ *
+ * Called with @wdt->lock held.
+ */
+static void ts72xx_wdt_start(struct ts72xx_wdt *wdt)
+{
+ /*
+ * To program the wdt, it first must be "fed" and
+ * only after that (within 30 usecs) the configuration
+ * can be changed.
+ */
+ ts72xx_wdt_kick(wdt);
+ __raw_writeb((u8)wdt->regval, wdt->control_reg);
+}
+
+/**
+ * ts72xx_wdt_stop() - stops the watchdog timer
+ * @wdt: watchdog to be stopped
+ *
+ * Called with @wdt->lock held.
+ */
+static void ts72xx_wdt_stop(struct ts72xx_wdt *wdt)
+{
+ ts72xx_wdt_kick(wdt);
+ __raw_writeb(0, wdt->control_reg);
+}
+
+static int ts72xx_wdt_open(struct inode *inode, struct file *file)
+{
+ struct ts72xx_wdt *wdt = platform_get_drvdata(ts72xx_wdt_pdev);
+ int regval;
+
+ /*
+ * Try to convert default timeout to valid register
+ * value first.
+ */
+ regval = timeout_to_regval(timeout);
+ if (regval < 0) {
+ dev_err(&wdt->pdev->dev,
+ "failed to convert timeout (%d) to register value\n",
+ timeout);
+ return -EINVAL;
+ }
+
+ if (mutex_lock_interruptible(&wdt->lock))
+ return -ERESTARTSYS;
+
+ if ((wdt->flags & TS72XX_WDT_BUSY_FLAG) != 0) {
+ mutex_unlock(&wdt->lock);
+ return -EBUSY;
+ }
+
+ wdt->flags = TS72XX_WDT_BUSY_FLAG;
+ wdt->regval = regval;
+ file->private_data = wdt;
+
+ ts72xx_wdt_start(wdt);
+
+ mutex_unlock(&wdt->lock);
+ return nonseekable_open(inode, file);
+}
+
+static int ts72xx_wdt_release(struct inode *inode, struct file *file)
+{
+ struct ts72xx_wdt *wdt = file->private_data;
+
+ if (mutex_lock_interruptible(&wdt->lock))
+ return -ERESTARTSYS;
+
+ if ((wdt->flags & TS72XX_WDT_EXPECT_CLOSE_FLAG) != 0) {
+ ts72xx_wdt_stop(wdt);
+ } else {
+ dev_warn(&wdt->pdev->dev,
+ "TS-72XX WDT device closed unexpectly. "
+ "Watchdog timer will not stop!\n");
+ /*
+ * Kick it one more time, to give userland some time
+ * to recover (for example, respawning the kicker
+ * daemon).
+ */
+ ts72xx_wdt_kick(wdt);
+ }
+
+ wdt->flags = 0;
+
+ mutex_unlock(&wdt->lock);
+ return 0;
+}
+
+static ssize_t ts72xx_wdt_write(struct file *file,
+ const char __user *data,
+ size_t len,
+ loff_t *ppos)
+{
+ struct ts72xx_wdt *wdt = file->private_data;
+
+ if (!len)
+ return 0;
+
+ if (mutex_lock_interruptible(&wdt->lock))
+ return -ERESTARTSYS;
+
+ ts72xx_wdt_kick(wdt);
+
+ /*
+ * Support for magic character closing. User process
+ * writes 'V' into the device, just before it is closed.
+ * This means that we know that the wdt timer can be
+ * stopped after user closes the device.
+ */
+ if (!nowayout) {
+ int i;
+
+ for (i = 0; i < len; i++) {
+ char c;
+
+ /* In case it was set long ago */
+ wdt->flags &= ~TS72XX_WDT_EXPECT_CLOSE_FLAG;
+
+ if (get_user(c, data + i)) {
+ mutex_unlock(&wdt->lock);
+ return -EFAULT;
+ }
+ if (c == 'V') {
+ wdt->flags |= TS72XX_WDT_EXPECT_CLOSE_FLAG;
+ break;
+ }
+ }
+ }
+
+ mutex_unlock(&wdt->lock);
+ return len;
+}
+
+static const struct watchdog_info winfo = {
+ .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
+ WDIOF_MAGICCLOSE,
+ .firmware_version = 1,
+ .identity = "TS-72XX WDT",
+};
+
+static long ts72xx_wdt_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct ts72xx_wdt *wdt = file->private_data;
+ void __user *argp = (void __user *)arg;
+ int __user *p = (int __user *)argp;
+ int error = 0;
+
+ if (mutex_lock_interruptible(&wdt->lock))
+ return -ERESTARTSYS;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ error = copy_to_user(argp, &winfo, sizeof(winfo));
+ break;
+
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, p);
+
+ case WDIOC_KEEPALIVE:
+ ts72xx_wdt_kick(wdt);
+ break;
+
+ case WDIOC_SETOPTIONS: {
+ int options;
+
+ if (get_user(options, p)) {
+ error = -EFAULT;
+ break;
+ }
+
+ error = -EINVAL;
+
+ if ((options & WDIOS_DISABLECARD) != 0) {
+ ts72xx_wdt_stop(wdt);
+ error = 0;
+ }
+ if ((options & WDIOS_ENABLECARD) != 0) {
+ ts72xx_wdt_start(wdt);
+ error = 0;
+ }
+
+ break;
+ }
+
+ case WDIOC_SETTIMEOUT: {
+ int new_timeout;
+
+ if (get_user(new_timeout, p)) {
+ error = -EFAULT;
+ } else {
+ int regval;
+
+ regval = timeout_to_regval(new_timeout);
+ if (regval < 0) {
+ error = -EINVAL;
+ } else {
+ ts72xx_wdt_stop(wdt);
+ wdt->regval = regval;
+ ts72xx_wdt_start(wdt);
+ }
+ }
+ if (error)
+ break;
+
+ /*FALLTHROUGH*/
+ }
+
+ case WDIOC_GETTIMEOUT:
+ if (put_user(regval_to_timeout(wdt->regval), p))
+ error = -EFAULT;
+ break;
+
+ default:
+ error = -ENOTTY;
+ break;
+ }
+
+ mutex_unlock(&wdt->lock);
+ return error;
+}
+
+static const struct file_operations ts72xx_wdt_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = ts72xx_wdt_open,
+ .release = ts72xx_wdt_release,
+ .write = ts72xx_wdt_write,
+ .unlocked_ioctl = ts72xx_wdt_ioctl,
+};
+
+static struct miscdevice ts72xx_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &ts72xx_wdt_fops,
+};
+
+static __devinit int ts72xx_wdt_probe(struct platform_device *pdev)
+{
+ struct ts72xx_wdt *wdt;
+ struct resource *r1, *r2;
+ int error = 0;
+
+ wdt = kzalloc(sizeof(struct ts72xx_wdt), GFP_KERNEL);
+ if (!wdt) {
+ dev_err(&pdev->dev, "failed to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ r1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!r1) {
+ dev_err(&pdev->dev, "failed to get memory resource\n");
+ error = -ENODEV;
+ goto fail;
+ }
+
+ r1 = request_mem_region(r1->start, resource_size(r1), pdev->name);
+ if (!r1) {
+ dev_err(&pdev->dev, "cannot request memory region\n");
+ error = -EBUSY;
+ goto fail;
+ }
+
+ wdt->control_reg = ioremap(r1->start, resource_size(r1));
+ if (!wdt->control_reg) {
+ dev_err(&pdev->dev, "failed to map memory\n");
+ error = -ENODEV;
+ goto fail_free_control;
+ }
+
+ r2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!r2) {
+ dev_err(&pdev->dev, "failed to get memory resource\n");
+ error = -ENODEV;
+ goto fail_unmap_control;
+ }
+
+ r2 = request_mem_region(r2->start, resource_size(r2), pdev->name);
+ if (!r2) {
+ dev_err(&pdev->dev, "cannot request memory region\n");
+ error = -EBUSY;
+ goto fail_unmap_control;
+ }
+
+ wdt->feed_reg = ioremap(r2->start, resource_size(r2));
+ if (!wdt->feed_reg) {
+ dev_err(&pdev->dev, "failed to map memory\n");
+ error = -ENODEV;
+ goto fail_free_feed;
+ }
+
+ platform_set_drvdata(pdev, wdt);
+ ts72xx_wdt_pdev = pdev;
+ wdt->pdev = pdev;
+ mutex_init(&wdt->lock);
+
+ error = misc_register(&ts72xx_wdt_miscdev);
+ if (error) {
+ dev_err(&pdev->dev, "failed to register miscdev\n");
+ goto fail_unmap_feed;
+ }
+
+ dev_info(&pdev->dev, "TS-72xx Watchdog driver\n");
+
+ return 0;
+
+fail_unmap_feed:
+ platform_set_drvdata(pdev, NULL);
+ iounmap(wdt->feed_reg);
+fail_free_feed:
+ release_mem_region(r2->start, resource_size(r2));
+fail_unmap_control:
+ iounmap(wdt->control_reg);
+fail_free_control:
+ release_mem_region(r1->start, resource_size(r1));
+fail:
+ kfree(wdt);
+ return error;
+}
+
+static __devexit int ts72xx_wdt_remove(struct platform_device *pdev)
+{
+ struct ts72xx_wdt *wdt = platform_get_drvdata(pdev);
+ struct resource *res;
+ int error;
+
+ error = misc_deregister(&ts72xx_wdt_miscdev);
+ platform_set_drvdata(pdev, NULL);
+
+ iounmap(wdt->feed_reg);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ release_mem_region(res->start, resource_size(res));
+
+ iounmap(wdt->control_reg);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(res->start, resource_size(res));
+
+ kfree(wdt);
+ return error;
+}
+
+static struct platform_driver ts72xx_wdt_driver = {
+ .probe = ts72xx_wdt_probe,
+ .remove = __devexit_p(ts72xx_wdt_remove),
+ .driver = {
+ .name = "ts72xx-wdt",
+ .owner = THIS_MODULE,
+ },
+};
+
+static __init int ts72xx_wdt_init(void)
+{
+ return platform_driver_register(&ts72xx_wdt_driver);
+}
+module_init(ts72xx_wdt_init);
+
+static __exit void ts72xx_wdt_exit(void)
+{
+ platform_driver_unregister(&ts72xx_wdt_driver);
+}
+module_exit(ts72xx_wdt_exit);
+
+MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
+MODULE_DESCRIPTION("TS-72xx SBC Watchdog");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ts72xx-wdt");
diff --git a/drivers/watchdog/txx9wdt.c b/drivers/watchdog/txx9wdt.c
index d635566e930..9e9ed7bfabc 100644
--- a/drivers/watchdog/txx9wdt.c
+++ b/drivers/watchdog/txx9wdt.c
@@ -13,7 +13,6 @@
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/fs.h>
-#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/uaccess.h>
#include <linux/platform_device.h>
@@ -166,14 +165,6 @@ static long txx9wdt_ioctl(struct file *file, unsigned int cmd,
}
}
-static int txx9wdt_notify_sys(struct notifier_block *this, unsigned long code,
- void *unused)
-{
- if (code == SYS_DOWN || code == SYS_HALT)
- txx9wdt_stop();
- return NOTIFY_DONE;
-}
-
static const struct file_operations txx9wdt_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
@@ -189,10 +180,6 @@ static struct miscdevice txx9wdt_miscdev = {
.fops = &txx9wdt_fops,
};
-static struct notifier_block txx9wdt_notifier = {
- .notifier_call = txx9wdt_notify_sys,
-};
-
static int __init txx9wdt_probe(struct platform_device *dev)
{
struct resource *res;
@@ -221,13 +208,8 @@ static int __init txx9wdt_probe(struct platform_device *dev)
if (!txx9wdt_reg)
goto exit_busy;
- ret = register_reboot_notifier(&txx9wdt_notifier);
- if (ret)
- goto exit;
-
ret = misc_register(&txx9wdt_miscdev);
if (ret) {
- unregister_reboot_notifier(&txx9wdt_notifier);
goto exit;
}
@@ -249,14 +231,19 @@ exit:
static int __exit txx9wdt_remove(struct platform_device *dev)
{
misc_deregister(&txx9wdt_miscdev);
- unregister_reboot_notifier(&txx9wdt_notifier);
clk_disable(txx9_imclk);
clk_put(txx9_imclk);
return 0;
}
+static void txx9wdt_shutdown(struct platform_device *dev)
+{
+ txx9wdt_stop();
+}
+
static struct platform_driver txx9wdt_driver = {
.remove = __exit_p(txx9wdt_remove),
+ .shutdown = txx9wdt_shutdown,
.driver = {
.name = "txx9wdt",
.owner = THIS_MODULE,
diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c
index f201accc4e3..0f5288df009 100644
--- a/drivers/watchdog/w83627hf_wdt.c
+++ b/drivers/watchdog/w83627hf_wdt.c
@@ -201,7 +201,7 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
void __user *argp = (void __user *)arg;
int __user *p = argp;
int new_timeout;
- static struct watchdog_info ident = {
+ static const struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
WDIOF_MAGICCLOSE,
.firmware_version = 1,
diff --git a/drivers/watchdog/w83977f_wdt.c b/drivers/watchdog/w83977f_wdt.c
index 0560182a1d0..6e6743d1066 100644
--- a/drivers/watchdog/w83977f_wdt.c
+++ b/drivers/watchdog/w83977f_wdt.c
@@ -371,7 +371,7 @@ static ssize_t wdt_write(struct file *file, const char __user *buf,
* according to their available features.
*/
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
.firmware_version = 1,
.identity = WATCHDOG_NAME,
diff --git a/drivers/watchdog/wdrtas.c b/drivers/watchdog/wdrtas.c
index 5bfb1f2c531..94ec22b9e66 100644
--- a/drivers/watchdog/wdrtas.c
+++ b/drivers/watchdog/wdrtas.c
@@ -312,7 +312,7 @@ static long wdrtas_ioctl(struct file *file, unsigned int cmd,
{
int __user *argp = (void __user *)arg;
int i;
- static struct watchdog_info wdinfo = {
+ static const struct watchdog_info wdinfo = {
.options = WDRTAS_SUPPORTED_MASK,
.firmware_version = 0,
.identity = "wdrtas",
diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c
index 3bbefe9a263..bfda2e99dd8 100644
--- a/drivers/watchdog/wdt.c
+++ b/drivers/watchdog/wdt.c
@@ -358,7 +358,7 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
int new_heartbeat;
int status;
- static struct watchdog_info ident = {
+ struct watchdog_info ident = {
.options = WDIOF_SETTIMEOUT|
WDIOF_MAGICCLOSE|
WDIOF_KEEPALIVEPING,
diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c
index f368dd87083..7b22e3cdbc8 100644
--- a/drivers/watchdog/wdt_pci.c
+++ b/drivers/watchdog/wdt_pci.c
@@ -412,7 +412,7 @@ static long wdtpci_ioctl(struct file *file, unsigned int cmd,
int new_heartbeat;
int status;
- static struct watchdog_info ident = {
+ struct watchdog_info ident = {
.options = WDIOF_SETTIMEOUT|
WDIOF_MAGICCLOSE|
WDIOF_KEEPALIVEPING,
diff --git a/drivers/watchdog/wm831x_wdt.c b/drivers/watchdog/wm831x_wdt.c
index 775bcd807f3..8c4b2d5bb7d 100644
--- a/drivers/watchdog/wm831x_wdt.c
+++ b/drivers/watchdog/wm831x_wdt.c
@@ -213,7 +213,7 @@ static ssize_t wm831x_wdt_write(struct file *file,
return count;
}
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
.identity = "WM831x Watchdog",
};
diff --git a/drivers/watchdog/wm8350_wdt.c b/drivers/watchdog/wm8350_wdt.c
index a2d2e8eb228..89dd7b03529 100644
--- a/drivers/watchdog/wm8350_wdt.c
+++ b/drivers/watchdog/wm8350_wdt.c
@@ -177,7 +177,7 @@ static ssize_t wm8350_wdt_write(struct file *file,
return count;
}
-static struct watchdog_info ident = {
+static const struct watchdog_info ident = {
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
.identity = "WM8350 Watchdog",
};
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig
index cab100acf98..fad3df2c127 100644
--- a/drivers/xen/Kconfig
+++ b/drivers/xen/Kconfig
@@ -1,6 +1,8 @@
+menu "Xen driver support"
+ depends on XEN
+
config XEN_BALLOON
bool "Xen memory balloon driver"
- depends on XEN
default y
help
The balloon driver allows the Xen domain to request more memory from
@@ -20,7 +22,6 @@ config XEN_SCRUB_PAGES
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
@@ -30,7 +31,6 @@ config XEN_DEV_EVTCHN
config XENFS
tristate "Xen filesystem"
- depends on XEN
default y
help
The xen filesystem provides a way for domains to share
@@ -53,11 +53,13 @@ config XEN_COMPAT_XENFS
config XEN_SYS_HYPERVISOR
bool "Create xen entries under /sys/hypervisor"
- depends on XEN && SYSFS
+ depends on 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
+ but will have no xen contents.
+
+endmenu
diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c
index ae5cb05a1a1..bb71ab2336c 100644
--- a/drivers/xen/sys-hypervisor.c
+++ b/drivers/xen/sys-hypervisor.c
@@ -426,7 +426,7 @@ static ssize_t hyp_sysfs_store(struct kobject *kobj,
return 0;
}
-static struct sysfs_ops hyp_sysfs_ops = {
+static const struct sysfs_ops hyp_sysfs_ops = {
.show = hyp_sysfs_show,
.store = hyp_sysfs_store,
};
diff --git a/fs/Kconfig b/fs/Kconfig
index 64d44efad7a..7405f071be6 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -177,6 +177,7 @@ source "fs/efs/Kconfig"
source "fs/jffs2/Kconfig"
# UBIFS File system configuration
source "fs/ubifs/Kconfig"
+source "fs/logfs/Kconfig"
source "fs/cramfs/Kconfig"
source "fs/squashfs/Kconfig"
source "fs/freevxfs/Kconfig"
diff --git a/fs/Makefile b/fs/Makefile
index af6d04700d9..c3633aa4691 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -99,6 +99,7 @@ obj-$(CONFIG_NTFS_FS) += ntfs/
obj-$(CONFIG_UFS_FS) += ufs/
obj-$(CONFIG_EFS_FS) += efs/
obj-$(CONFIG_JFFS2_FS) += jffs2/
+obj-$(CONFIG_LOGFS) += logfs/
obj-$(CONFIG_UBIFS_FS) += ubifs/
obj-$(CONFIG_AFFS_FS) += affs/
obj-$(CONFIG_ROMFS_FS) += romfs/
diff --git a/fs/attr.c b/fs/attr.c
index 0a6ea54cde7..0815e93bb48 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -81,7 +81,7 @@ int inode_newsize_ok(const struct inode *inode, loff_t offset)
if (inode->i_size < offset) {
unsigned long limit;
- limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
+ limit = rlimit(RLIMIT_FSIZE);
if (limit != RLIM_INFINITY && offset > limit)
goto out_sig;
if (offset > inode->i_sb->s_maxbytes)
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index fdd39709917..15d80bb35d6 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -24,6 +24,7 @@
#include <linux/binfmts.h>
#include <linux/personality.h>
#include <linux/init.h>
+#include <linux/coredump.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -60,26 +61,6 @@ static int set_brk(unsigned long start, unsigned long end)
}
/*
- * These are the only things you should do on a core-file: use only these
- * macros to write out all the necessary info.
- */
-
-static int dump_write(struct file *file, const void *addr, int nr)
-{
- return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
-}
-
-#define DUMP_WRITE(addr, nr) \
- if (!dump_write(file, (void *)(addr), (nr))) \
- goto end_coredump;
-
-#define DUMP_SEEK(offset) \
-if (file->f_op->llseek) { \
- if (file->f_op->llseek(file,(offset),0) != (offset)) \
- goto end_coredump; \
-} else file->f_pos = (offset)
-
-/*
* Routine writes a core dump image in the current directory.
* Currently only a stub-function.
*
@@ -130,26 +111,31 @@ static int aout_core_dump(struct coredump_params *cprm)
set_fs(KERNEL_DS);
/* struct user */
- DUMP_WRITE(&dump,sizeof(dump));
+ if (!dump_write(file, &dump, sizeof(dump)))
+ goto end_coredump;
/* Now dump all of the user data. Include malloced stuff as well */
- DUMP_SEEK(PAGE_SIZE);
+ if (!dump_seek(cprm->file, PAGE_SIZE - sizeof(dump)))
+ goto end_coredump;
/* now we start writing out the user space info */
set_fs(USER_DS);
/* Dump the data area */
if (dump.u_dsize != 0) {
dump_start = START_DATA(dump);
dump_size = dump.u_dsize << PAGE_SHIFT;
- DUMP_WRITE(dump_start,dump_size);
+ if (!dump_write(file, dump_start, dump_size))
+ goto end_coredump;
}
/* Now prepare to dump the stack area */
if (dump.u_ssize != 0) {
dump_start = START_STACK(dump);
dump_size = dump.u_ssize << PAGE_SHIFT;
- DUMP_WRITE(dump_start,dump_size);
+ if (!dump_write(file, dump_start, dump_size))
+ goto end_coredump;
}
/* Finally dump the task struct. Not be used by gdb, but could be useful */
set_fs(KERNEL_DS);
- DUMP_WRITE(current,sizeof(*current));
+ if (!dump_write(file, current, sizeof(*current)))
+ goto end_coredump;
end_coredump:
set_fs(fs);
return has_dumped;
@@ -247,7 +233,7 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
* size limits imposed on them by creating programs with large
* arrays in the data or bss.
*/
- rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
+ rlim = rlimit(RLIMIT_DATA);
if (rlim >= RLIM_INFINITY)
rlim = ~0;
if (ex.a_data + ex.a_bss > rlim)
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index fd5b2ea5d29..535e763ab1a 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -31,6 +31,7 @@
#include <linux/random.h>
#include <linux/elf.h>
#include <linux/utsname.h>
+#include <linux/coredump.h>
#include <asm/uaccess.h>
#include <asm/param.h>
#include <asm/page.h>
@@ -1085,36 +1086,6 @@ out:
* Modelled on fs/exec.c:aout_core_dump()
* Jeremy Fitzhardinge <jeremy@sw.oz.au>
*/
-/*
- * These are the only things you should do on a core-file: use only these
- * functions to write out all the necessary info.
- */
-static int dump_write(struct file *file, const void *addr, int nr)
-{
- return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
-}
-
-static int dump_seek(struct file *file, loff_t off)
-{
- if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
- if (file->f_op->llseek(file, off, SEEK_CUR) < 0)
- return 0;
- } else {
- char *buf = (char *)get_zeroed_page(GFP_KERNEL);
- if (!buf)
- return 0;
- while (off > 0) {
- unsigned long n = off;
- if (n > PAGE_SIZE)
- n = PAGE_SIZE;
- if (!dump_write(file, buf, n))
- return 0;
- off -= n;
- }
- free_page((unsigned long)buf);
- }
- return 1;
-}
/*
* Decide what to dump of a segment, part, all or none.
@@ -1249,11 +1220,6 @@ static int writenote(struct memelfnote *men, struct file *file,
}
#undef DUMP_WRITE
-#define DUMP_WRITE(addr, nr) \
- if ((size += (nr)) > cprm->limit || \
- !dump_write(cprm->file, (addr), (nr))) \
- goto end_coredump;
-
static void fill_elf_header(struct elfhdr *elf, int segs,
u16 machine, u32 flags, u8 osabi)
{
@@ -1872,6 +1838,34 @@ static struct vm_area_struct *next_vma(struct vm_area_struct *this_vma,
return gate_vma;
}
+static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum,
+ elf_addr_t e_shoff, int segs)
+{
+ elf->e_shoff = e_shoff;
+ elf->e_shentsize = sizeof(*shdr4extnum);
+ elf->e_shnum = 1;
+ elf->e_shstrndx = SHN_UNDEF;
+
+ memset(shdr4extnum, 0, sizeof(*shdr4extnum));
+
+ shdr4extnum->sh_type = SHT_NULL;
+ shdr4extnum->sh_size = elf->e_shnum;
+ shdr4extnum->sh_link = elf->e_shstrndx;
+ shdr4extnum->sh_info = segs;
+}
+
+static size_t elf_core_vma_data_size(struct vm_area_struct *gate_vma,
+ unsigned long mm_flags)
+{
+ struct vm_area_struct *vma;
+ size_t size = 0;
+
+ for (vma = first_vma(current, gate_vma); vma != NULL;
+ vma = next_vma(vma, gate_vma))
+ size += vma_dump_size(vma, mm_flags);
+ return size;
+}
+
/*
* Actual dumper
*
@@ -1888,8 +1882,11 @@ static int elf_core_dump(struct coredump_params *cprm)
struct vm_area_struct *vma, *gate_vma;
struct elfhdr *elf = NULL;
loff_t offset = 0, dataoff, foffset;
- unsigned long mm_flags;
struct elf_note_info info;
+ struct elf_phdr *phdr4note = NULL;
+ struct elf_shdr *shdr4extnum = NULL;
+ Elf_Half e_phnum;
+ elf_addr_t e_shoff;
/*
* We no longer stop all VM operations.
@@ -1912,20 +1909,25 @@ static int elf_core_dump(struct coredump_params *cprm)
* Please check DEFAULT_MAX_MAP_COUNT definition when you modify here.
*/
segs = current->mm->map_count;
-#ifdef ELF_CORE_EXTRA_PHDRS
- segs += ELF_CORE_EXTRA_PHDRS;
-#endif
+ segs += elf_core_extra_phdrs();
gate_vma = get_gate_vma(current);
if (gate_vma != NULL)
segs++;
+ /* for notes section */
+ segs++;
+
+ /* If segs > PN_XNUM(0xffff), then e_phnum overflows. To avoid
+ * this, kernel supports extended numbering. Have a look at
+ * include/linux/elf.h for further information. */
+ e_phnum = segs > PN_XNUM ? PN_XNUM : segs;
+
/*
* Collect all the non-memory information about the process for the
* notes. This also sets up the file header.
*/
- if (!fill_note_info(elf, segs + 1, /* including notes section */
- &info, cprm->signr, cprm->regs))
+ if (!fill_note_info(elf, e_phnum, &info, cprm->signr, cprm->regs))
goto cleanup;
has_dumped = 1;
@@ -1934,31 +1936,47 @@ static int elf_core_dump(struct coredump_params *cprm)
fs = get_fs();
set_fs(KERNEL_DS);
- DUMP_WRITE(elf, sizeof(*elf));
offset += sizeof(*elf); /* Elf header */
- offset += (segs + 1) * sizeof(struct elf_phdr); /* Program headers */
+ offset += segs * sizeof(struct elf_phdr); /* Program headers */
foffset = offset;
/* Write notes phdr entry */
{
- struct elf_phdr phdr;
size_t sz = get_note_info_size(&info);
sz += elf_coredump_extra_notes_size();
- fill_elf_note_phdr(&phdr, sz, offset);
+ phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL);
+ if (!phdr4note)
+ goto end_coredump;
+
+ fill_elf_note_phdr(phdr4note, sz, offset);
offset += sz;
- DUMP_WRITE(&phdr, sizeof(phdr));
}
dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
- /*
- * We must use the same mm->flags while dumping core to avoid
- * inconsistency between the program headers and bodies, otherwise an
- * unusable core file can be generated.
- */
- mm_flags = current->mm->flags;
+ offset += elf_core_vma_data_size(gate_vma, cprm->mm_flags);
+ offset += elf_core_extra_data_size();
+ e_shoff = offset;
+
+ if (e_phnum == PN_XNUM) {
+ shdr4extnum = kmalloc(sizeof(*shdr4extnum), GFP_KERNEL);
+ if (!shdr4extnum)
+ goto end_coredump;
+ fill_extnum_info(elf, shdr4extnum, e_shoff, segs);
+ }
+
+ offset = dataoff;
+
+ size += sizeof(*elf);
+ if (size > cprm->limit || !dump_write(cprm->file, elf, sizeof(*elf)))
+ goto end_coredump;
+
+ size += sizeof(*phdr4note);
+ if (size > cprm->limit
+ || !dump_write(cprm->file, phdr4note, sizeof(*phdr4note)))
+ goto end_coredump;
/* Write program headers for segments dump */
for (vma = first_vma(current, gate_vma); vma != NULL;
@@ -1969,7 +1987,7 @@ static int elf_core_dump(struct coredump_params *cprm)
phdr.p_offset = offset;
phdr.p_vaddr = vma->vm_start;
phdr.p_paddr = 0;
- phdr.p_filesz = vma_dump_size(vma, mm_flags);
+ phdr.p_filesz = vma_dump_size(vma, cprm->mm_flags);
phdr.p_memsz = vma->vm_end - vma->vm_start;
offset += phdr.p_filesz;
phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
@@ -1979,12 +1997,14 @@ static int elf_core_dump(struct coredump_params *cprm)
phdr.p_flags |= PF_X;
phdr.p_align = ELF_EXEC_PAGESIZE;
- DUMP_WRITE(&phdr, sizeof(phdr));
+ size += sizeof(phdr);
+ if (size > cprm->limit
+ || !dump_write(cprm->file, &phdr, sizeof(phdr)))
+ goto end_coredump;
}
-#ifdef ELF_CORE_WRITE_EXTRA_PHDRS
- ELF_CORE_WRITE_EXTRA_PHDRS;
-#endif
+ if (!elf_core_write_extra_phdrs(cprm->file, offset, &size, cprm->limit))
+ goto end_coredump;
/* write out the notes section */
if (!write_note_info(&info, cprm->file, &foffset))
@@ -2002,7 +2022,7 @@ static int elf_core_dump(struct coredump_params *cprm)
unsigned long addr;
unsigned long end;
- end = vma->vm_start + vma_dump_size(vma, mm_flags);
+ end = vma->vm_start + vma_dump_size(vma, cprm->mm_flags);
for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) {
struct page *page;
@@ -2023,15 +2043,24 @@ static int elf_core_dump(struct coredump_params *cprm)
}
}
-#ifdef ELF_CORE_WRITE_EXTRA_DATA
- ELF_CORE_WRITE_EXTRA_DATA;
-#endif
+ if (!elf_core_write_extra_data(cprm->file, &size, cprm->limit))
+ goto end_coredump;
+
+ if (e_phnum == PN_XNUM) {
+ size += sizeof(*shdr4extnum);
+ if (size > cprm->limit
+ || !dump_write(cprm->file, shdr4extnum,
+ sizeof(*shdr4extnum)))
+ goto end_coredump;
+ }
end_coredump:
set_fs(fs);
cleanup:
free_note_info(&info);
+ kfree(shdr4extnum);
+ kfree(phdr4note);
kfree(elf);
out:
return has_dumped;
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 18d77297ccc..6d6a16c5e9b 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -34,6 +34,7 @@
#include <linux/elf.h>
#include <linux/elf-fdpic.h>
#include <linux/elfcore.h>
+#include <linux/coredump.h>
#include <asm/uaccess.h>
#include <asm/param.h>
@@ -1216,26 +1217,6 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
#ifdef CONFIG_ELF_CORE
/*
- * These are the only things you should do on a core-file: use only these
- * functions to write out all the necessary info.
- */
-static int dump_write(struct file *file, const void *addr, int nr)
-{
- return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
-}
-
-static int dump_seek(struct file *file, loff_t off)
-{
- if (file->f_op->llseek) {
- if (file->f_op->llseek(file, off, SEEK_SET) != off)
- return 0;
- } else {
- file->f_pos = off;
- }
- return 1;
-}
-
-/*
* Decide whether a segment is worth dumping; default is yes to be
* sure (missing info is worse than too much; etc).
* Personally I'd include everything, and use the coredump limit...
@@ -1313,35 +1294,35 @@ static int notesize(struct memelfnote *en)
/* #define DEBUG */
-#define DUMP_WRITE(addr, nr) \
- do { if (!dump_write(file, (addr), (nr))) return 0; } while(0)
-#define DUMP_SEEK(off) \
- do { if (!dump_seek(file, (off))) return 0; } while(0)
+#define DUMP_WRITE(addr, nr, foffset) \
+ do { if (!dump_write(file, (addr), (nr))) return 0; *foffset += (nr); } while(0)
-static int writenote(struct memelfnote *men, struct file *file)
+static int alignfile(struct file *file, loff_t *foffset)
{
- struct elf_note en;
+ static const char buf[4] = { 0, };
+ DUMP_WRITE(buf, roundup(*foffset, 4) - *foffset, foffset);
+ return 1;
+}
+static int writenote(struct memelfnote *men, struct file *file,
+ loff_t *foffset)
+{
+ struct elf_note en;
en.n_namesz = strlen(men->name) + 1;
en.n_descsz = men->datasz;
en.n_type = men->type;
- DUMP_WRITE(&en, sizeof(en));
- DUMP_WRITE(men->name, en.n_namesz);
- /* XXX - cast from long long to long to avoid need for libgcc.a */
- DUMP_SEEK(roundup((unsigned long)file->f_pos, 4)); /* XXX */
- DUMP_WRITE(men->data, men->datasz);
- DUMP_SEEK(roundup((unsigned long)file->f_pos, 4)); /* XXX */
+ DUMP_WRITE(&en, sizeof(en), foffset);
+ DUMP_WRITE(men->name, en.n_namesz, foffset);
+ if (!alignfile(file, foffset))
+ return 0;
+ DUMP_WRITE(men->data, men->datasz, foffset);
+ if (!alignfile(file, foffset))
+ return 0;
return 1;
}
#undef DUMP_WRITE
-#undef DUMP_SEEK
-
-#define DUMP_WRITE(addr, nr) \
- if ((size += (nr)) > cprm->limit || \
- !dump_write(cprm->file, (addr), (nr))) \
- goto end_coredump;
static inline void fill_elf_fdpic_header(struct elfhdr *elf, int segs)
{
@@ -1524,6 +1505,22 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
return sz;
}
+static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum,
+ elf_addr_t e_shoff, int segs)
+{
+ elf->e_shoff = e_shoff;
+ elf->e_shentsize = sizeof(*shdr4extnum);
+ elf->e_shnum = 1;
+ elf->e_shstrndx = SHN_UNDEF;
+
+ memset(shdr4extnum, 0, sizeof(*shdr4extnum));
+
+ shdr4extnum->sh_type = SHT_NULL;
+ shdr4extnum->sh_size = elf->e_shnum;
+ shdr4extnum->sh_link = elf->e_shstrndx;
+ shdr4extnum->sh_info = segs;
+}
+
/*
* dump the segments for an MMU process
*/
@@ -1552,7 +1549,7 @@ static int elf_fdpic_dump_segments(struct file *file, size_t *size,
err = -EIO;
kunmap(page);
page_cache_release(page);
- } else if (!dump_seek(file, file->f_pos + PAGE_SIZE))
+ } else if (!dump_seek(file, PAGE_SIZE))
err = -EFBIG;
if (err)
goto out;
@@ -1588,6 +1585,17 @@ static int elf_fdpic_dump_segments(struct file *file, size_t *size,
}
#endif
+static size_t elf_core_vma_data_size(unsigned long mm_flags)
+{
+ struct vm_area_struct *vma;
+ size_t size = 0;
+
+ for (vma = current->mm->mmap; vma; vma->vm_next)
+ if (maydump(vma, mm_flags))
+ size += vma->vm_end - vma->vm_start;
+ return size;
+}
+
/*
* Actual dumper
*
@@ -1605,7 +1613,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
int i;
struct vm_area_struct *vma;
struct elfhdr *elf = NULL;
- loff_t offset = 0, dataoff;
+ loff_t offset = 0, dataoff, foffset;
int numnote;
struct memelfnote *notes = NULL;
struct elf_prstatus *prstatus = NULL; /* NT_PRSTATUS */
@@ -1618,7 +1626,10 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
#endif
int thread_status_size = 0;
elf_addr_t *auxv;
- unsigned long mm_flags;
+ struct elf_phdr *phdr4note = NULL;
+ struct elf_shdr *shdr4extnum = NULL;
+ Elf_Half e_phnum;
+ elf_addr_t e_shoff;
/*
* We no longer stop all VM operations.
@@ -1683,12 +1694,18 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
elf_core_copy_regs(&prstatus->pr_reg, cprm->regs);
segs = current->mm->map_count;
-#ifdef ELF_CORE_EXTRA_PHDRS
- segs += ELF_CORE_EXTRA_PHDRS;
-#endif
+ segs += elf_core_extra_phdrs();
+
+ /* for notes section */
+ segs++;
+
+ /* If segs > PN_XNUM(0xffff), then e_phnum overflows. To avoid
+ * this, kernel supports extended numbering. Have a look at
+ * include/linux/elf.h for further information. */
+ e_phnum = segs > PN_XNUM ? PN_XNUM : segs;
/* Set up header */
- fill_elf_fdpic_header(elf, segs + 1); /* including notes section */
+ fill_elf_fdpic_header(elf, e_phnum);
has_dumped = 1;
current->flags |= PF_DUMPCORE;
@@ -1727,13 +1744,12 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
fs = get_fs();
set_fs(KERNEL_DS);
- DUMP_WRITE(elf, sizeof(*elf));
offset += sizeof(*elf); /* Elf header */
- offset += (segs+1) * sizeof(struct elf_phdr); /* Program headers */
+ offset += segs * sizeof(struct elf_phdr); /* Program headers */
+ foffset = offset;
/* Write notes phdr entry */
{
- struct elf_phdr phdr;
int sz = 0;
for (i = 0; i < numnote; i++)
@@ -1741,20 +1757,38 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
sz += thread_status_size;
- fill_elf_note_phdr(&phdr, sz, offset);
+ phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL);
+ if (!phdr4note)
+ goto end_coredump;
+
+ fill_elf_note_phdr(phdr4note, sz, offset);
offset += sz;
- DUMP_WRITE(&phdr, sizeof(phdr));
}
/* Page-align dumped data */
dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
- /*
- * We must use the same mm->flags while dumping core to avoid
- * inconsistency between the program headers and bodies, otherwise an
- * unusable core file can be generated.
- */
- mm_flags = current->mm->flags;
+ offset += elf_core_vma_data_size(cprm->mm_flags);
+ offset += elf_core_extra_data_size();
+ e_shoff = offset;
+
+ if (e_phnum == PN_XNUM) {
+ shdr4extnum = kmalloc(sizeof(*shdr4extnum), GFP_KERNEL);
+ if (!shdr4extnum)
+ goto end_coredump;
+ fill_extnum_info(elf, shdr4extnum, e_shoff, segs);
+ }
+
+ offset = dataoff;
+
+ size += sizeof(*elf);
+ if (size > cprm->limit || !dump_write(cprm->file, elf, sizeof(*elf)))
+ goto end_coredump;
+
+ size += sizeof(*phdr4note);
+ if (size > cprm->limit
+ || !dump_write(cprm->file, phdr4note, sizeof(*phdr4note)))
+ goto end_coredump;
/* write program headers for segments dump */
for (vma = current->mm->mmap; vma; vma = vma->vm_next) {
@@ -1767,7 +1801,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
phdr.p_offset = offset;
phdr.p_vaddr = vma->vm_start;
phdr.p_paddr = 0;
- phdr.p_filesz = maydump(vma, mm_flags) ? sz : 0;
+ phdr.p_filesz = maydump(vma, cprm->mm_flags) ? sz : 0;
phdr.p_memsz = sz;
offset += phdr.p_filesz;
phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
@@ -1777,16 +1811,18 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
phdr.p_flags |= PF_X;
phdr.p_align = ELF_EXEC_PAGESIZE;
- DUMP_WRITE(&phdr, sizeof(phdr));
+ size += sizeof(phdr);
+ if (size > cprm->limit
+ || !dump_write(cprm->file, &phdr, sizeof(phdr)))
+ goto end_coredump;
}
-#ifdef ELF_CORE_WRITE_EXTRA_PHDRS
- ELF_CORE_WRITE_EXTRA_PHDRS;
-#endif
+ if (!elf_core_write_extra_phdrs(cprm->file, offset, &size, cprm->limit))
+ goto end_coredump;
/* write out the notes section */
for (i = 0; i < numnote; i++)
- if (!writenote(notes + i, cprm->file))
+ if (!writenote(notes + i, cprm->file, &foffset))
goto end_coredump;
/* write out the thread status notes section */
@@ -1795,20 +1831,27 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
list_entry(t, struct elf_thread_status, list);
for (i = 0; i < tmp->num_notes; i++)
- if (!writenote(&tmp->notes[i], cprm->file))
+ if (!writenote(&tmp->notes[i], cprm->file, &foffset))
goto end_coredump;
}
- if (!dump_seek(cprm->file, dataoff))
+ if (!dump_seek(cprm->file, dataoff - foffset))
goto end_coredump;
if (elf_fdpic_dump_segments(cprm->file, &size, &cprm->limit,
- mm_flags) < 0)
+ cprm->mm_flags) < 0)
goto end_coredump;
-#ifdef ELF_CORE_WRITE_EXTRA_DATA
- ELF_CORE_WRITE_EXTRA_DATA;
-#endif
+ if (!elf_core_write_extra_data(cprm->file, &size, cprm->limit))
+ goto end_coredump;
+
+ if (e_phnum == PN_XNUM) {
+ size += sizeof(*shdr4extnum);
+ if (size > cprm->limit
+ || !dump_write(cprm->file, shdr4extnum,
+ sizeof(*shdr4extnum)))
+ goto end_coredump;
+ }
if (cprm->file->f_pos != offset) {
/* Sanity check */
@@ -1826,7 +1869,7 @@ cleanup:
list_del(tmp);
kfree(list_entry(tmp, struct elf_thread_status, list));
}
-
+ kfree(phdr4note);
kfree(elf);
kfree(prstatus);
kfree(psinfo);
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 42c6b4a5444..e0e769bdca5 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -501,7 +501,7 @@ static int load_flat_file(struct linux_binprm * bprm,
* size limits imposed on them by creating programs with large
* arrays in the data or bss.
*/
- rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
+ rlim = rlimit(RLIMIT_DATA);
if (rlim >= RLIM_INFINITY)
rlim = ~0;
if (data_len + bss_len > rlim) {
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 2b59201b955..0427183e3e0 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -901,7 +901,7 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
root->highest_objectid = 0;
root->name = NULL;
root->in_sysfs = 0;
- root->inode_tree.rb_node = NULL;
+ root->inode_tree = RB_ROOT;
INIT_LIST_HEAD(&root->dirty_list);
INIT_LIST_HEAD(&root->orphan_list);
@@ -1673,7 +1673,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
insert_inode_hash(fs_info->btree_inode);
spin_lock_init(&fs_info->block_group_cache_lock);
- fs_info->block_group_cache_tree.rb_node = NULL;
+ fs_info->block_group_cache_tree = RB_ROOT;
extent_io_tree_init(&fs_info->freed_extents[0],
fs_info->btree_inode->i_mapping, GFP_NOFS);
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index b177ed31961..7073cbb1b2d 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -104,8 +104,8 @@ void extent_io_exit(void)
void extent_io_tree_init(struct extent_io_tree *tree,
struct address_space *mapping, gfp_t mask)
{
- tree->state.rb_node = NULL;
- tree->buffer.rb_node = NULL;
+ tree->state = RB_ROOT;
+ tree->buffer = RB_ROOT;
tree->ops = NULL;
tree->dirty_bytes = 0;
spin_lock_init(&tree->lock);
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index 428fcac45f9..28d87ba60ce 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -35,7 +35,7 @@ void extent_map_exit(void)
*/
void extent_map_tree_init(struct extent_map_tree *tree, gfp_t mask)
{
- tree->map.rb_node = NULL;
+ tree->map = RB_ROOT;
rwlock_init(&tree->lock);
}
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index cb2849f0325..dd831ed31ee 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -870,7 +870,7 @@ __btrfs_return_cluster_to_free_space(
tree_insert_offset(&block_group->free_space_offset,
entry->offset, &entry->offset_index, 0);
}
- cluster->root.rb_node = NULL;
+ cluster->root = RB_ROOT;
out:
spin_unlock(&cluster->lock);
@@ -1355,7 +1355,7 @@ void btrfs_init_free_cluster(struct btrfs_free_cluster *cluster)
{
spin_lock_init(&cluster->lock);
spin_lock_init(&cluster->refill_lock);
- cluster->root.rb_node = NULL;
+ cluster->root = RB_ROOT;
cluster->max_size = 0;
cluster->points_to_bitmap = false;
INIT_LIST_HEAD(&cluster->block_group_list);
diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h
index 1fe1282ef47..9116c6d0c5a 100644
--- a/fs/btrfs/ordered-data.h
+++ b/fs/btrfs/ordered-data.h
@@ -129,7 +129,7 @@ static inline void
btrfs_ordered_inode_tree_init(struct btrfs_ordered_inode_tree *t)
{
mutex_init(&t->mutex);
- t->tree.rb_node = NULL;
+ t->tree = RB_ROOT;
t->last = NULL;
}
diff --git a/fs/btrfs/ref-cache.h b/fs/btrfs/ref-cache.h
index bc283ad2db7..e2a55cb2072 100644
--- a/fs/btrfs/ref-cache.h
+++ b/fs/btrfs/ref-cache.h
@@ -52,7 +52,7 @@ static inline size_t btrfs_leaf_ref_size(int nr_extents)
static inline void btrfs_leaf_ref_tree_init(struct btrfs_leaf_ref_tree *tree)
{
- tree->root.rb_node = NULL;
+ tree->root = RB_ROOT;
INIT_LIST_HEAD(&tree->list);
spin_lock_init(&tree->lock);
}
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index ab7ab531874..0109e5606ba 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -170,14 +170,14 @@ struct async_merge {
static void mapping_tree_init(struct mapping_tree *tree)
{
- tree->rb_root.rb_node = NULL;
+ tree->rb_root = RB_ROOT;
spin_lock_init(&tree->lock);
}
static void backref_cache_init(struct backref_cache *cache)
{
int i;
- cache->rb_root.rb_node = NULL;
+ cache->rb_root = RB_ROOT;
for (i = 0; i < BTRFS_MAX_LEVEL; i++)
INIT_LIST_HEAD(&cache->pending[i]);
spin_lock_init(&cache->lock);
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 8a1ea6e6457..f8b4521de90 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -128,7 +128,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
{
struct btrfs_fs_info *info = root->fs_info;
substring_t args[MAX_OPT_ARGS];
- char *p, *num;
+ char *p, *num, *orig;
int intarg;
int ret = 0;
@@ -143,6 +143,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
if (!options)
return -ENOMEM;
+ orig = options;
while ((p = strsep(&options, ",")) != NULL) {
int token;
@@ -280,7 +281,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
}
}
out:
- kfree(options);
+ kfree(orig);
return ret;
}
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index a240b6fa81d..4ce16ef702a 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -164,12 +164,12 @@ static void btrfs_root_release(struct kobject *kobj)
complete(&root->kobj_unregister);
}
-static struct sysfs_ops btrfs_super_attr_ops = {
+static const struct sysfs_ops btrfs_super_attr_ops = {
.show = btrfs_super_attr_show,
.store = btrfs_super_attr_store,
};
-static struct sysfs_ops btrfs_root_attr_ops = {
+static const struct sysfs_ops btrfs_root_attr_ops = {
.show = btrfs_root_attr_show,
.store = btrfs_root_attr_store,
};
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index b2acc79f1b3..2a36e236a49 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -69,7 +69,7 @@ static noinline int join_transaction(struct btrfs_root *root)
cur_trans->commit_done = 0;
cur_trans->start_time = get_seconds();
- cur_trans->delayed_refs.root.rb_node = NULL;
+ cur_trans->delayed_refs.root = RB_ROOT;
cur_trans->delayed_refs.num_entries = 0;
cur_trans->delayed_refs.num_heads_ready = 0;
cur_trans->delayed_refs.num_heads = 0;
diff --git a/fs/compat_binfmt_elf.c b/fs/compat_binfmt_elf.c
index 0adced2f296..112e45a17e9 100644
--- a/fs/compat_binfmt_elf.c
+++ b/fs/compat_binfmt_elf.c
@@ -28,10 +28,12 @@
#undef elfhdr
#undef elf_phdr
+#undef elf_shdr
#undef elf_note
#undef elf_addr_t
#define elfhdr elf32_hdr
#define elf_phdr elf32_phdr
+#define elf_shdr elf32_shdr
#define elf_note elf32_note
#define elf_addr_t Elf32_Addr
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 0ca9ec4a79c..6d55b61bfa7 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -545,7 +545,7 @@ static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, void __user *argp)
kcmd = MTIOCPOS;
karg = &pos;
break;
- case MTIOCGET32:
+ default: /* MTIOCGET32 */
kcmd = MTIOCGET;
karg = &get;
break;
@@ -663,7 +663,7 @@ static int raw_ioctl(unsigned fd, unsigned cmd,
switch (cmd) {
case RAW_SETBIND:
- case RAW_GETBIND: {
+ default: { /* RAW_GETBIND */
struct raw_config_request req;
mm_segment_t oldfs = get_fs();
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index 26a8bd40400..f994a7dfda8 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -148,7 +148,7 @@ static void lockspace_kobj_release(struct kobject *k)
kfree(ls);
}
-static struct sysfs_ops dlm_attr_ops = {
+static const struct sysfs_ops dlm_attr_ops = {
.show = dlm_attr_show,
.store = dlm_attr_store,
};
diff --git a/fs/exec.c b/fs/exec.c
index cce6bbdbdbb..49cdaa19e5b 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -195,7 +195,7 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
* to work from.
*/
rlim = current->signal->rlim;
- if (size > rlim[RLIMIT_STACK].rlim_cur / 4) {
+ if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) {
put_page(page);
return NULL;
}
@@ -246,6 +246,7 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
vma->vm_start = vma->vm_end - PAGE_SIZE;
vma->vm_flags = VM_STACK_FLAGS;
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+ INIT_LIST_HEAD(&vma->anon_vma_chain);
err = insert_vm_struct(mm, vma);
if (err)
goto err;
@@ -516,7 +517,8 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
/*
* cover the whole range: [new_start, old_end)
*/
- vma_adjust(vma, new_start, old_end, vma->vm_pgoff, NULL);
+ if (vma_adjust(vma, new_start, old_end, vma->vm_pgoff, NULL))
+ return -ENOMEM;
/*
* move the page tables downwards, on failure we rely on
@@ -547,15 +549,13 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift)
tlb_finish_mmu(tlb, new_end, old_end);
/*
- * shrink the vma to just the new range.
+ * Shrink the vma to just the new range. Always succeeds.
*/
vma_adjust(vma, new_start, new_end, vma->vm_pgoff, NULL);
return 0;
}
-#define EXTRA_STACK_VM_PAGES 20 /* random */
-
/*
* Finalizes the stack vm_area_struct. The flags and permissions are updated,
* the stack is optionally relocated, and some extra space is added.
@@ -577,7 +577,7 @@ int setup_arg_pages(struct linux_binprm *bprm,
#ifdef CONFIG_STACK_GROWSUP
/* Limit stack size to 1GB */
- stack_base = current->signal->rlim[RLIMIT_STACK].rlim_max;
+ stack_base = rlimit_max(RLIMIT_STACK);
if (stack_base > (1 << 30))
stack_base = 1 << 30;
@@ -630,7 +630,7 @@ int setup_arg_pages(struct linux_binprm *bprm,
goto out_unlock;
}
- stack_expand = EXTRA_STACK_VM_PAGES * PAGE_SIZE;
+ stack_expand = 131072UL; /* randomly 32*4k (or 2*64k) pages */
stack_size = vma->vm_end - vma->vm_start;
/*
* Align this down to a page boundary as expand_stack
@@ -718,6 +718,7 @@ static int exec_mmap(struct mm_struct *mm)
/* Notify parent that we're no longer interested in the old VM */
tsk = current;
old_mm = current->mm;
+ sync_mm_rss(tsk, old_mm);
mm_release(tsk, old_mm);
if (old_mm) {
@@ -1532,7 +1533,7 @@ static int format_corename(char *corename, long signr)
/* core limit size */
case 'c':
rc = snprintf(out_ptr, out_end - out_ptr,
- "%lu", current->signal->rlim[RLIMIT_CORE].rlim_cur);
+ "%lu", rlimit(RLIMIT_CORE));
if (rc > out_end - out_ptr)
goto out;
out_ptr += rc;
@@ -1560,12 +1561,13 @@ out:
return ispipe;
}
-static int zap_process(struct task_struct *start)
+static int zap_process(struct task_struct *start, int exit_code)
{
struct task_struct *t;
int nr = 0;
start->signal->flags = SIGNAL_GROUP_EXIT;
+ start->signal->group_exit_code = exit_code;
start->signal->group_stop_count = 0;
t = start;
@@ -1590,8 +1592,7 @@ static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm,
spin_lock_irq(&tsk->sighand->siglock);
if (!signal_group_exit(tsk->signal)) {
mm->core_state = core_state;
- tsk->signal->group_exit_code = exit_code;
- nr = zap_process(tsk);
+ nr = zap_process(tsk, exit_code);
}
spin_unlock_irq(&tsk->sighand->siglock);
if (unlikely(nr < 0))
@@ -1640,7 +1641,7 @@ static inline int zap_threads(struct task_struct *tsk, struct mm_struct *mm,
if (p->mm) {
if (unlikely(p->mm == mm)) {
lock_task_sighand(p, &flags);
- nr += zap_process(p);
+ nr += zap_process(p, exit_code);
unlock_task_sighand(p, &flags);
}
break;
@@ -1747,14 +1748,19 @@ void set_dumpable(struct mm_struct *mm, int value)
}
}
-int get_dumpable(struct mm_struct *mm)
+static int __get_dumpable(unsigned long mm_flags)
{
int ret;
- ret = mm->flags & 0x3;
+ ret = mm_flags & MMF_DUMPABLE_MASK;
return (ret >= 2) ? 2 : ret;
}
+int get_dumpable(struct mm_struct *mm)
+{
+ return __get_dumpable(mm->flags);
+}
+
static void wait_for_dump_helpers(struct file *file)
{
struct pipe_inode_info *pipe;
@@ -1797,7 +1803,13 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
struct coredump_params cprm = {
.signr = signr,
.regs = regs,
- .limit = current->signal->rlim[RLIMIT_CORE].rlim_cur,
+ .limit = rlimit(RLIMIT_CORE),
+ /*
+ * We must use the same mm->flags while dumping core to avoid
+ * inconsistency of bit flags, since this flag is not protected
+ * by any locks.
+ */
+ .mm_flags = mm->flags,
};
audit_core_dumps(signr);
@@ -1816,7 +1828,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
/*
* If another thread got here first, or we are not dumpable, bail out.
*/
- if (mm->core_state || !get_dumpable(mm)) {
+ if (mm->core_state || !__get_dumpable(cprm.mm_flags)) {
up_write(&mm->mmap_sem);
put_cred(cred);
goto fail;
@@ -1827,7 +1839,8 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
* process nor do we know its entire history. We only know it
* was tainted so we dump it as root in mode 2.
*/
- if (get_dumpable(mm) == 2) { /* Setuid core dump mode */
+ if (__get_dumpable(cprm.mm_flags) == 2) {
+ /* Setuid core dump mode */
flag = O_EXCL; /* Stop rewrite attacks */
cred->fsuid = 0; /* Dump root private */
}
@@ -1923,8 +1936,9 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
/*
* Dont allow local users get cute and trick others to coredump
* into their pre-created files:
+ * Note, this is not relevant for pipes
*/
- if (inode->i_uid != current_fsuid())
+ if (!ispipe && (inode->i_uid != current_fsuid()))
goto close_fail;
if (!cprm.file->f_op)
goto close_fail;
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 2b83b96cb2e..ce84a6ed4a4 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -2358,7 +2358,7 @@ static void ext4_sb_release(struct kobject *kobj)
}
-static struct sysfs_ops ext4_attr_ops = {
+static const struct sysfs_ops ext4_attr_ops = {
.show = ext4_attr_show,
.store = ext4_attr_store,
};
diff --git a/fs/fcntl.c b/fs/fcntl.c
index 97e01dc0d95..452d02f9075 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -344,7 +344,7 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg,
switch (cmd) {
case F_DUPFD:
case F_DUPFD_CLOEXEC:
- if (arg >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
+ if (arg >= rlimit(RLIMIT_NOFILE))
break;
err = alloc_fd(arg, cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0);
if (err >= 0) {
diff --git a/fs/file.c b/fs/file.c
index 38039af6766..34bb7f71d99 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -257,7 +257,7 @@ int expand_files(struct files_struct *files, int nr)
* N.B. For clone tasks sharing a files structure, this test
* will limit the total number of files that can be opened.
*/
- if (nr >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
+ if (nr >= rlimit(RLIMIT_NOFILE))
return -EMFILE;
/* Do we need to expand? */
diff --git a/fs/file_table.c b/fs/file_table.c
index b98404b5438..32d12b78bac 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -393,7 +393,9 @@ retry:
continue;
if (!(f->f_mode & FMODE_WRITE))
continue;
+ spin_lock(&f->f_lock);
f->f_mode &= ~FMODE_WRITE;
+ spin_unlock(&f->f_lock);
if (file_check_writeable(f) != 0)
continue;
file_release_write(f);
diff --git a/fs/fscache/Kconfig b/fs/fscache/Kconfig
index 864dac20a24..cc94bb9563f 100644
--- a/fs/fscache/Kconfig
+++ b/fs/fscache/Kconfig
@@ -1,7 +1,6 @@
config FSCACHE
tristate "General filesystem local caching manager"
- depends on EXPERIMENTAL
select SLOW_WORK
help
This option enables a generic filesystem caching manager that can be
diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c
index b5f1a46133c..419042f7f0b 100644
--- a/fs/gfs2/sys.c
+++ b/fs/gfs2/sys.c
@@ -49,7 +49,7 @@ static ssize_t gfs2_attr_store(struct kobject *kobj, struct attribute *attr,
return a->store ? a->store(sdp, buf, len) : len;
}
-static struct sysfs_ops gfs2_attr_ops = {
+static const struct sysfs_ops gfs2_attr_ops = {
.show = gfs2_attr_show,
.store = gfs2_attr_store,
};
@@ -574,7 +574,7 @@ static int gfs2_uevent(struct kset *kset, struct kobject *kobj,
return 0;
}
-static struct kset_uevent_ops gfs2_uevent_ops = {
+static const struct kset_uevent_ops gfs2_uevent_ops = {
.uevent = gfs2_uevent,
};
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 4600c2037b8..bb464d12104 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -479,8 +479,8 @@ again: mutex_lock(&nlm_host_mutex);
}
}
}
-
mutex_unlock(&nlm_host_mutex);
+ nsm_release(nsm);
}
/*
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index f956651d0f6..fefa4df3f00 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -349,9 +349,9 @@ retry:
* nsm_reboot_lookup - match NLMPROC_SM_NOTIFY arguments to an nsm_handle
* @info: pointer to NLMPROC_SM_NOTIFY arguments
*
- * Returns a matching nsm_handle if found in the nsm cache; the returned
- * nsm_handle's reference count is bumped and sm_monitored is cleared.
- * Otherwise returns NULL if some error occurred.
+ * Returns a matching nsm_handle if found in the nsm cache. The returned
+ * nsm_handle's reference count is bumped. Otherwise returns NULL if some
+ * error occurred.
*/
struct nsm_handle *nsm_reboot_lookup(const struct nlm_reboot *info)
{
@@ -370,12 +370,6 @@ struct nsm_handle *nsm_reboot_lookup(const struct nlm_reboot *info)
atomic_inc(&cached->sm_count);
spin_unlock(&nsm_lock);
- /*
- * During subsequent lock activity, force a fresh
- * notification to be set up for this host.
- */
- cached->sm_monitored = 0;
-
dprintk("lockd: host %s (%s) rebooted, cnt %d\n",
cached->sm_name, cached->sm_addrbuf,
atomic_read(&cached->sm_count));
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index e50cfa3d965..7d150517ddf 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -243,11 +243,9 @@ static int make_socks(struct svc_serv *serv)
if (err < 0)
goto out_err;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
err = create_lockd_family(serv, PF_INET6);
if (err < 0 && err != -EAFNOSUPPORT)
goto out_err;
-#endif /* CONFIG_IPV6 || CONFIG_IPV6_MODULE */
warned = 0;
return 0;
diff --git a/fs/logfs/Kconfig b/fs/logfs/Kconfig
new file mode 100644
index 00000000000..daf9a9b32dd
--- /dev/null
+++ b/fs/logfs/Kconfig
@@ -0,0 +1,17 @@
+config LOGFS
+ tristate "LogFS file system (EXPERIMENTAL)"
+ depends on (MTD || BLOCK) && EXPERIMENTAL
+ select ZLIB_INFLATE
+ select ZLIB_DEFLATE
+ select CRC32
+ select BTREE
+ help
+ Flash filesystem aimed to scale efficiently to large devices.
+ In comparison to JFFS2 it offers significantly faster mount
+ times and potentially less RAM usage, although the latter has
+ not been measured yet.
+
+ In its current state it is still very experimental and should
+ not be used for other than testing purposes.
+
+ If unsure, say N.
diff --git a/fs/logfs/Makefile b/fs/logfs/Makefile
new file mode 100644
index 00000000000..4820027787e
--- /dev/null
+++ b/fs/logfs/Makefile
@@ -0,0 +1,13 @@
+obj-$(CONFIG_LOGFS) += logfs.o
+
+logfs-y += compr.o
+logfs-y += dir.o
+logfs-y += file.o
+logfs-y += gc.o
+logfs-y += inode.o
+logfs-y += journal.o
+logfs-y += readwrite.o
+logfs-y += segment.o
+logfs-y += super.o
+logfs-$(CONFIG_BLOCK) += dev_bdev.o
+logfs-$(CONFIG_MTD) += dev_mtd.o
diff --git a/fs/logfs/compr.c b/fs/logfs/compr.c
new file mode 100644
index 00000000000..44bbfd249ab
--- /dev/null
+++ b/fs/logfs/compr.c
@@ -0,0 +1,95 @@
+/*
+ * fs/logfs/compr.c - compression routines
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ */
+#include "logfs.h"
+#include <linux/vmalloc.h>
+#include <linux/zlib.h>
+
+#define COMPR_LEVEL 3
+
+static DEFINE_MUTEX(compr_mutex);
+static struct z_stream_s stream;
+
+int logfs_compress(void *in, void *out, size_t inlen, size_t outlen)
+{
+ int err, ret;
+
+ ret = -EIO;
+ mutex_lock(&compr_mutex);
+ err = zlib_deflateInit(&stream, COMPR_LEVEL);
+ if (err != Z_OK)
+ goto error;
+
+ stream.next_in = in;
+ stream.avail_in = inlen;
+ stream.total_in = 0;
+ stream.next_out = out;
+ stream.avail_out = outlen;
+ stream.total_out = 0;
+
+ err = zlib_deflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END)
+ goto error;
+
+ err = zlib_deflateEnd(&stream);
+ if (err != Z_OK)
+ goto error;
+
+ if (stream.total_out >= stream.total_in)
+ goto error;
+
+ ret = stream.total_out;
+error:
+ mutex_unlock(&compr_mutex);
+ return ret;
+}
+
+int logfs_uncompress(void *in, void *out, size_t inlen, size_t outlen)
+{
+ int err, ret;
+
+ ret = -EIO;
+ mutex_lock(&compr_mutex);
+ err = zlib_inflateInit(&stream);
+ if (err != Z_OK)
+ goto error;
+
+ stream.next_in = in;
+ stream.avail_in = inlen;
+ stream.total_in = 0;
+ stream.next_out = out;
+ stream.avail_out = outlen;
+ stream.total_out = 0;
+
+ err = zlib_inflate(&stream, Z_FINISH);
+ if (err != Z_STREAM_END)
+ goto error;
+
+ err = zlib_inflateEnd(&stream);
+ if (err != Z_OK)
+ goto error;
+
+ ret = 0;
+error:
+ mutex_unlock(&compr_mutex);
+ return ret;
+}
+
+int __init logfs_compr_init(void)
+{
+ size_t size = max(zlib_deflate_workspacesize(),
+ zlib_inflate_workspacesize());
+ stream.workspace = vmalloc(size);
+ if (!stream.workspace)
+ return -ENOMEM;
+ return 0;
+}
+
+void logfs_compr_exit(void)
+{
+ vfree(stream.workspace);
+}
diff --git a/fs/logfs/dev_bdev.c b/fs/logfs/dev_bdev.c
new file mode 100644
index 00000000000..9718c22f186
--- /dev/null
+++ b/fs/logfs/dev_bdev.c
@@ -0,0 +1,327 @@
+/*
+ * fs/logfs/dev_bdev.c - Device access methods for block devices
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ */
+#include "logfs.h"
+#include <linux/bio.h>
+#include <linux/blkdev.h>
+#include <linux/buffer_head.h>
+
+#define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1))
+
+static void request_complete(struct bio *bio, int err)
+{
+ complete((struct completion *)bio->bi_private);
+}
+
+static int sync_request(struct page *page, struct block_device *bdev, int rw)
+{
+ struct bio bio;
+ struct bio_vec bio_vec;
+ struct completion complete;
+
+ bio_init(&bio);
+ bio.bi_io_vec = &bio_vec;
+ bio_vec.bv_page = page;
+ bio_vec.bv_len = PAGE_SIZE;
+ bio_vec.bv_offset = 0;
+ bio.bi_vcnt = 1;
+ bio.bi_idx = 0;
+ bio.bi_size = PAGE_SIZE;
+ bio.bi_bdev = bdev;
+ bio.bi_sector = page->index * (PAGE_SIZE >> 9);
+ init_completion(&complete);
+ bio.bi_private = &complete;
+ bio.bi_end_io = request_complete;
+
+ submit_bio(rw, &bio);
+ generic_unplug_device(bdev_get_queue(bdev));
+ wait_for_completion(&complete);
+ return test_bit(BIO_UPTODATE, &bio.bi_flags) ? 0 : -EIO;
+}
+
+static int bdev_readpage(void *_sb, struct page *page)
+{
+ struct super_block *sb = _sb;
+ struct block_device *bdev = logfs_super(sb)->s_bdev;
+ int err;
+
+ err = sync_request(page, bdev, READ);
+ if (err) {
+ ClearPageUptodate(page);
+ SetPageError(page);
+ } else {
+ SetPageUptodate(page);
+ ClearPageError(page);
+ }
+ unlock_page(page);
+ return err;
+}
+
+static DECLARE_WAIT_QUEUE_HEAD(wq);
+
+static void writeseg_end_io(struct bio *bio, int err)
+{
+ const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+ struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
+ struct super_block *sb = bio->bi_private;
+ struct logfs_super *super = logfs_super(sb);
+ struct page *page;
+
+ BUG_ON(!uptodate); /* FIXME: Retry io or write elsewhere */
+ BUG_ON(err);
+ BUG_ON(bio->bi_vcnt == 0);
+ do {
+ page = bvec->bv_page;
+ if (--bvec >= bio->bi_io_vec)
+ prefetchw(&bvec->bv_page->flags);
+
+ end_page_writeback(page);
+ } while (bvec >= bio->bi_io_vec);
+ bio_put(bio);
+ if (atomic_dec_and_test(&super->s_pending_writes))
+ wake_up(&wq);
+}
+
+static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index,
+ size_t nr_pages)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct address_space *mapping = super->s_mapping_inode->i_mapping;
+ struct bio *bio;
+ struct page *page;
+ struct request_queue *q = bdev_get_queue(sb->s_bdev);
+ unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9);
+ int i;
+
+ bio = bio_alloc(GFP_NOFS, max_pages);
+ BUG_ON(!bio); /* FIXME: handle this */
+
+ for (i = 0; i < nr_pages; i++) {
+ if (i >= max_pages) {
+ /* Block layer cannot split bios :( */
+ bio->bi_vcnt = i;
+ bio->bi_idx = 0;
+ bio->bi_size = i * PAGE_SIZE;
+ bio->bi_bdev = super->s_bdev;
+ bio->bi_sector = ofs >> 9;
+ bio->bi_private = sb;
+ bio->bi_end_io = writeseg_end_io;
+ atomic_inc(&super->s_pending_writes);
+ submit_bio(WRITE, bio);
+
+ ofs += i * PAGE_SIZE;
+ index += i;
+ nr_pages -= i;
+ i = 0;
+
+ bio = bio_alloc(GFP_NOFS, max_pages);
+ BUG_ON(!bio);
+ }
+ page = find_lock_page(mapping, index + i);
+ BUG_ON(!page);
+ bio->bi_io_vec[i].bv_page = page;
+ bio->bi_io_vec[i].bv_len = PAGE_SIZE;
+ bio->bi_io_vec[i].bv_offset = 0;
+
+ BUG_ON(PageWriteback(page));
+ set_page_writeback(page);
+ unlock_page(page);
+ }
+ bio->bi_vcnt = nr_pages;
+ bio->bi_idx = 0;
+ bio->bi_size = nr_pages * PAGE_SIZE;
+ bio->bi_bdev = super->s_bdev;
+ bio->bi_sector = ofs >> 9;
+ bio->bi_private = sb;
+ bio->bi_end_io = writeseg_end_io;
+ atomic_inc(&super->s_pending_writes);
+ submit_bio(WRITE, bio);
+ return 0;
+}
+
+static void bdev_writeseg(struct super_block *sb, u64 ofs, size_t len)
+{
+ struct logfs_super *super = logfs_super(sb);
+ int head;
+
+ BUG_ON(super->s_flags & LOGFS_SB_FLAG_RO);
+
+ if (len == 0) {
+ /* This can happen when the object fit perfectly into a
+ * segment, the segment gets written per sync and subsequently
+ * closed.
+ */
+ return;
+ }
+ head = ofs & (PAGE_SIZE - 1);
+ if (head) {
+ ofs -= head;
+ len += head;
+ }
+ len = PAGE_ALIGN(len);
+ __bdev_writeseg(sb, ofs, ofs >> PAGE_SHIFT, len >> PAGE_SHIFT);
+ generic_unplug_device(bdev_get_queue(logfs_super(sb)->s_bdev));
+}
+
+
+static void erase_end_io(struct bio *bio, int err)
+{
+ const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
+ struct super_block *sb = bio->bi_private;
+ struct logfs_super *super = logfs_super(sb);
+
+ BUG_ON(!uptodate); /* FIXME: Retry io or write elsewhere */
+ BUG_ON(err);
+ BUG_ON(bio->bi_vcnt == 0);
+ bio_put(bio);
+ if (atomic_dec_and_test(&super->s_pending_writes))
+ wake_up(&wq);
+}
+
+static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index,
+ size_t nr_pages)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct bio *bio;
+ struct request_queue *q = bdev_get_queue(sb->s_bdev);
+ unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9);
+ int i;
+
+ bio = bio_alloc(GFP_NOFS, max_pages);
+ BUG_ON(!bio); /* FIXME: handle this */
+
+ for (i = 0; i < nr_pages; i++) {
+ if (i >= max_pages) {
+ /* Block layer cannot split bios :( */
+ bio->bi_vcnt = i;
+ bio->bi_idx = 0;
+ bio->bi_size = i * PAGE_SIZE;
+ bio->bi_bdev = super->s_bdev;
+ bio->bi_sector = ofs >> 9;
+ bio->bi_private = sb;
+ bio->bi_end_io = erase_end_io;
+ atomic_inc(&super->s_pending_writes);
+ submit_bio(WRITE, bio);
+
+ ofs += i * PAGE_SIZE;
+ index += i;
+ nr_pages -= i;
+ i = 0;
+
+ bio = bio_alloc(GFP_NOFS, max_pages);
+ BUG_ON(!bio);
+ }
+ bio->bi_io_vec[i].bv_page = super->s_erase_page;
+ bio->bi_io_vec[i].bv_len = PAGE_SIZE;
+ bio->bi_io_vec[i].bv_offset = 0;
+ }
+ bio->bi_vcnt = nr_pages;
+ bio->bi_idx = 0;
+ bio->bi_size = nr_pages * PAGE_SIZE;
+ bio->bi_bdev = super->s_bdev;
+ bio->bi_sector = ofs >> 9;
+ bio->bi_private = sb;
+ bio->bi_end_io = erase_end_io;
+ atomic_inc(&super->s_pending_writes);
+ submit_bio(WRITE, bio);
+ return 0;
+}
+
+static int bdev_erase(struct super_block *sb, loff_t to, size_t len,
+ int ensure_write)
+{
+ struct logfs_super *super = logfs_super(sb);
+
+ BUG_ON(to & (PAGE_SIZE - 1));
+ BUG_ON(len & (PAGE_SIZE - 1));
+
+ if (super->s_flags & LOGFS_SB_FLAG_RO)
+ return -EROFS;
+
+ if (ensure_write) {
+ /*
+ * Object store doesn't care whether erases happen or not.
+ * But for the journal they are required. Otherwise a scan
+ * can find an old commit entry and assume it is the current
+ * one, travelling back in time.
+ */
+ do_erase(sb, to, to >> PAGE_SHIFT, len >> PAGE_SHIFT);
+ }
+
+ return 0;
+}
+
+static void bdev_sync(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+
+ wait_event(wq, atomic_read(&super->s_pending_writes) == 0);
+}
+
+static struct page *bdev_find_first_sb(struct super_block *sb, u64 *ofs)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct address_space *mapping = super->s_mapping_inode->i_mapping;
+ filler_t *filler = bdev_readpage;
+
+ *ofs = 0;
+ return read_cache_page(mapping, 0, filler, sb);
+}
+
+static struct page *bdev_find_last_sb(struct super_block *sb, u64 *ofs)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct address_space *mapping = super->s_mapping_inode->i_mapping;
+ filler_t *filler = bdev_readpage;
+ u64 pos = (super->s_bdev->bd_inode->i_size & ~0xfffULL) - 0x1000;
+ pgoff_t index = pos >> PAGE_SHIFT;
+
+ *ofs = pos;
+ return read_cache_page(mapping, index, filler, sb);
+}
+
+static int bdev_write_sb(struct super_block *sb, struct page *page)
+{
+ struct block_device *bdev = logfs_super(sb)->s_bdev;
+
+ /* Nothing special to do for block devices. */
+ return sync_request(page, bdev, WRITE);
+}
+
+static void bdev_put_device(struct super_block *sb)
+{
+ close_bdev_exclusive(logfs_super(sb)->s_bdev, FMODE_READ|FMODE_WRITE);
+}
+
+static const struct logfs_device_ops bd_devops = {
+ .find_first_sb = bdev_find_first_sb,
+ .find_last_sb = bdev_find_last_sb,
+ .write_sb = bdev_write_sb,
+ .readpage = bdev_readpage,
+ .writeseg = bdev_writeseg,
+ .erase = bdev_erase,
+ .sync = bdev_sync,
+ .put_device = bdev_put_device,
+};
+
+int logfs_get_sb_bdev(struct file_system_type *type, int flags,
+ const char *devname, struct vfsmount *mnt)
+{
+ struct block_device *bdev;
+
+ bdev = open_bdev_exclusive(devname, FMODE_READ|FMODE_WRITE, type);
+ if (IS_ERR(bdev))
+ return PTR_ERR(bdev);
+
+ if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
+ int mtdnr = MINOR(bdev->bd_dev);
+ close_bdev_exclusive(bdev, FMODE_READ|FMODE_WRITE);
+ return logfs_get_sb_mtd(type, flags, mtdnr, mnt);
+ }
+
+ return logfs_get_sb_device(type, flags, NULL, bdev, &bd_devops, mnt);
+}
diff --git a/fs/logfs/dev_mtd.c b/fs/logfs/dev_mtd.c
new file mode 100644
index 00000000000..cafb6ef2e05
--- /dev/null
+++ b/fs/logfs/dev_mtd.c
@@ -0,0 +1,254 @@
+/*
+ * fs/logfs/dev_mtd.c - Device access methods for MTD
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ */
+#include "logfs.h"
+#include <linux/completion.h>
+#include <linux/mount.h>
+#include <linux/sched.h>
+
+#define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1))
+
+static int mtd_read(struct super_block *sb, loff_t ofs, size_t len, void *buf)
+{
+ struct mtd_info *mtd = logfs_super(sb)->s_mtd;
+ size_t retlen;
+ int ret;
+
+ ret = mtd->read(mtd, ofs, len, &retlen, buf);
+ BUG_ON(ret == -EINVAL);
+ if (ret)
+ return ret;
+
+ /* Not sure if we should loop instead. */
+ if (retlen != len)
+ return -EIO;
+
+ return 0;
+}
+
+static int mtd_write(struct super_block *sb, loff_t ofs, size_t len, void *buf)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct mtd_info *mtd = super->s_mtd;
+ size_t retlen;
+ loff_t page_start, page_end;
+ int ret;
+
+ if (super->s_flags & LOGFS_SB_FLAG_RO)
+ return -EROFS;
+
+ BUG_ON((ofs >= mtd->size) || (len > mtd->size - ofs));
+ BUG_ON(ofs != (ofs >> super->s_writeshift) << super->s_writeshift);
+ BUG_ON(len > PAGE_CACHE_SIZE);
+ page_start = ofs & PAGE_CACHE_MASK;
+ page_end = PAGE_CACHE_ALIGN(ofs + len) - 1;
+ ret = mtd->write(mtd, ofs, len, &retlen, buf);
+ if (ret || (retlen != len))
+ return -EIO;
+
+ return 0;
+}
+
+/*
+ * For as long as I can remember (since about 2001) mtd->erase has been an
+ * asynchronous interface lacking the first driver to actually use the
+ * asynchronous properties. So just to prevent the first implementor of such
+ * a thing from breaking logfs in 2350, we do the usual pointless dance to
+ * declare a completion variable and wait for completion before returning
+ * from mtd_erase(). What an excercise in futility!
+ */
+static void logfs_erase_callback(struct erase_info *ei)
+{
+ complete((struct completion *)ei->priv);
+}
+
+static int mtd_erase_mapping(struct super_block *sb, loff_t ofs, size_t len)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct address_space *mapping = super->s_mapping_inode->i_mapping;
+ struct page *page;
+ pgoff_t index = ofs >> PAGE_SHIFT;
+
+ for (index = ofs >> PAGE_SHIFT; index < (ofs + len) >> PAGE_SHIFT; index++) {
+ page = find_get_page(mapping, index);
+ if (!page)
+ continue;
+ memset(page_address(page), 0xFF, PAGE_SIZE);
+ page_cache_release(page);
+ }
+ return 0;
+}
+
+static int mtd_erase(struct super_block *sb, loff_t ofs, size_t len,
+ int ensure_write)
+{
+ struct mtd_info *mtd = logfs_super(sb)->s_mtd;
+ struct erase_info ei;
+ DECLARE_COMPLETION_ONSTACK(complete);
+ int ret;
+
+ BUG_ON(len % mtd->erasesize);
+ if (logfs_super(sb)->s_flags & LOGFS_SB_FLAG_RO)
+ return -EROFS;
+
+ memset(&ei, 0, sizeof(ei));
+ ei.mtd = mtd;
+ ei.addr = ofs;
+ ei.len = len;
+ ei.callback = logfs_erase_callback;
+ ei.priv = (long)&complete;
+ ret = mtd->erase(mtd, &ei);
+ if (ret)
+ return -EIO;
+
+ wait_for_completion(&complete);
+ if (ei.state != MTD_ERASE_DONE)
+ return -EIO;
+ return mtd_erase_mapping(sb, ofs, len);
+}
+
+static void mtd_sync(struct super_block *sb)
+{
+ struct mtd_info *mtd = logfs_super(sb)->s_mtd;
+
+ if (mtd->sync)
+ mtd->sync(mtd);
+}
+
+static int mtd_readpage(void *_sb, struct page *page)
+{
+ struct super_block *sb = _sb;
+ int err;
+
+ err = mtd_read(sb, page->index << PAGE_SHIFT, PAGE_SIZE,
+ page_address(page));
+ if (err == -EUCLEAN) {
+ err = 0;
+ /* FIXME: force GC this segment */
+ }
+ if (err) {
+ ClearPageUptodate(page);
+ SetPageError(page);
+ } else {
+ SetPageUptodate(page);
+ ClearPageError(page);
+ }
+ unlock_page(page);
+ return err;
+}
+
+static struct page *mtd_find_first_sb(struct super_block *sb, u64 *ofs)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct address_space *mapping = super->s_mapping_inode->i_mapping;
+ filler_t *filler = mtd_readpage;
+ struct mtd_info *mtd = super->s_mtd;
+
+ if (!mtd->block_isbad)
+ return NULL;
+
+ *ofs = 0;
+ while (mtd->block_isbad(mtd, *ofs)) {
+ *ofs += mtd->erasesize;
+ if (*ofs >= mtd->size)
+ return NULL;
+ }
+ BUG_ON(*ofs & ~PAGE_MASK);
+ return read_cache_page(mapping, *ofs >> PAGE_SHIFT, filler, sb);
+}
+
+static struct page *mtd_find_last_sb(struct super_block *sb, u64 *ofs)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct address_space *mapping = super->s_mapping_inode->i_mapping;
+ filler_t *filler = mtd_readpage;
+ struct mtd_info *mtd = super->s_mtd;
+
+ if (!mtd->block_isbad)
+ return NULL;
+
+ *ofs = mtd->size - mtd->erasesize;
+ while (mtd->block_isbad(mtd, *ofs)) {
+ *ofs -= mtd->erasesize;
+ if (*ofs <= 0)
+ return NULL;
+ }
+ *ofs = *ofs + mtd->erasesize - 0x1000;
+ BUG_ON(*ofs & ~PAGE_MASK);
+ return read_cache_page(mapping, *ofs >> PAGE_SHIFT, filler, sb);
+}
+
+static int __mtd_writeseg(struct super_block *sb, u64 ofs, pgoff_t index,
+ size_t nr_pages)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct address_space *mapping = super->s_mapping_inode->i_mapping;
+ struct page *page;
+ int i, err;
+
+ for (i = 0; i < nr_pages; i++) {
+ page = find_lock_page(mapping, index + i);
+ BUG_ON(!page);
+
+ err = mtd_write(sb, page->index << PAGE_SHIFT, PAGE_SIZE,
+ page_address(page));
+ unlock_page(page);
+ page_cache_release(page);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+static void mtd_writeseg(struct super_block *sb, u64 ofs, size_t len)
+{
+ struct logfs_super *super = logfs_super(sb);
+ int head;
+
+ if (super->s_flags & LOGFS_SB_FLAG_RO)
+ return;
+
+ if (len == 0) {
+ /* This can happen when the object fit perfectly into a
+ * segment, the segment gets written per sync and subsequently
+ * closed.
+ */
+ return;
+ }
+ head = ofs & (PAGE_SIZE - 1);
+ if (head) {
+ ofs -= head;
+ len += head;
+ }
+ len = PAGE_ALIGN(len);
+ __mtd_writeseg(sb, ofs, ofs >> PAGE_SHIFT, len >> PAGE_SHIFT);
+}
+
+static void mtd_put_device(struct super_block *sb)
+{
+ put_mtd_device(logfs_super(sb)->s_mtd);
+}
+
+static const struct logfs_device_ops mtd_devops = {
+ .find_first_sb = mtd_find_first_sb,
+ .find_last_sb = mtd_find_last_sb,
+ .readpage = mtd_readpage,
+ .writeseg = mtd_writeseg,
+ .erase = mtd_erase,
+ .sync = mtd_sync,
+ .put_device = mtd_put_device,
+};
+
+int logfs_get_sb_mtd(struct file_system_type *type, int flags,
+ int mtdnr, struct vfsmount *mnt)
+{
+ struct mtd_info *mtd;
+ const struct logfs_device_ops *devops = &mtd_devops;
+
+ mtd = get_mtd_device(NULL, mtdnr);
+ return logfs_get_sb_device(type, flags, mtd, NULL, devops, mnt);
+}
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c
new file mode 100644
index 00000000000..56a8bfbb012
--- /dev/null
+++ b/fs/logfs/dir.c
@@ -0,0 +1,827 @@
+/*
+ * fs/logfs/dir.c - directory-related code
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ */
+#include "logfs.h"
+
+
+/*
+ * Atomic dir operations
+ *
+ * Directory operations are by default not atomic. Dentries and Inodes are
+ * created/removed/altered in seperate operations. Therefore we need to do
+ * a small amount of journaling.
+ *
+ * Create, link, mkdir, mknod and symlink all share the same function to do
+ * the work: __logfs_create. This function works in two atomic steps:
+ * 1. allocate inode (remember in journal)
+ * 2. allocate dentry (clear journal)
+ *
+ * As we can only get interrupted between the two, when the inode we just
+ * created is simply stored in the anchor. On next mount, if we were
+ * interrupted, we delete the inode. From a users point of view the
+ * operation never happened.
+ *
+ * Unlink and rmdir also share the same function: unlink. Again, this
+ * function works in two atomic steps
+ * 1. remove dentry (remember inode in journal)
+ * 2. unlink inode (clear journal)
+ *
+ * And again, on the next mount, if we were interrupted, we delete the inode.
+ * From a users point of view the operation succeeded.
+ *
+ * Rename is the real pain to deal with, harder than all the other methods
+ * combined. Depending on the circumstances we can run into three cases.
+ * A "target rename" where the target dentry already existed, a "local
+ * rename" where both parent directories are identical or a "cross-directory
+ * rename" in the remaining case.
+ *
+ * Local rename is atomic, as the old dentry is simply rewritten with a new
+ * name.
+ *
+ * Cross-directory rename works in two steps, similar to __logfs_create and
+ * logfs_unlink:
+ * 1. Write new dentry (remember old dentry in journal)
+ * 2. Remove old dentry (clear journal)
+ *
+ * Here we remember a dentry instead of an inode. On next mount, if we were
+ * interrupted, we delete the dentry. From a users point of view, the
+ * operation succeeded.
+ *
+ * Target rename works in three atomic steps:
+ * 1. Attach old inode to new dentry (remember old dentry and new inode)
+ * 2. Remove old dentry (still remember the new inode)
+ * 3. Remove victim inode
+ *
+ * Here we remember both an inode an a dentry. If we get interrupted
+ * between steps 1 and 2, we delete both the dentry and the inode. If
+ * we get interrupted between steps 2 and 3, we delete just the inode.
+ * In either case, the remaining objects are deleted on next mount. From
+ * a users point of view, the operation succeeded.
+ */
+
+static int write_dir(struct inode *dir, struct logfs_disk_dentry *dd,
+ loff_t pos)
+{
+ return logfs_inode_write(dir, dd, sizeof(*dd), pos, WF_LOCK, NULL);
+}
+
+static int write_inode(struct inode *inode)
+{
+ return __logfs_write_inode(inode, WF_LOCK);
+}
+
+static s64 dir_seek_data(struct inode *inode, s64 pos)
+{
+ s64 new_pos = logfs_seek_data(inode, pos);
+
+ return max(pos, new_pos - 1);
+}
+
+static int beyond_eof(struct inode *inode, loff_t bix)
+{
+ loff_t pos = bix << inode->i_sb->s_blocksize_bits;
+ return pos >= i_size_read(inode);
+}
+
+/*
+ * Prime value was chosen to be roughly 256 + 26. r5 hash uses 11,
+ * so short names (len <= 9) don't even occupy the complete 32bit name
+ * space. A prime >256 ensures short names quickly spread the 32bit
+ * name space. Add about 26 for the estimated amount of information
+ * of each character and pick a prime nearby, preferrably a bit-sparse
+ * one.
+ */
+static u32 hash_32(const char *s, int len, u32 seed)
+{
+ u32 hash = seed;
+ int i;
+
+ for (i = 0; i < len; i++)
+ hash = hash * 293 + s[i];
+ return hash;
+}
+
+/*
+ * We have to satisfy several conflicting requirements here. Small
+ * directories should stay fairly compact and not require too many
+ * indirect blocks. The number of possible locations for a given hash
+ * should be small to make lookup() fast. And we should try hard not
+ * to overflow the 32bit name space or nfs and 32bit host systems will
+ * be unhappy.
+ *
+ * So we use the following scheme. First we reduce the hash to 0..15
+ * and try a direct block. If that is occupied we reduce the hash to
+ * 16..255 and try an indirect block. Same for 2x and 3x indirect
+ * blocks. Lastly we reduce the hash to 0x800_0000 .. 0xffff_ffff,
+ * but use buckets containing eight entries instead of a single one.
+ *
+ * Using 16 entries should allow for a reasonable amount of hash
+ * collisions, so the 32bit name space can be packed fairly tight
+ * before overflowing. Oh and currently we don't overflow but return
+ * and error.
+ *
+ * How likely are collisions? Doing the appropriate math is beyond me
+ * and the Bronstein textbook. But running a test program to brute
+ * force collisions for a couple of days showed that on average the
+ * first collision occurs after 598M entries, with 290M being the
+ * smallest result. Obviously 21 entries could already cause a
+ * collision if all entries are carefully chosen.
+ */
+static pgoff_t hash_index(u32 hash, int round)
+{
+ u32 i0_blocks = I0_BLOCKS;
+ u32 i1_blocks = I1_BLOCKS;
+ u32 i2_blocks = I2_BLOCKS;
+ u32 i3_blocks = I3_BLOCKS;
+
+ switch (round) {
+ case 0:
+ return hash % i0_blocks;
+ case 1:
+ return i0_blocks + hash % (i1_blocks - i0_blocks);
+ case 2:
+ return i1_blocks + hash % (i2_blocks - i1_blocks);
+ case 3:
+ return i2_blocks + hash % (i3_blocks - i2_blocks);
+ case 4 ... 19:
+ return i3_blocks + 16 * (hash % (((1<<31) - i3_blocks) / 16))
+ + round - 4;
+ }
+ BUG();
+}
+
+static struct page *logfs_get_dd_page(struct inode *dir, struct dentry *dentry)
+{
+ struct qstr *name = &dentry->d_name;
+ struct page *page;
+ struct logfs_disk_dentry *dd;
+ u32 hash = hash_32(name->name, name->len, 0);
+ pgoff_t index;
+ int round;
+
+ if (name->len > LOGFS_MAX_NAMELEN)
+ return ERR_PTR(-ENAMETOOLONG);
+
+ for (round = 0; round < 20; round++) {
+ index = hash_index(hash, round);
+
+ if (beyond_eof(dir, index))
+ return NULL;
+ if (!logfs_exist_block(dir, index))
+ continue;
+ page = read_cache_page(dir->i_mapping, index,
+ (filler_t *)logfs_readpage, NULL);
+ if (IS_ERR(page))
+ return page;
+ dd = kmap_atomic(page, KM_USER0);
+ BUG_ON(dd->namelen == 0);
+
+ if (name->len != be16_to_cpu(dd->namelen) ||
+ memcmp(name->name, dd->name, name->len)) {
+ kunmap_atomic(dd, KM_USER0);
+ page_cache_release(page);
+ continue;
+ }
+
+ kunmap_atomic(dd, KM_USER0);
+ return page;
+ }
+ return NULL;
+}
+
+static int logfs_remove_inode(struct inode *inode)
+{
+ int ret;
+
+ inode->i_nlink--;
+ ret = write_inode(inode);
+ LOGFS_BUG_ON(ret, inode->i_sb);
+ return ret;
+}
+
+static void abort_transaction(struct inode *inode, struct logfs_transaction *ta)
+{
+ if (logfs_inode(inode)->li_block)
+ logfs_inode(inode)->li_block->ta = NULL;
+ kfree(ta);
+}
+
+static int logfs_unlink(struct inode *dir, struct dentry *dentry)
+{
+ struct logfs_super *super = logfs_super(dir->i_sb);
+ struct inode *inode = dentry->d_inode;
+ struct logfs_transaction *ta;
+ struct page *page;
+ pgoff_t index;
+ int ret;
+
+ ta = kzalloc(sizeof(*ta), GFP_KERNEL);
+ if (!ta)
+ return -ENOMEM;
+
+ ta->state = UNLINK_1;
+ ta->ino = inode->i_ino;
+
+ inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+
+ page = logfs_get_dd_page(dir, dentry);
+ if (!page) {
+ kfree(ta);
+ return -ENOENT;
+ }
+ if (IS_ERR(page)) {
+ kfree(ta);
+ return PTR_ERR(page);
+ }
+ index = page->index;
+ page_cache_release(page);
+
+ mutex_lock(&super->s_dirop_mutex);
+ logfs_add_transaction(dir, ta);
+
+ ret = logfs_delete(dir, index, NULL);
+ if (!ret)
+ ret = write_inode(dir);
+
+ if (ret) {
+ abort_transaction(dir, ta);
+ printk(KERN_ERR"LOGFS: unable to delete inode\n");
+ goto out;
+ }
+
+ ta->state = UNLINK_2;
+ logfs_add_transaction(inode, ta);
+ ret = logfs_remove_inode(inode);
+out:
+ mutex_unlock(&super->s_dirop_mutex);
+ return ret;
+}
+
+static inline int logfs_empty_dir(struct inode *dir)
+{
+ u64 data;
+
+ data = logfs_seek_data(dir, 0) << dir->i_sb->s_blocksize_bits;
+ return data >= i_size_read(dir);
+}
+
+static int logfs_rmdir(struct inode *dir, struct dentry *dentry)
+{
+ struct inode *inode = dentry->d_inode;
+
+ if (!logfs_empty_dir(inode))
+ return -ENOTEMPTY;
+
+ return logfs_unlink(dir, dentry);
+}
+
+/* FIXME: readdir currently has it's own dir_walk code. I don't see a good
+ * way to combine the two copies */
+#define IMPLICIT_NODES 2
+static int __logfs_readdir(struct file *file, void *buf, filldir_t filldir)
+{
+ struct inode *dir = file->f_dentry->d_inode;
+ loff_t pos = file->f_pos - IMPLICIT_NODES;
+ struct page *page;
+ struct logfs_disk_dentry *dd;
+ int full;
+
+ BUG_ON(pos < 0);
+ for (;; pos++) {
+ if (beyond_eof(dir, pos))
+ break;
+ if (!logfs_exist_block(dir, pos)) {
+ /* deleted dentry */
+ pos = dir_seek_data(dir, pos);
+ continue;
+ }
+ page = read_cache_page(dir->i_mapping, pos,
+ (filler_t *)logfs_readpage, NULL);
+ if (IS_ERR(page))
+ return PTR_ERR(page);
+ dd = kmap_atomic(page, KM_USER0);
+ BUG_ON(dd->namelen == 0);
+
+ full = filldir(buf, (char *)dd->name, be16_to_cpu(dd->namelen),
+ pos, be64_to_cpu(dd->ino), dd->type);
+ kunmap_atomic(dd, KM_USER0);
+ page_cache_release(page);
+ if (full)
+ break;
+ }
+
+ file->f_pos = pos + IMPLICIT_NODES;
+ return 0;
+}
+
+static int logfs_readdir(struct file *file, void *buf, filldir_t filldir)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+ ino_t pino = parent_ino(file->f_dentry);
+ int err;
+
+ if (file->f_pos < 0)
+ return -EINVAL;
+
+ if (file->f_pos == 0) {
+ if (filldir(buf, ".", 1, 1, inode->i_ino, DT_DIR) < 0)
+ return 0;
+ file->f_pos++;
+ }
+ if (file->f_pos == 1) {
+ if (filldir(buf, "..", 2, 2, pino, DT_DIR) < 0)
+ return 0;
+ file->f_pos++;
+ }
+
+ err = __logfs_readdir(file, buf, filldir);
+ return err;
+}
+
+static void logfs_set_name(struct logfs_disk_dentry *dd, struct qstr *name)
+{
+ dd->namelen = cpu_to_be16(name->len);
+ memcpy(dd->name, name->name, name->len);
+}
+
+static struct dentry *logfs_lookup(struct inode *dir, struct dentry *dentry,
+ struct nameidata *nd)
+{
+ struct page *page;
+ struct logfs_disk_dentry *dd;
+ pgoff_t index;
+ u64 ino = 0;
+ struct inode *inode;
+
+ page = logfs_get_dd_page(dir, dentry);
+ if (IS_ERR(page))
+ return ERR_CAST(page);
+ if (!page) {
+ d_add(dentry, NULL);
+ return NULL;
+ }
+ index = page->index;
+ dd = kmap_atomic(page, KM_USER0);
+ ino = be64_to_cpu(dd->ino);
+ kunmap_atomic(dd, KM_USER0);
+ page_cache_release(page);
+
+ inode = logfs_iget(dir->i_sb, ino);
+ if (IS_ERR(inode)) {
+ printk(KERN_ERR"LogFS: Cannot read inode #%llx for dentry (%lx, %lx)n",
+ ino, dir->i_ino, index);
+ return ERR_CAST(inode);
+ }
+ return d_splice_alias(inode, dentry);
+}
+
+static void grow_dir(struct inode *dir, loff_t index)
+{
+ index = (index + 1) << dir->i_sb->s_blocksize_bits;
+ if (i_size_read(dir) < index)
+ i_size_write(dir, index);
+}
+
+static int logfs_write_dir(struct inode *dir, struct dentry *dentry,
+ struct inode *inode)
+{
+ struct page *page;
+ struct logfs_disk_dentry *dd;
+ u32 hash = hash_32(dentry->d_name.name, dentry->d_name.len, 0);
+ pgoff_t index;
+ int round, err;
+
+ for (round = 0; round < 20; round++) {
+ index = hash_index(hash, round);
+
+ if (logfs_exist_block(dir, index))
+ continue;
+ page = find_or_create_page(dir->i_mapping, index, GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+
+ dd = kmap_atomic(page, KM_USER0);
+ memset(dd, 0, sizeof(*dd));
+ dd->ino = cpu_to_be64(inode->i_ino);
+ dd->type = logfs_type(inode);
+ logfs_set_name(dd, &dentry->d_name);
+ kunmap_atomic(dd, KM_USER0);
+
+ err = logfs_write_buf(dir, page, WF_LOCK);
+ unlock_page(page);
+ page_cache_release(page);
+ if (!err)
+ grow_dir(dir, index);
+ return err;
+ }
+ /* FIXME: Is there a better return value? In most cases neither
+ * the filesystem nor the directory are full. But we have had
+ * too many collisions for this particular hash and no fallback.
+ */
+ return -ENOSPC;
+}
+
+static int __logfs_create(struct inode *dir, struct dentry *dentry,
+ struct inode *inode, const char *dest, long destlen)
+{
+ struct logfs_super *super = logfs_super(dir->i_sb);
+ struct logfs_inode *li = logfs_inode(inode);
+ struct logfs_transaction *ta;
+ int ret;
+
+ ta = kzalloc(sizeof(*ta), GFP_KERNEL);
+ if (!ta)
+ return -ENOMEM;
+
+ ta->state = CREATE_1;
+ ta->ino = inode->i_ino;
+ mutex_lock(&super->s_dirop_mutex);
+ logfs_add_transaction(inode, ta);
+
+ if (dest) {
+ /* symlink */
+ ret = logfs_inode_write(inode, dest, destlen, 0, WF_LOCK, NULL);
+ if (!ret)
+ ret = write_inode(inode);
+ } else {
+ /* creat/mkdir/mknod */
+ ret = write_inode(inode);
+ }
+ if (ret) {
+ abort_transaction(inode, ta);
+ li->li_flags |= LOGFS_IF_STILLBORN;
+ /* FIXME: truncate symlink */
+ inode->i_nlink--;
+ iput(inode);
+ goto out;
+ }
+
+ ta->state = CREATE_2;
+ logfs_add_transaction(dir, ta);
+ ret = logfs_write_dir(dir, dentry, inode);
+ /* sync directory */
+ if (!ret)
+ ret = write_inode(dir);
+
+ if (ret) {
+ logfs_del_transaction(dir, ta);
+ ta->state = CREATE_2;
+ logfs_add_transaction(inode, ta);
+ logfs_remove_inode(inode);
+ iput(inode);
+ goto out;
+ }
+ d_instantiate(dentry, inode);
+out:
+ mutex_unlock(&super->s_dirop_mutex);
+ return ret;
+}
+
+static int logfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+ struct inode *inode;
+
+ /*
+ * FIXME: why do we have to fill in S_IFDIR, while the mode is
+ * correct for mknod, creat, etc.? Smells like the vfs *should*
+ * do it for us but for some reason fails to do so.
+ */
+ inode = logfs_new_inode(dir, S_IFDIR | mode);
+ if (IS_ERR(inode))
+ return PTR_ERR(inode);
+
+ inode->i_op = &logfs_dir_iops;
+ inode->i_fop = &logfs_dir_fops;
+
+ return __logfs_create(dir, dentry, inode, NULL, 0);
+}
+
+static int logfs_create(struct inode *dir, struct dentry *dentry, int mode,
+ struct nameidata *nd)
+{
+ struct inode *inode;
+
+ inode = logfs_new_inode(dir, mode);
+ if (IS_ERR(inode))
+ return PTR_ERR(inode);
+
+ inode->i_op = &logfs_reg_iops;
+ inode->i_fop = &logfs_reg_fops;
+ inode->i_mapping->a_ops = &logfs_reg_aops;
+
+ return __logfs_create(dir, dentry, inode, NULL, 0);
+}
+
+static int logfs_mknod(struct inode *dir, struct dentry *dentry, int mode,
+ dev_t rdev)
+{
+ struct inode *inode;
+
+ if (dentry->d_name.len > LOGFS_MAX_NAMELEN)
+ return -ENAMETOOLONG;
+
+ inode = logfs_new_inode(dir, mode);
+ if (IS_ERR(inode))
+ return PTR_ERR(inode);
+
+ init_special_inode(inode, mode, rdev);
+
+ return __logfs_create(dir, dentry, inode, NULL, 0);
+}
+
+static int logfs_symlink(struct inode *dir, struct dentry *dentry,
+ const char *target)
+{
+ struct inode *inode;
+ size_t destlen = strlen(target) + 1;
+
+ if (destlen > dir->i_sb->s_blocksize)
+ return -ENAMETOOLONG;
+
+ inode = logfs_new_inode(dir, S_IFLNK | 0777);
+ if (IS_ERR(inode))
+ return PTR_ERR(inode);
+
+ inode->i_op = &logfs_symlink_iops;
+ inode->i_mapping->a_ops = &logfs_reg_aops;
+
+ return __logfs_create(dir, dentry, inode, target, destlen);
+}
+
+static int logfs_permission(struct inode *inode, int mask)
+{
+ return generic_permission(inode, mask, NULL);
+}
+
+static int logfs_link(struct dentry *old_dentry, struct inode *dir,
+ struct dentry *dentry)
+{
+ struct inode *inode = old_dentry->d_inode;
+
+ if (inode->i_nlink >= LOGFS_LINK_MAX)
+ return -EMLINK;
+
+ inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ atomic_inc(&inode->i_count);
+ inode->i_nlink++;
+ mark_inode_dirty_sync(inode);
+
+ return __logfs_create(dir, dentry, inode, NULL, 0);
+}
+
+static int logfs_get_dd(struct inode *dir, struct dentry *dentry,
+ struct logfs_disk_dentry *dd, loff_t *pos)
+{
+ struct page *page;
+ void *map;
+
+ page = logfs_get_dd_page(dir, dentry);
+ if (IS_ERR(page))
+ return PTR_ERR(page);
+ *pos = page->index;
+ map = kmap_atomic(page, KM_USER0);
+ memcpy(dd, map, sizeof(*dd));
+ kunmap_atomic(map, KM_USER0);
+ page_cache_release(page);
+ return 0;
+}
+
+static int logfs_delete_dd(struct inode *dir, loff_t pos)
+{
+ /*
+ * Getting called with pos somewhere beyond eof is either a goofup
+ * within this file or means someone maliciously edited the
+ * (crc-protected) journal.
+ */
+ BUG_ON(beyond_eof(dir, pos));
+ dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+ log_dir(" Delete dentry (%lx, %llx)\n", dir->i_ino, pos);
+ return logfs_delete(dir, pos, NULL);
+}
+
+/*
+ * Cross-directory rename, target does not exist. Just a little nasty.
+ * Create a new dentry in the target dir, then remove the old dentry,
+ * all the while taking care to remember our operation in the journal.
+ */
+static int logfs_rename_cross(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
+{
+ struct logfs_super *super = logfs_super(old_dir->i_sb);
+ struct logfs_disk_dentry dd;
+ struct logfs_transaction *ta;
+ loff_t pos;
+ int err;
+
+ /* 1. locate source dd */
+ err = logfs_get_dd(old_dir, old_dentry, &dd, &pos);
+ if (err)
+ return err;
+
+ ta = kzalloc(sizeof(*ta), GFP_KERNEL);
+ if (!ta)
+ return -ENOMEM;
+
+ ta->state = CROSS_RENAME_1;
+ ta->dir = old_dir->i_ino;
+ ta->pos = pos;
+
+ /* 2. write target dd */
+ mutex_lock(&super->s_dirop_mutex);
+ logfs_add_transaction(new_dir, ta);
+ err = logfs_write_dir(new_dir, new_dentry, old_dentry->d_inode);
+ if (!err)
+ err = write_inode(new_dir);
+
+ if (err) {
+ super->s_rename_dir = 0;
+ super->s_rename_pos = 0;
+ abort_transaction(new_dir, ta);
+ goto out;
+ }
+
+ /* 3. remove source dd */
+ ta->state = CROSS_RENAME_2;
+ logfs_add_transaction(old_dir, ta);
+ err = logfs_delete_dd(old_dir, pos);
+ if (!err)
+ err = write_inode(old_dir);
+ LOGFS_BUG_ON(err, old_dir->i_sb);
+out:
+ mutex_unlock(&super->s_dirop_mutex);
+ return err;
+}
+
+static int logfs_replace_inode(struct inode *dir, struct dentry *dentry,
+ struct logfs_disk_dentry *dd, struct inode *inode)
+{
+ loff_t pos;
+ int err;
+
+ err = logfs_get_dd(dir, dentry, dd, &pos);
+ if (err)
+ return err;
+ dd->ino = cpu_to_be64(inode->i_ino);
+ dd->type = logfs_type(inode);
+
+ err = write_dir(dir, dd, pos);
+ if (err)
+ return err;
+ log_dir("Replace dentry (%lx, %llx) %s -> %llx\n", dir->i_ino, pos,
+ dd->name, be64_to_cpu(dd->ino));
+ return write_inode(dir);
+}
+
+/* Target dentry exists - the worst case. We need to attach the source
+ * inode to the target dentry, then remove the orphaned target inode and
+ * source dentry.
+ */
+static int logfs_rename_target(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
+{
+ struct logfs_super *super = logfs_super(old_dir->i_sb);
+ struct inode *old_inode = old_dentry->d_inode;
+ struct inode *new_inode = new_dentry->d_inode;
+ int isdir = S_ISDIR(old_inode->i_mode);
+ struct logfs_disk_dentry dd;
+ struct logfs_transaction *ta;
+ loff_t pos;
+ int err;
+
+ BUG_ON(isdir != S_ISDIR(new_inode->i_mode));
+ if (isdir) {
+ if (!logfs_empty_dir(new_inode))
+ return -ENOTEMPTY;
+ }
+
+ /* 1. locate source dd */
+ err = logfs_get_dd(old_dir, old_dentry, &dd, &pos);
+ if (err)
+ return err;
+
+ ta = kzalloc(sizeof(*ta), GFP_KERNEL);
+ if (!ta)
+ return -ENOMEM;
+
+ ta->state = TARGET_RENAME_1;
+ ta->dir = old_dir->i_ino;
+ ta->pos = pos;
+ ta->ino = new_inode->i_ino;
+
+ /* 2. attach source inode to target dd */
+ mutex_lock(&super->s_dirop_mutex);
+ logfs_add_transaction(new_dir, ta);
+ err = logfs_replace_inode(new_dir, new_dentry, &dd, old_inode);
+ if (err) {
+ super->s_rename_dir = 0;
+ super->s_rename_pos = 0;
+ super->s_victim_ino = 0;
+ abort_transaction(new_dir, ta);
+ goto out;
+ }
+
+ /* 3. remove source dd */
+ ta->state = TARGET_RENAME_2;
+ logfs_add_transaction(old_dir, ta);
+ err = logfs_delete_dd(old_dir, pos);
+ if (!err)
+ err = write_inode(old_dir);
+ LOGFS_BUG_ON(err, old_dir->i_sb);
+
+ /* 4. remove target inode */
+ ta->state = TARGET_RENAME_3;
+ logfs_add_transaction(new_inode, ta);
+ err = logfs_remove_inode(new_inode);
+
+out:
+ mutex_unlock(&super->s_dirop_mutex);
+ return err;
+}
+
+static int logfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+ struct inode *new_dir, struct dentry *new_dentry)
+{
+ if (new_dentry->d_inode)
+ return logfs_rename_target(old_dir, old_dentry,
+ new_dir, new_dentry);
+ return logfs_rename_cross(old_dir, old_dentry, new_dir, new_dentry);
+}
+
+/* No locking done here, as this is called before .get_sb() returns. */
+int logfs_replay_journal(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct inode *inode;
+ u64 ino, pos;
+ int err;
+
+ if (super->s_victim_ino) {
+ /* delete victim inode */
+ ino = super->s_victim_ino;
+ printk(KERN_INFO"LogFS: delete unmapped inode #%llx\n", ino);
+ inode = logfs_iget(sb, ino);
+ if (IS_ERR(inode))
+ goto fail;
+
+ LOGFS_BUG_ON(i_size_read(inode) > 0, sb);
+ super->s_victim_ino = 0;
+ err = logfs_remove_inode(inode);
+ iput(inode);
+ if (err) {
+ super->s_victim_ino = ino;
+ goto fail;
+ }
+ }
+ if (super->s_rename_dir) {
+ /* delete old dd from rename */
+ ino = super->s_rename_dir;
+ pos = super->s_rename_pos;
+ printk(KERN_INFO"LogFS: delete unbacked dentry (%llx, %llx)\n",
+ ino, pos);
+ inode = logfs_iget(sb, ino);
+ if (IS_ERR(inode))
+ goto fail;
+
+ super->s_rename_dir = 0;
+ super->s_rename_pos = 0;
+ err = logfs_delete_dd(inode, pos);
+ iput(inode);
+ if (err) {
+ super->s_rename_dir = ino;
+ super->s_rename_pos = pos;
+ goto fail;
+ }
+ }
+ return 0;
+fail:
+ LOGFS_BUG(sb);
+ return -EIO;
+}
+
+const struct inode_operations logfs_symlink_iops = {
+ .readlink = generic_readlink,
+ .follow_link = page_follow_link_light,
+};
+
+const struct inode_operations logfs_dir_iops = {
+ .create = logfs_create,
+ .link = logfs_link,
+ .lookup = logfs_lookup,
+ .mkdir = logfs_mkdir,
+ .mknod = logfs_mknod,
+ .rename = logfs_rename,
+ .rmdir = logfs_rmdir,
+ .permission = logfs_permission,
+ .symlink = logfs_symlink,
+ .unlink = logfs_unlink,
+};
+const struct file_operations logfs_dir_fops = {
+ .fsync = logfs_fsync,
+ .ioctl = logfs_ioctl,
+ .readdir = logfs_readdir,
+ .read = generic_read_dir,
+};
diff --git a/fs/logfs/file.c b/fs/logfs/file.c
new file mode 100644
index 00000000000..370f367a933
--- /dev/null
+++ b/fs/logfs/file.c
@@ -0,0 +1,263 @@
+/*
+ * fs/logfs/file.c - prepare_write, commit_write and friends
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ */
+#include "logfs.h"
+#include <linux/sched.h>
+#include <linux/writeback.h>
+
+static int logfs_write_begin(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned flags,
+ struct page **pagep, void **fsdata)
+{
+ struct inode *inode = mapping->host;
+ struct page *page;
+ pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+
+ page = grab_cache_page_write_begin(mapping, index, flags);
+ if (!page)
+ return -ENOMEM;
+ *pagep = page;
+
+ if ((len == PAGE_CACHE_SIZE) || PageUptodate(page))
+ return 0;
+ if ((pos & PAGE_CACHE_MASK) >= i_size_read(inode)) {
+ unsigned start = pos & (PAGE_CACHE_SIZE - 1);
+ unsigned end = start + len;
+
+ /* Reading beyond i_size is simple: memset to zero */
+ zero_user_segments(page, 0, start, end, PAGE_CACHE_SIZE);
+ return 0;
+ }
+ return logfs_readpage_nolock(page);
+}
+
+static int logfs_write_end(struct file *file, struct address_space *mapping,
+ loff_t pos, unsigned len, unsigned copied, struct page *page,
+ void *fsdata)
+{
+ struct inode *inode = mapping->host;
+ pgoff_t index = page->index;
+ unsigned start = pos & (PAGE_CACHE_SIZE - 1);
+ unsigned end = start + copied;
+ int ret = 0;
+
+ BUG_ON(PAGE_CACHE_SIZE != inode->i_sb->s_blocksize);
+ BUG_ON(page->index > I3_BLOCKS);
+
+ if (copied < len) {
+ /*
+ * Short write of a non-initialized paged. Just tell userspace
+ * to retry the entire page.
+ */
+ if (!PageUptodate(page)) {
+ copied = 0;
+ goto out;
+ }
+ }
+ if (copied == 0)
+ goto out; /* FIXME: do we need to update inode? */
+
+ if (i_size_read(inode) < (index << PAGE_CACHE_SHIFT) + end) {
+ i_size_write(inode, (index << PAGE_CACHE_SHIFT) + end);
+ mark_inode_dirty_sync(inode);
+ }
+
+ SetPageUptodate(page);
+ if (!PageDirty(page)) {
+ if (!get_page_reserve(inode, page))
+ __set_page_dirty_nobuffers(page);
+ else
+ ret = logfs_write_buf(inode, page, WF_LOCK);
+ }
+out:
+ unlock_page(page);
+ page_cache_release(page);
+ return ret ? ret : copied;
+}
+
+int logfs_readpage(struct file *file, struct page *page)
+{
+ int ret;
+
+ ret = logfs_readpage_nolock(page);
+ unlock_page(page);
+ return ret;
+}
+
+/* Clear the page's dirty flag in the radix tree. */
+/* TODO: mucking with PageWriteback is silly. Add a generic function to clear
+ * the dirty bit from the radix tree for filesystems that don't have to wait
+ * for page writeback to finish (i.e. any compressing filesystem).
+ */
+static void clear_radix_tree_dirty(struct page *page)
+{
+ BUG_ON(PagePrivate(page) || page->private);
+ set_page_writeback(page);
+ end_page_writeback(page);
+}
+
+static int __logfs_writepage(struct page *page)
+{
+ struct inode *inode = page->mapping->host;
+ int err;
+
+ err = logfs_write_buf(inode, page, WF_LOCK);
+ if (err)
+ set_page_dirty(page);
+ else
+ clear_radix_tree_dirty(page);
+ unlock_page(page);
+ return err;
+}
+
+static int logfs_writepage(struct page *page, struct writeback_control *wbc)
+{
+ struct inode *inode = page->mapping->host;
+ loff_t i_size = i_size_read(inode);
+ pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
+ unsigned offset;
+ u64 bix;
+ level_t level;
+
+ log_file("logfs_writepage(%lx, %lx, %p)\n", inode->i_ino, page->index,
+ page);
+
+ logfs_unpack_index(page->index, &bix, &level);
+
+ /* Indirect blocks are never truncated */
+ if (level != 0)
+ return __logfs_writepage(page);
+
+ /*
+ * TODO: everything below is a near-verbatim copy of nobh_writepage().
+ * The relevant bits should be factored out after logfs is merged.
+ */
+
+ /* Is the page fully inside i_size? */
+ if (bix < end_index)
+ return __logfs_writepage(page);
+
+ /* Is the page fully outside i_size? (truncate in progress) */
+ offset = i_size & (PAGE_CACHE_SIZE-1);
+ if (bix > end_index || offset == 0) {
+ unlock_page(page);
+ return 0; /* don't care */
+ }
+
+ /*
+ * The page straddles i_size. It must be zeroed out on each and every
+ * writepage invokation because it may be mmapped. "A file is mapped
+ * in multiples of the page size. For a file that is not a multiple of
+ * the page size, the remaining memory is zeroed when mapped, and
+ * writes to that region are not written out to the file."
+ */
+ zero_user_segment(page, offset, PAGE_CACHE_SIZE);
+ return __logfs_writepage(page);
+}
+
+static void logfs_invalidatepage(struct page *page, unsigned long offset)
+{
+ move_page_to_btree(page);
+ BUG_ON(PagePrivate(page) || page->private);
+}
+
+static int logfs_releasepage(struct page *page, gfp_t only_xfs_uses_this)
+{
+ return 0; /* None of these are easy to release */
+}
+
+
+int logfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+ unsigned int oldflags, flags;
+ int err;
+
+ switch (cmd) {
+ case FS_IOC_GETFLAGS:
+ flags = li->li_flags & LOGFS_FL_USER_VISIBLE;
+ return put_user(flags, (int __user *)arg);
+ case FS_IOC_SETFLAGS:
+ if (IS_RDONLY(inode))
+ return -EROFS;
+
+ if (!is_owner_or_cap(inode))
+ return -EACCES;
+
+ err = get_user(flags, (int __user *)arg);
+ if (err)
+ return err;
+
+ mutex_lock(&inode->i_mutex);
+ oldflags = li->li_flags;
+ flags &= LOGFS_FL_USER_MODIFIABLE;
+ flags |= oldflags & ~LOGFS_FL_USER_MODIFIABLE;
+ li->li_flags = flags;
+ mutex_unlock(&inode->i_mutex);
+
+ inode->i_ctime = CURRENT_TIME;
+ mark_inode_dirty_sync(inode);
+ return 0;
+
+ default:
+ return -ENOTTY;
+ }
+}
+
+int logfs_fsync(struct file *file, struct dentry *dentry, int datasync)
+{
+ struct super_block *sb = dentry->d_inode->i_sb;
+ struct logfs_super *super = logfs_super(sb);
+
+ /* FIXME: write anchor */
+ super->s_devops->sync(sb);
+ return 0;
+}
+
+static int logfs_setattr(struct dentry *dentry, struct iattr *attr)
+{
+ struct inode *inode = dentry->d_inode;
+ int err = 0;
+
+ if (attr->ia_valid & ATTR_SIZE)
+ err = logfs_truncate(inode, attr->ia_size);
+ attr->ia_valid &= ~ATTR_SIZE;
+
+ if (!err)
+ err = inode_change_ok(inode, attr);
+ if (!err)
+ err = inode_setattr(inode, attr);
+ return err;
+}
+
+const struct inode_operations logfs_reg_iops = {
+ .setattr = logfs_setattr,
+};
+
+const struct file_operations logfs_reg_fops = {
+ .aio_read = generic_file_aio_read,
+ .aio_write = generic_file_aio_write,
+ .fsync = logfs_fsync,
+ .ioctl = logfs_ioctl,
+ .llseek = generic_file_llseek,
+ .mmap = generic_file_readonly_mmap,
+ .open = generic_file_open,
+ .read = do_sync_read,
+ .write = do_sync_write,
+};
+
+const struct address_space_operations logfs_reg_aops = {
+ .invalidatepage = logfs_invalidatepage,
+ .readpage = logfs_readpage,
+ .releasepage = logfs_releasepage,
+ .set_page_dirty = __set_page_dirty_nobuffers,
+ .writepage = logfs_writepage,
+ .writepages = generic_writepages,
+ .write_begin = logfs_write_begin,
+ .write_end = logfs_write_end,
+};
diff --git a/fs/logfs/gc.c b/fs/logfs/gc.c
new file mode 100644
index 00000000000..92949f95a90
--- /dev/null
+++ b/fs/logfs/gc.c
@@ -0,0 +1,730 @@
+/*
+ * fs/logfs/gc.c - garbage collection code
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ */
+#include "logfs.h"
+#include <linux/sched.h>
+
+/*
+ * Wear leveling needs to kick in when the difference between low erase
+ * counts and high erase counts gets too big. A good value for "too big"
+ * may be somewhat below 10% of maximum erase count for the device.
+ * Why not 397, to pick a nice round number with no specific meaning? :)
+ *
+ * WL_RATELIMIT is the minimum time between two wear level events. A huge
+ * number of segments may fulfil the requirements for wear leveling at the
+ * same time. If that happens we don't want to cause a latency from hell,
+ * but just gently pick one segment every so often and minimize overhead.
+ */
+#define WL_DELTA 397
+#define WL_RATELIMIT 100
+#define MAX_OBJ_ALIASES 2600
+#define SCAN_RATIO 512 /* number of scanned segments per gc'd segment */
+#define LIST_SIZE 64 /* base size of candidate lists */
+#define SCAN_ROUNDS 128 /* maximum number of complete medium scans */
+#define SCAN_ROUNDS_HIGH 4 /* maximum number of higher-level scans */
+
+static int no_free_segments(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+
+ return super->s_free_list.count;
+}
+
+/* journal has distance -1, top-most ifile layer distance 0 */
+static u8 root_distance(struct super_block *sb, gc_level_t __gc_level)
+{
+ struct logfs_super *super = logfs_super(sb);
+ u8 gc_level = (__force u8)__gc_level;
+
+ switch (gc_level) {
+ case 0: /* fall through */
+ case 1: /* fall through */
+ case 2: /* fall through */
+ case 3:
+ /* file data or indirect blocks */
+ return super->s_ifile_levels + super->s_iblock_levels - gc_level;
+ case 6: /* fall through */
+ case 7: /* fall through */
+ case 8: /* fall through */
+ case 9:
+ /* inode file data or indirect blocks */
+ return super->s_ifile_levels - (gc_level - 6);
+ default:
+ printk(KERN_ERR"LOGFS: segment of unknown level %x found\n",
+ gc_level);
+ WARN_ON(1);
+ return super->s_ifile_levels + super->s_iblock_levels;
+ }
+}
+
+static int segment_is_reserved(struct super_block *sb, u32 segno)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_area *area;
+ void *reserved;
+ int i;
+
+ /* Some segments are reserved. Just pretend they were all valid */
+ reserved = btree_lookup32(&super->s_reserved_segments, segno);
+ if (reserved)
+ return 1;
+
+ /* Currently open segments */
+ for_each_area(i) {
+ area = super->s_area[i];
+ if (area->a_is_open && area->a_segno == segno)
+ return 1;
+ }
+
+ return 0;
+}
+
+static void logfs_mark_segment_bad(struct super_block *sb, u32 segno)
+{
+ BUG();
+}
+
+/*
+ * Returns the bytes consumed by valid objects in this segment. Object headers
+ * are counted, the segment header is not.
+ */
+static u32 logfs_valid_bytes(struct super_block *sb, u32 segno, u32 *ec,
+ gc_level_t *gc_level)
+{
+ struct logfs_segment_entry se;
+ u32 ec_level;
+
+ logfs_get_segment_entry(sb, segno, &se);
+ if (se.ec_level == cpu_to_be32(BADSEG) ||
+ se.valid == cpu_to_be32(RESERVED))
+ return RESERVED;
+
+ ec_level = be32_to_cpu(se.ec_level);
+ *ec = ec_level >> 4;
+ *gc_level = GC_LEVEL(ec_level & 0xf);
+ return be32_to_cpu(se.valid);
+}
+
+static void logfs_cleanse_block(struct super_block *sb, u64 ofs, u64 ino,
+ u64 bix, gc_level_t gc_level)
+{
+ struct inode *inode;
+ int err, cookie;
+
+ inode = logfs_safe_iget(sb, ino, &cookie);
+ err = logfs_rewrite_block(inode, bix, ofs, gc_level, 0);
+ BUG_ON(err);
+ logfs_safe_iput(inode, cookie);
+}
+
+static u32 logfs_gc_segment(struct super_block *sb, u32 segno, u8 dist)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_segment_header sh;
+ struct logfs_object_header oh;
+ u64 ofs, ino, bix;
+ u32 seg_ofs, logical_segno, cleaned = 0;
+ int err, len, valid;
+ gc_level_t gc_level;
+
+ LOGFS_BUG_ON(segment_is_reserved(sb, segno), sb);
+
+ btree_insert32(&super->s_reserved_segments, segno, (void *)1, GFP_NOFS);
+ err = wbuf_read(sb, dev_ofs(sb, segno, 0), sizeof(sh), &sh);
+ BUG_ON(err);
+ gc_level = GC_LEVEL(sh.level);
+ logical_segno = be32_to_cpu(sh.segno);
+ if (sh.crc != logfs_crc32(&sh, sizeof(sh), 4)) {
+ logfs_mark_segment_bad(sb, segno);
+ cleaned = -1;
+ goto out;
+ }
+
+ for (seg_ofs = LOGFS_SEGMENT_HEADERSIZE;
+ seg_ofs + sizeof(oh) < super->s_segsize; ) {
+ ofs = dev_ofs(sb, logical_segno, seg_ofs);
+ err = wbuf_read(sb, dev_ofs(sb, segno, seg_ofs), sizeof(oh),
+ &oh);
+ BUG_ON(err);
+
+ if (!memchr_inv(&oh, 0xff, sizeof(oh)))
+ break;
+
+ if (oh.crc != logfs_crc32(&oh, sizeof(oh) - 4, 4)) {
+ logfs_mark_segment_bad(sb, segno);
+ cleaned = super->s_segsize - 1;
+ goto out;
+ }
+
+ ino = be64_to_cpu(oh.ino);
+ bix = be64_to_cpu(oh.bix);
+ len = sizeof(oh) + be16_to_cpu(oh.len);
+ valid = logfs_is_valid_block(sb, ofs, ino, bix, gc_level);
+ if (valid == 1) {
+ logfs_cleanse_block(sb, ofs, ino, bix, gc_level);
+ cleaned += len;
+ } else if (valid == 2) {
+ /* Will be invalid upon journal commit */
+ cleaned += len;
+ }
+ seg_ofs += len;
+ }
+out:
+ btree_remove32(&super->s_reserved_segments, segno);
+ return cleaned;
+}
+
+static struct gc_candidate *add_list(struct gc_candidate *cand,
+ struct candidate_list *list)
+{
+ struct rb_node **p = &list->rb_tree.rb_node;
+ struct rb_node *parent = NULL;
+ struct gc_candidate *cur;
+ int comp;
+
+ cand->list = list;
+ while (*p) {
+ parent = *p;
+ cur = rb_entry(parent, struct gc_candidate, rb_node);
+
+ if (list->sort_by_ec)
+ comp = cand->erase_count < cur->erase_count;
+ else
+ comp = cand->valid < cur->valid;
+
+ if (comp)
+ p = &parent->rb_left;
+ else
+ p = &parent->rb_right;
+ }
+ rb_link_node(&cand->rb_node, parent, p);
+ rb_insert_color(&cand->rb_node, &list->rb_tree);
+
+ if (list->count <= list->maxcount) {
+ list->count++;
+ return NULL;
+ }
+ cand = rb_entry(rb_last(&list->rb_tree), struct gc_candidate, rb_node);
+ rb_erase(&cand->rb_node, &list->rb_tree);
+ cand->list = NULL;
+ return cand;
+}
+
+static void remove_from_list(struct gc_candidate *cand)
+{
+ struct candidate_list *list = cand->list;
+
+ rb_erase(&cand->rb_node, &list->rb_tree);
+ list->count--;
+}
+
+static void free_candidate(struct super_block *sb, struct gc_candidate *cand)
+{
+ struct logfs_super *super = logfs_super(sb);
+
+ btree_remove32(&super->s_cand_tree, cand->segno);
+ kfree(cand);
+}
+
+u32 get_best_cand(struct super_block *sb, struct candidate_list *list, u32 *ec)
+{
+ struct gc_candidate *cand;
+ u32 segno;
+
+ BUG_ON(list->count == 0);
+
+ cand = rb_entry(rb_first(&list->rb_tree), struct gc_candidate, rb_node);
+ remove_from_list(cand);
+ segno = cand->segno;
+ if (ec)
+ *ec = cand->erase_count;
+ free_candidate(sb, cand);
+ return segno;
+}
+
+/*
+ * We have several lists to manage segments with. The reserve_list is used to
+ * deal with bad blocks. We try to keep the best (lowest ec) segments on this
+ * list.
+ * The free_list contains free segments for normal usage. It usually gets the
+ * second pick after the reserve_list. But when the free_list is running short
+ * it is more important to keep the free_list full than to keep a reserve.
+ *
+ * Segments that are not free are put onto a per-level low_list. If we have
+ * to run garbage collection, we pick a candidate from there. All segments on
+ * those lists should have at least some free space so GC will make progress.
+ *
+ * And last we have the ec_list, which is used to pick segments for wear
+ * leveling.
+ *
+ * If all appropriate lists are full, we simply free the candidate and forget
+ * about that segment for a while. We have better candidates for each purpose.
+ */
+static void __add_candidate(struct super_block *sb, struct gc_candidate *cand)
+{
+ struct logfs_super *super = logfs_super(sb);
+ u32 full = super->s_segsize - LOGFS_SEGMENT_RESERVE;
+
+ if (cand->valid == 0) {
+ /* 100% free segments */
+ log_gc_noisy("add reserve segment %x (ec %x) at %llx\n",
+ cand->segno, cand->erase_count,
+ dev_ofs(sb, cand->segno, 0));
+ cand = add_list(cand, &super->s_reserve_list);
+ if (cand) {
+ log_gc_noisy("add free segment %x (ec %x) at %llx\n",
+ cand->segno, cand->erase_count,
+ dev_ofs(sb, cand->segno, 0));
+ cand = add_list(cand, &super->s_free_list);
+ }
+ } else {
+ /* good candidates for Garbage Collection */
+ if (cand->valid < full)
+ cand = add_list(cand, &super->s_low_list[cand->dist]);
+ /* good candidates for wear leveling,
+ * segments that were recently written get ignored */
+ if (cand)
+ cand = add_list(cand, &super->s_ec_list);
+ }
+ if (cand)
+ free_candidate(sb, cand);
+}
+
+static int add_candidate(struct super_block *sb, u32 segno, u32 valid, u32 ec,
+ u8 dist)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct gc_candidate *cand;
+
+ cand = kmalloc(sizeof(*cand), GFP_NOFS);
+ if (!cand)
+ return -ENOMEM;
+
+ cand->segno = segno;
+ cand->valid = valid;
+ cand->erase_count = ec;
+ cand->dist = dist;
+
+ btree_insert32(&super->s_cand_tree, segno, cand, GFP_NOFS);
+ __add_candidate(sb, cand);
+ return 0;
+}
+
+static void remove_segment_from_lists(struct super_block *sb, u32 segno)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct gc_candidate *cand;
+
+ cand = btree_lookup32(&super->s_cand_tree, segno);
+ if (cand) {
+ remove_from_list(cand);
+ free_candidate(sb, cand);
+ }
+}
+
+static void scan_segment(struct super_block *sb, u32 segno)
+{
+ u32 valid, ec = 0;
+ gc_level_t gc_level = 0;
+ u8 dist;
+
+ if (segment_is_reserved(sb, segno))
+ return;
+
+ remove_segment_from_lists(sb, segno);
+ valid = logfs_valid_bytes(sb, segno, &ec, &gc_level);
+ if (valid == RESERVED)
+ return;
+
+ dist = root_distance(sb, gc_level);
+ add_candidate(sb, segno, valid, ec, dist);
+}
+
+static struct gc_candidate *first_in_list(struct candidate_list *list)
+{
+ if (list->count == 0)
+ return NULL;
+ return rb_entry(rb_first(&list->rb_tree), struct gc_candidate, rb_node);
+}
+
+/*
+ * Find the best segment for garbage collection. Main criterion is
+ * the segment requiring the least effort to clean. Secondary
+ * criterion is to GC on the lowest level available.
+ *
+ * So we search the least effort segment on the lowest level first,
+ * then move up and pick another segment iff is requires significantly
+ * less effort. Hence the LOGFS_MAX_OBJECTSIZE in the comparison.
+ */
+static struct gc_candidate *get_candidate(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ int i, max_dist;
+ struct gc_candidate *cand = NULL, *this;
+
+ max_dist = min(no_free_segments(sb), LOGFS_NO_AREAS);
+
+ for (i = max_dist; i >= 0; i--) {
+ this = first_in_list(&super->s_low_list[i]);
+ if (!this)
+ continue;
+ if (!cand)
+ cand = this;
+ if (this->valid + LOGFS_MAX_OBJECTSIZE <= cand->valid)
+ cand = this;
+ }
+ return cand;
+}
+
+static int __logfs_gc_once(struct super_block *sb, struct gc_candidate *cand)
+{
+ struct logfs_super *super = logfs_super(sb);
+ gc_level_t gc_level;
+ u32 cleaned, valid, segno, ec;
+ u8 dist;
+
+ if (!cand) {
+ log_gc("GC attempted, but no candidate found\n");
+ return 0;
+ }
+
+ segno = cand->segno;
+ dist = cand->dist;
+ valid = logfs_valid_bytes(sb, segno, &ec, &gc_level);
+ free_candidate(sb, cand);
+ log_gc("GC segment #%02x at %llx, %x required, %x free, %x valid, %llx free\n",
+ segno, (u64)segno << super->s_segshift,
+ dist, no_free_segments(sb), valid,
+ super->s_free_bytes);
+ cleaned = logfs_gc_segment(sb, segno, dist);
+ log_gc("GC segment #%02x complete - now %x valid\n", segno,
+ valid - cleaned);
+ BUG_ON(cleaned != valid);
+ return 1;
+}
+
+static int logfs_gc_once(struct super_block *sb)
+{
+ struct gc_candidate *cand;
+
+ cand = get_candidate(sb);
+ if (cand)
+ remove_from_list(cand);
+ return __logfs_gc_once(sb, cand);
+}
+
+/* returns 1 if a wrap occurs, 0 otherwise */
+static int logfs_scan_some(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ u32 segno;
+ int i, ret = 0;
+
+ segno = super->s_sweeper;
+ for (i = SCAN_RATIO; i > 0; i--) {
+ segno++;
+ if (segno >= super->s_no_segs) {
+ segno = 0;
+ ret = 1;
+ /* Break out of the loop. We want to read a single
+ * block from the segment size on next invocation if
+ * SCAN_RATIO is set to match block size
+ */
+ break;
+ }
+
+ scan_segment(sb, segno);
+ }
+ super->s_sweeper = segno;
+ return ret;
+}
+
+/*
+ * In principle, this function should loop forever, looking for GC candidates
+ * and moving data. LogFS is designed in such a way that this loop is
+ * guaranteed to terminate.
+ *
+ * Limiting the loop to some iterations serves purely to catch cases when
+ * these guarantees have failed. An actual endless loop is an obvious bug
+ * and should be reported as such.
+ */
+static void __logfs_gc_pass(struct super_block *sb, int target)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_block *block;
+ int round, progress, last_progress = 0;
+
+ if (no_free_segments(sb) >= target &&
+ super->s_no_object_aliases < MAX_OBJ_ALIASES)
+ return;
+
+ log_gc("__logfs_gc_pass(%x)\n", target);
+ for (round = 0; round < SCAN_ROUNDS; ) {
+ if (no_free_segments(sb) >= target)
+ goto write_alias;
+
+ /* Sync in-memory state with on-medium state in case they
+ * diverged */
+ logfs_write_anchor(sb);
+ round += logfs_scan_some(sb);
+ if (no_free_segments(sb) >= target)
+ goto write_alias;
+ progress = logfs_gc_once(sb);
+ if (progress)
+ last_progress = round;
+ else if (round - last_progress > 2)
+ break;
+ continue;
+
+ /*
+ * The goto logic is nasty, I just don't know a better way to
+ * code it. GC is supposed to ensure two things:
+ * 1. Enough free segments are available.
+ * 2. The number of aliases is bounded.
+ * When 1. is achieved, we take a look at 2. and write back
+ * some alias-containing blocks, if necessary. However, after
+ * each such write we need to go back to 1., as writes can
+ * consume free segments.
+ */
+write_alias:
+ if (super->s_no_object_aliases < MAX_OBJ_ALIASES)
+ return;
+ if (list_empty(&super->s_object_alias)) {
+ /* All aliases are still in btree */
+ return;
+ }
+ log_gc("Write back one alias\n");
+ block = list_entry(super->s_object_alias.next,
+ struct logfs_block, alias_list);
+ block->ops->write_block(block);
+ /*
+ * To round off the nasty goto logic, we reset round here. It
+ * is a safety-net for GC not making any progress and limited
+ * to something reasonably small. If incremented it for every
+ * single alias, the loop could terminate rather quickly.
+ */
+ round = 0;
+ }
+ LOGFS_BUG(sb);
+}
+
+static int wl_ratelimit(struct super_block *sb, u64 *next_event)
+{
+ struct logfs_super *super = logfs_super(sb);
+
+ if (*next_event < super->s_gec) {
+ *next_event = super->s_gec + WL_RATELIMIT;
+ return 0;
+ }
+ return 1;
+}
+
+static void logfs_wl_pass(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct gc_candidate *wl_cand, *free_cand;
+
+ if (wl_ratelimit(sb, &super->s_wl_gec_ostore))
+ return;
+
+ wl_cand = first_in_list(&super->s_ec_list);
+ if (!wl_cand)
+ return;
+ free_cand = first_in_list(&super->s_free_list);
+ if (!free_cand)
+ return;
+
+ if (wl_cand->erase_count < free_cand->erase_count + WL_DELTA) {
+ remove_from_list(wl_cand);
+ __logfs_gc_once(sb, wl_cand);
+ }
+}
+
+/*
+ * The journal needs wear leveling as well. But moving the journal is an
+ * expensive operation so we try to avoid it as much as possible. And if we
+ * have to do it, we move the whole journal, not individual segments.
+ *
+ * Ratelimiting is not strictly necessary here, it mainly serves to avoid the
+ * calculations. First we check whether moving the journal would be a
+ * significant improvement. That means that a) the current journal segments
+ * have more wear than the future journal segments and b) the current journal
+ * segments have more wear than normal ostore segments.
+ * Rationale for b) is that we don't have to move the journal if it is aging
+ * less than the ostore, even if the reserve segments age even less (they are
+ * excluded from wear leveling, after all).
+ * Next we check that the superblocks have less wear than the journal. Since
+ * moving the journal requires writing the superblocks, we have to protect the
+ * superblocks even more than the journal.
+ *
+ * Also we double the acceptable wear difference, compared to ostore wear
+ * leveling. Journal data is read and rewritten rapidly, comparatively. So
+ * soft errors have much less time to accumulate and we allow the journal to
+ * be a bit worse than the ostore.
+ */
+static void logfs_journal_wl_pass(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct gc_candidate *cand;
+ u32 min_journal_ec = -1, max_reserve_ec = 0;
+ int i;
+
+ if (wl_ratelimit(sb, &super->s_wl_gec_journal))
+ return;
+
+ if (super->s_reserve_list.count < super->s_no_journal_segs) {
+ /* Reserve is not full enough to move complete journal */
+ return;
+ }
+
+ journal_for_each(i)
+ if (super->s_journal_seg[i])
+ min_journal_ec = min(min_journal_ec,
+ super->s_journal_ec[i]);
+ cand = rb_entry(rb_first(&super->s_free_list.rb_tree),
+ struct gc_candidate, rb_node);
+ max_reserve_ec = cand->erase_count;
+ for (i = 0; i < 2; i++) {
+ struct logfs_segment_entry se;
+ u32 segno = seg_no(sb, super->s_sb_ofs[i]);
+ u32 ec;
+
+ logfs_get_segment_entry(sb, segno, &se);
+ ec = be32_to_cpu(se.ec_level) >> 4;
+ max_reserve_ec = max(max_reserve_ec, ec);
+ }
+
+ if (min_journal_ec > max_reserve_ec + 2 * WL_DELTA) {
+ do_logfs_journal_wl_pass(sb);
+ }
+}
+
+void logfs_gc_pass(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+
+ //BUG_ON(mutex_trylock(&logfs_super(sb)->s_w_mutex));
+ /* Write journal before free space is getting saturated with dirty
+ * objects.
+ */
+ if (super->s_dirty_used_bytes + super->s_dirty_free_bytes
+ + LOGFS_MAX_OBJECTSIZE >= super->s_free_bytes)
+ logfs_write_anchor(sb);
+ __logfs_gc_pass(sb, super->s_total_levels);
+ logfs_wl_pass(sb);
+ logfs_journal_wl_pass(sb);
+}
+
+static int check_area(struct super_block *sb, int i)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_area *area = super->s_area[i];
+ struct logfs_object_header oh;
+ u32 segno = area->a_segno;
+ u32 ofs = area->a_used_bytes;
+ __be32 crc;
+ int err;
+
+ if (!area->a_is_open)
+ return 0;
+
+ for (ofs = area->a_used_bytes;
+ ofs <= super->s_segsize - sizeof(oh);
+ ofs += (u32)be16_to_cpu(oh.len) + sizeof(oh)) {
+ err = wbuf_read(sb, dev_ofs(sb, segno, ofs), sizeof(oh), &oh);
+ if (err)
+ return err;
+
+ if (!memchr_inv(&oh, 0xff, sizeof(oh)))
+ break;
+
+ crc = logfs_crc32(&oh, sizeof(oh) - 4, 4);
+ if (crc != oh.crc) {
+ printk(KERN_INFO "interrupted header at %llx\n",
+ dev_ofs(sb, segno, ofs));
+ return 0;
+ }
+ }
+ if (ofs != area->a_used_bytes) {
+ printk(KERN_INFO "%x bytes unaccounted data found at %llx\n",
+ ofs - area->a_used_bytes,
+ dev_ofs(sb, segno, area->a_used_bytes));
+ area->a_used_bytes = ofs;
+ }
+ return 0;
+}
+
+int logfs_check_areas(struct super_block *sb)
+{
+ int i, err;
+
+ for_each_area(i) {
+ err = check_area(sb, i);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+static void logfs_init_candlist(struct candidate_list *list, int maxcount,
+ int sort_by_ec)
+{
+ list->count = 0;
+ list->maxcount = maxcount;
+ list->sort_by_ec = sort_by_ec;
+ list->rb_tree = RB_ROOT;
+}
+
+int logfs_init_gc(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ int i;
+
+ btree_init_mempool32(&super->s_cand_tree, super->s_btree_pool);
+ logfs_init_candlist(&super->s_free_list, LIST_SIZE + SCAN_RATIO, 1);
+ logfs_init_candlist(&super->s_reserve_list,
+ super->s_bad_seg_reserve, 1);
+ for_each_area(i)
+ logfs_init_candlist(&super->s_low_list[i], LIST_SIZE, 0);
+ logfs_init_candlist(&super->s_ec_list, LIST_SIZE, 1);
+ return 0;
+}
+
+static void logfs_cleanup_list(struct super_block *sb,
+ struct candidate_list *list)
+{
+ struct gc_candidate *cand;
+
+ while (list->count) {
+ cand = rb_entry(list->rb_tree.rb_node, struct gc_candidate,
+ rb_node);
+ remove_from_list(cand);
+ free_candidate(sb, cand);
+ }
+ BUG_ON(list->rb_tree.rb_node);
+}
+
+void logfs_cleanup_gc(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ int i;
+
+ if (!super->s_free_list.count)
+ return;
+
+ /*
+ * FIXME: The btree may still contain a single empty node. So we
+ * call the grim visitor to clean up that mess. Btree code should
+ * do it for us, really.
+ */
+ btree_grim_visitor32(&super->s_cand_tree, 0, NULL);
+ logfs_cleanup_list(sb, &super->s_free_list);
+ logfs_cleanup_list(sb, &super->s_reserve_list);
+ for_each_area(i)
+ logfs_cleanup_list(sb, &super->s_low_list[i]);
+ logfs_cleanup_list(sb, &super->s_ec_list);
+}
diff --git a/fs/logfs/inode.c b/fs/logfs/inode.c
new file mode 100644
index 00000000000..33ec1aeaeec
--- /dev/null
+++ b/fs/logfs/inode.c
@@ -0,0 +1,417 @@
+/*
+ * fs/logfs/inode.c - inode handling code
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ */
+#include "logfs.h"
+#include <linux/writeback.h>
+#include <linux/backing-dev.h>
+
+/*
+ * How soon to reuse old inode numbers? LogFS doesn't store deleted inodes
+ * on the medium. It therefore also lacks a method to store the previous
+ * generation number for deleted inodes. Instead a single generation number
+ * is stored which will be used for new inodes. Being just a 32bit counter,
+ * this can obvious wrap relatively quickly. So we only reuse inodes if we
+ * know that a fair number of inodes can be created before we have to increment
+ * the generation again - effectively adding some bits to the counter.
+ * But being too aggressive here means we keep a very large and very sparse
+ * inode file, wasting space on indirect blocks.
+ * So what is a good value? Beats me. 64k seems moderately bad on both
+ * fronts, so let's use that for now...
+ *
+ * NFS sucks, as everyone already knows.
+ */
+#define INOS_PER_WRAP (0x10000)
+
+/*
+ * Logfs' requirement to read inodes for garbage collection makes life a bit
+ * harder. GC may have to read inodes that are in I_FREEING state, when they
+ * are being written out - and waiting for GC to make progress, naturally.
+ *
+ * So we cannot just call iget() or some variant of it, but first have to check
+ * wether the inode in question might be in I_FREEING state. Therefore we
+ * maintain our own per-sb list of "almost deleted" inodes and check against
+ * that list first. Normally this should be at most 1-2 entries long.
+ *
+ * Also, inodes have logfs-specific reference counting on top of what the vfs
+ * does. When .destroy_inode is called, normally the reference count will drop
+ * to zero and the inode gets deleted. But if GC accessed the inode, its
+ * refcount will remain nonzero and final deletion will have to wait.
+ *
+ * As a result we have two sets of functions to get/put inodes:
+ * logfs_safe_iget/logfs_safe_iput - safe to call from GC context
+ * logfs_iget/iput - normal version
+ */
+static struct kmem_cache *logfs_inode_cache;
+
+static DEFINE_SPINLOCK(logfs_inode_lock);
+
+static void logfs_inode_setops(struct inode *inode)
+{
+ switch (inode->i_mode & S_IFMT) {
+ case S_IFDIR:
+ inode->i_op = &logfs_dir_iops;
+ inode->i_fop = &logfs_dir_fops;
+ inode->i_mapping->a_ops = &logfs_reg_aops;
+ break;
+ case S_IFREG:
+ inode->i_op = &logfs_reg_iops;
+ inode->i_fop = &logfs_reg_fops;
+ inode->i_mapping->a_ops = &logfs_reg_aops;
+ break;
+ case S_IFLNK:
+ inode->i_op = &logfs_symlink_iops;
+ inode->i_mapping->a_ops = &logfs_reg_aops;
+ break;
+ case S_IFSOCK: /* fall through */
+ case S_IFBLK: /* fall through */
+ case S_IFCHR: /* fall through */
+ case S_IFIFO:
+ init_special_inode(inode, inode->i_mode, inode->i_rdev);
+ break;
+ default:
+ BUG();
+ }
+}
+
+static struct inode *__logfs_iget(struct super_block *sb, ino_t ino)
+{
+ struct inode *inode = iget_locked(sb, ino);
+ int err;
+
+ if (!inode)
+ return ERR_PTR(-ENOMEM);
+ if (!(inode->i_state & I_NEW))
+ return inode;
+
+ err = logfs_read_inode(inode);
+ if (err || inode->i_nlink == 0) {
+ /* inode->i_nlink == 0 can be true when called from
+ * block validator */
+ /* set i_nlink to 0 to prevent caching */
+ inode->i_nlink = 0;
+ logfs_inode(inode)->li_flags |= LOGFS_IF_ZOMBIE;
+ iget_failed(inode);
+ if (!err)
+ err = -ENOENT;
+ return ERR_PTR(err);
+ }
+
+ logfs_inode_setops(inode);
+ unlock_new_inode(inode);
+ return inode;
+}
+
+struct inode *logfs_iget(struct super_block *sb, ino_t ino)
+{
+ BUG_ON(ino == LOGFS_INO_MASTER);
+ BUG_ON(ino == LOGFS_INO_SEGFILE);
+ return __logfs_iget(sb, ino);
+}
+
+/*
+ * is_cached is set to 1 if we hand out a cached inode, 0 otherwise.
+ * this allows logfs_iput to do the right thing later
+ */
+struct inode *logfs_safe_iget(struct super_block *sb, ino_t ino, int *is_cached)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_inode *li;
+
+ if (ino == LOGFS_INO_MASTER)
+ return super->s_master_inode;
+ if (ino == LOGFS_INO_SEGFILE)
+ return super->s_segfile_inode;
+
+ spin_lock(&logfs_inode_lock);
+ list_for_each_entry(li, &super->s_freeing_list, li_freeing_list)
+ if (li->vfs_inode.i_ino == ino) {
+ li->li_refcount++;
+ spin_unlock(&logfs_inode_lock);
+ *is_cached = 1;
+ return &li->vfs_inode;
+ }
+ spin_unlock(&logfs_inode_lock);
+
+ *is_cached = 0;
+ return __logfs_iget(sb, ino);
+}
+
+static void __logfs_destroy_inode(struct inode *inode)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+
+ BUG_ON(li->li_block);
+ list_del(&li->li_freeing_list);
+ kmem_cache_free(logfs_inode_cache, li);
+}
+
+static void logfs_destroy_inode(struct inode *inode)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+
+ BUG_ON(list_empty(&li->li_freeing_list));
+ spin_lock(&logfs_inode_lock);
+ li->li_refcount--;
+ if (li->li_refcount == 0)
+ __logfs_destroy_inode(inode);
+ spin_unlock(&logfs_inode_lock);
+}
+
+void logfs_safe_iput(struct inode *inode, int is_cached)
+{
+ if (inode->i_ino == LOGFS_INO_MASTER)
+ return;
+ if (inode->i_ino == LOGFS_INO_SEGFILE)
+ return;
+
+ if (is_cached) {
+ logfs_destroy_inode(inode);
+ return;
+ }
+
+ iput(inode);
+}
+
+static void logfs_init_inode(struct super_block *sb, struct inode *inode)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+ int i;
+
+ li->li_flags = 0;
+ li->li_height = 0;
+ li->li_used_bytes = 0;
+ li->li_block = NULL;
+ inode->i_uid = 0;
+ inode->i_gid = 0;
+ inode->i_size = 0;
+ inode->i_blocks = 0;
+ inode->i_ctime = CURRENT_TIME;
+ inode->i_mtime = CURRENT_TIME;
+ inode->i_nlink = 1;
+ INIT_LIST_HEAD(&li->li_freeing_list);
+
+ for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++)
+ li->li_data[i] = 0;
+
+ return;
+}
+
+static struct inode *logfs_alloc_inode(struct super_block *sb)
+{
+ struct logfs_inode *li;
+
+ li = kmem_cache_alloc(logfs_inode_cache, GFP_NOFS);
+ if (!li)
+ return NULL;
+ logfs_init_inode(sb, &li->vfs_inode);
+ return &li->vfs_inode;
+}
+
+/*
+ * In logfs inodes are written to an inode file. The inode file, like any
+ * other file, is managed with a inode. The inode file's inode, aka master
+ * inode, requires special handling in several respects. First, it cannot be
+ * written to the inode file, so it is stored in the journal instead.
+ *
+ * Secondly, this inode cannot be written back and destroyed before all other
+ * inodes have been written. The ordering is important. Linux' VFS is happily
+ * unaware of the ordering constraint and would ordinarily destroy the master
+ * inode at umount time while other inodes are still in use and dirty. Not
+ * good.
+ *
+ * So logfs makes sure the master inode is not written until all other inodes
+ * have been destroyed. Sadly, this method has another side-effect. The VFS
+ * will notice one remaining inode and print a frightening warning message.
+ * Worse, it is impossible to judge whether such a warning was caused by the
+ * master inode or any other inodes have leaked as well.
+ *
+ * Our attempt of solving this is with logfs_new_meta_inode() below. Its
+ * purpose is to create a new inode that will not trigger the warning if such
+ * an inode is still in use. An ugly hack, no doubt. Suggections for
+ * improvement are welcome.
+ */
+struct inode *logfs_new_meta_inode(struct super_block *sb, u64 ino)
+{
+ struct inode *inode;
+
+ inode = logfs_alloc_inode(sb);
+ if (!inode)
+ return ERR_PTR(-ENOMEM);
+
+ inode->i_mode = S_IFREG;
+ inode->i_ino = ino;
+ inode->i_sb = sb;
+
+ /* This is a blatant copy of alloc_inode code. We'd need alloc_inode
+ * to be nonstatic, alas. */
+ {
+ struct address_space * const mapping = &inode->i_data;
+
+ mapping->a_ops = &logfs_reg_aops;
+ mapping->host = inode;
+ mapping->flags = 0;
+ mapping_set_gfp_mask(mapping, GFP_NOFS);
+ mapping->assoc_mapping = NULL;
+ mapping->backing_dev_info = &default_backing_dev_info;
+ inode->i_mapping = mapping;
+ inode->i_nlink = 1;
+ }
+
+ return inode;
+}
+
+struct inode *logfs_read_meta_inode(struct super_block *sb, u64 ino)
+{
+ struct inode *inode;
+ int err;
+
+ inode = logfs_new_meta_inode(sb, ino);
+ if (IS_ERR(inode))
+ return inode;
+
+ err = logfs_read_inode(inode);
+ if (err) {
+ destroy_meta_inode(inode);
+ return ERR_PTR(err);
+ }
+ logfs_inode_setops(inode);
+ return inode;
+}
+
+static int logfs_write_inode(struct inode *inode, struct writeback_control *wbc)
+{
+ int ret;
+ long flags = WF_LOCK;
+
+ /* Can only happen if creat() failed. Safe to skip. */
+ if (logfs_inode(inode)->li_flags & LOGFS_IF_STILLBORN)
+ return 0;
+
+ ret = __logfs_write_inode(inode, flags);
+ LOGFS_BUG_ON(ret, inode->i_sb);
+ return ret;
+}
+
+void destroy_meta_inode(struct inode *inode)
+{
+ if (inode) {
+ if (inode->i_data.nrpages)
+ truncate_inode_pages(&inode->i_data, 0);
+ logfs_clear_inode(inode);
+ kmem_cache_free(logfs_inode_cache, logfs_inode(inode));
+ }
+}
+
+/* called with inode_lock held */
+static void logfs_drop_inode(struct inode *inode)
+{
+ struct logfs_super *super = logfs_super(inode->i_sb);
+ struct logfs_inode *li = logfs_inode(inode);
+
+ spin_lock(&logfs_inode_lock);
+ list_move(&li->li_freeing_list, &super->s_freeing_list);
+ spin_unlock(&logfs_inode_lock);
+ generic_drop_inode(inode);
+}
+
+static void logfs_set_ino_generation(struct super_block *sb,
+ struct inode *inode)
+{
+ struct logfs_super *super = logfs_super(sb);
+ u64 ino;
+
+ mutex_lock(&super->s_journal_mutex);
+ ino = logfs_seek_hole(super->s_master_inode, super->s_last_ino);
+ super->s_last_ino = ino;
+ super->s_inos_till_wrap--;
+ if (super->s_inos_till_wrap < 0) {
+ super->s_last_ino = LOGFS_RESERVED_INOS;
+ super->s_generation++;
+ super->s_inos_till_wrap = INOS_PER_WRAP;
+ }
+ inode->i_ino = ino;
+ inode->i_generation = super->s_generation;
+ mutex_unlock(&super->s_journal_mutex);
+}
+
+struct inode *logfs_new_inode(struct inode *dir, int mode)
+{
+ struct super_block *sb = dir->i_sb;
+ struct inode *inode;
+
+ inode = new_inode(sb);
+ if (!inode)
+ return ERR_PTR(-ENOMEM);
+
+ logfs_init_inode(sb, inode);
+
+ /* inherit parent flags */
+ logfs_inode(inode)->li_flags |=
+ logfs_inode(dir)->li_flags & LOGFS_FL_INHERITED;
+
+ inode->i_mode = mode;
+ logfs_set_ino_generation(sb, inode);
+
+ inode->i_uid = current_fsuid();
+ inode->i_gid = current_fsgid();
+ if (dir->i_mode & S_ISGID) {
+ inode->i_gid = dir->i_gid;
+ if (S_ISDIR(mode))
+ inode->i_mode |= S_ISGID;
+ }
+
+ logfs_inode_setops(inode);
+ insert_inode_hash(inode);
+
+ return inode;
+}
+
+static void logfs_init_once(void *_li)
+{
+ struct logfs_inode *li = _li;
+ int i;
+
+ li->li_flags = 0;
+ li->li_used_bytes = 0;
+ li->li_refcount = 1;
+ for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++)
+ li->li_data[i] = 0;
+ inode_init_once(&li->vfs_inode);
+}
+
+static int logfs_sync_fs(struct super_block *sb, int wait)
+{
+ /* FIXME: write anchor */
+ logfs_super(sb)->s_devops->sync(sb);
+ return 0;
+}
+
+const struct super_operations logfs_super_operations = {
+ .alloc_inode = logfs_alloc_inode,
+ .clear_inode = logfs_clear_inode,
+ .delete_inode = logfs_delete_inode,
+ .destroy_inode = logfs_destroy_inode,
+ .drop_inode = logfs_drop_inode,
+ .write_inode = logfs_write_inode,
+ .statfs = logfs_statfs,
+ .sync_fs = logfs_sync_fs,
+};
+
+int logfs_init_inode_cache(void)
+{
+ logfs_inode_cache = kmem_cache_create("logfs_inode_cache",
+ sizeof(struct logfs_inode), 0, SLAB_RECLAIM_ACCOUNT,
+ logfs_init_once);
+ if (!logfs_inode_cache)
+ return -ENOMEM;
+ return 0;
+}
+
+void logfs_destroy_inode_cache(void)
+{
+ kmem_cache_destroy(logfs_inode_cache);
+}
diff --git a/fs/logfs/journal.c b/fs/logfs/journal.c
new file mode 100644
index 00000000000..6ad30a4c905
--- /dev/null
+++ b/fs/logfs/journal.c
@@ -0,0 +1,883 @@
+/*
+ * fs/logfs/journal.c - journal handling code
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ */
+#include "logfs.h"
+
+static void logfs_calc_free(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ u64 reserve, no_segs = super->s_no_segs;
+ s64 free;
+ int i;
+
+ /* superblock segments */
+ no_segs -= 2;
+ super->s_no_journal_segs = 0;
+ /* journal */
+ journal_for_each(i)
+ if (super->s_journal_seg[i]) {
+ no_segs--;
+ super->s_no_journal_segs++;
+ }
+
+ /* open segments plus one extra per level for GC */
+ no_segs -= 2 * super->s_total_levels;
+
+ free = no_segs * (super->s_segsize - LOGFS_SEGMENT_RESERVE);
+ free -= super->s_used_bytes;
+ /* just a bit extra */
+ free -= super->s_total_levels * 4096;
+
+ /* Bad blocks are 'paid' for with speed reserve - the filesystem
+ * simply gets slower as bad blocks accumulate. Until the bad blocks
+ * exceed the speed reserve - then the filesystem gets smaller.
+ */
+ reserve = super->s_bad_segments + super->s_bad_seg_reserve;
+ reserve *= super->s_segsize - LOGFS_SEGMENT_RESERVE;
+ reserve = max(reserve, super->s_speed_reserve);
+ free -= reserve;
+ if (free < 0)
+ free = 0;
+
+ super->s_free_bytes = free;
+}
+
+static void reserve_sb_and_journal(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct btree_head32 *head = &super->s_reserved_segments;
+ int i, err;
+
+ err = btree_insert32(head, seg_no(sb, super->s_sb_ofs[0]), (void *)1,
+ GFP_KERNEL);
+ BUG_ON(err);
+
+ err = btree_insert32(head, seg_no(sb, super->s_sb_ofs[1]), (void *)1,
+ GFP_KERNEL);
+ BUG_ON(err);
+
+ journal_for_each(i) {
+ if (!super->s_journal_seg[i])
+ continue;
+ err = btree_insert32(head, super->s_journal_seg[i], (void *)1,
+ GFP_KERNEL);
+ BUG_ON(err);
+ }
+}
+
+static void read_dynsb(struct super_block *sb,
+ struct logfs_je_dynsb *dynsb)
+{
+ struct logfs_super *super = logfs_super(sb);
+
+ super->s_gec = be64_to_cpu(dynsb->ds_gec);
+ super->s_sweeper = be64_to_cpu(dynsb->ds_sweeper);
+ super->s_victim_ino = be64_to_cpu(dynsb->ds_victim_ino);
+ super->s_rename_dir = be64_to_cpu(dynsb->ds_rename_dir);
+ super->s_rename_pos = be64_to_cpu(dynsb->ds_rename_pos);
+ super->s_used_bytes = be64_to_cpu(dynsb->ds_used_bytes);
+ super->s_generation = be32_to_cpu(dynsb->ds_generation);
+}
+
+static void read_anchor(struct super_block *sb,
+ struct logfs_je_anchor *da)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct inode *inode = super->s_master_inode;
+ struct logfs_inode *li = logfs_inode(inode);
+ int i;
+
+ super->s_last_ino = be64_to_cpu(da->da_last_ino);
+ li->li_flags = 0;
+ li->li_height = da->da_height;
+ i_size_write(inode, be64_to_cpu(da->da_size));
+ li->li_used_bytes = be64_to_cpu(da->da_used_bytes);
+
+ for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++)
+ li->li_data[i] = be64_to_cpu(da->da_data[i]);
+}
+
+static void read_erasecount(struct super_block *sb,
+ struct logfs_je_journal_ec *ec)
+{
+ struct logfs_super *super = logfs_super(sb);
+ int i;
+
+ journal_for_each(i)
+ super->s_journal_ec[i] = be32_to_cpu(ec->ec[i]);
+}
+
+static int read_area(struct super_block *sb, struct logfs_je_area *a)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_area *area = super->s_area[a->gc_level];
+ u64 ofs;
+ u32 writemask = ~(super->s_writesize - 1);
+
+ if (a->gc_level >= LOGFS_NO_AREAS)
+ return -EIO;
+ if (a->vim != VIM_DEFAULT)
+ return -EIO; /* TODO: close area and continue */
+
+ area->a_used_bytes = be32_to_cpu(a->used_bytes);
+ area->a_written_bytes = area->a_used_bytes & writemask;
+ area->a_segno = be32_to_cpu(a->segno);
+ if (area->a_segno)
+ area->a_is_open = 1;
+
+ ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes);
+ if (super->s_writesize > 1)
+ logfs_buf_recover(area, ofs, a + 1, super->s_writesize);
+ else
+ logfs_buf_recover(area, ofs, NULL, 0);
+ return 0;
+}
+
+static void *unpack(void *from, void *to)
+{
+ struct logfs_journal_header *jh = from;
+ void *data = from + sizeof(struct logfs_journal_header);
+ int err;
+ size_t inlen, outlen;
+
+ inlen = be16_to_cpu(jh->h_len);
+ outlen = be16_to_cpu(jh->h_datalen);
+
+ if (jh->h_compr == COMPR_NONE)
+ memcpy(to, data, inlen);
+ else {
+ err = logfs_uncompress(data, to, inlen, outlen);
+ BUG_ON(err);
+ }
+ return to;
+}
+
+static int __read_je_header(struct super_block *sb, u64 ofs,
+ struct logfs_journal_header *jh)
+{
+ struct logfs_super *super = logfs_super(sb);
+ size_t bufsize = max_t(size_t, sb->s_blocksize, super->s_writesize)
+ + MAX_JOURNAL_HEADER;
+ u16 type, len, datalen;
+ int err;
+
+ /* read header only */
+ err = wbuf_read(sb, ofs, sizeof(*jh), jh);
+ if (err)
+ return err;
+ type = be16_to_cpu(jh->h_type);
+ len = be16_to_cpu(jh->h_len);
+ datalen = be16_to_cpu(jh->h_datalen);
+ if (len > sb->s_blocksize)
+ return -EIO;
+ if ((type < JE_FIRST) || (type > JE_LAST))
+ return -EIO;
+ if (datalen > bufsize)
+ return -EIO;
+ return 0;
+}
+
+static int __read_je_payload(struct super_block *sb, u64 ofs,
+ struct logfs_journal_header *jh)
+{
+ u16 len;
+ int err;
+
+ len = be16_to_cpu(jh->h_len);
+ err = wbuf_read(sb, ofs + sizeof(*jh), len, jh + 1);
+ if (err)
+ return err;
+ if (jh->h_crc != logfs_crc32(jh, len + sizeof(*jh), 4)) {
+ /* Old code was confused. It forgot about the header length
+ * and stopped calculating the crc 16 bytes before the end
+ * of data - ick!
+ * FIXME: Remove this hack once the old code is fixed.
+ */
+ if (jh->h_crc == logfs_crc32(jh, len, 4))
+ WARN_ON_ONCE(1);
+ else
+ return -EIO;
+ }
+ return 0;
+}
+
+/*
+ * jh needs to be large enough to hold the complete entry, not just the header
+ */
+static int __read_je(struct super_block *sb, u64 ofs,
+ struct logfs_journal_header *jh)
+{
+ int err;
+
+ err = __read_je_header(sb, ofs, jh);
+ if (err)
+ return err;
+ return __read_je_payload(sb, ofs, jh);
+}
+
+static int read_je(struct super_block *sb, u64 ofs)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_journal_header *jh = super->s_compressed_je;
+ void *scratch = super->s_je;
+ u16 type, datalen;
+ int err;
+
+ err = __read_je(sb, ofs, jh);
+ if (err)
+ return err;
+ type = be16_to_cpu(jh->h_type);
+ datalen = be16_to_cpu(jh->h_datalen);
+
+ switch (type) {
+ case JE_DYNSB:
+ read_dynsb(sb, unpack(jh, scratch));
+ break;
+ case JE_ANCHOR:
+ read_anchor(sb, unpack(jh, scratch));
+ break;
+ case JE_ERASECOUNT:
+ read_erasecount(sb, unpack(jh, scratch));
+ break;
+ case JE_AREA:
+ read_area(sb, unpack(jh, scratch));
+ break;
+ case JE_OBJ_ALIAS:
+ err = logfs_load_object_aliases(sb, unpack(jh, scratch),
+ datalen);
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ return -EIO;
+ }
+ return err;
+}
+
+static int logfs_read_segment(struct super_block *sb, u32 segno)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_journal_header *jh = super->s_compressed_je;
+ u64 ofs, seg_ofs = dev_ofs(sb, segno, 0);
+ u32 h_ofs, last_ofs = 0;
+ u16 len, datalen, last_len = 0;
+ int i, err;
+
+ /* search for most recent commit */
+ for (h_ofs = 0; h_ofs < super->s_segsize; h_ofs += sizeof(*jh)) {
+ ofs = seg_ofs + h_ofs;
+ err = __read_je_header(sb, ofs, jh);
+ if (err)
+ continue;
+ if (jh->h_type != cpu_to_be16(JE_COMMIT))
+ continue;
+ err = __read_je_payload(sb, ofs, jh);
+ if (err)
+ continue;
+ len = be16_to_cpu(jh->h_len);
+ datalen = be16_to_cpu(jh->h_datalen);
+ if ((datalen > sizeof(super->s_je_array)) ||
+ (datalen % sizeof(__be64)))
+ continue;
+ last_ofs = h_ofs;
+ last_len = datalen;
+ h_ofs += ALIGN(len, sizeof(*jh)) - sizeof(*jh);
+ }
+ /* read commit */
+ if (last_ofs == 0)
+ return -ENOENT;
+ ofs = seg_ofs + last_ofs;
+ log_journal("Read commit from %llx\n", ofs);
+ err = __read_je(sb, ofs, jh);
+ BUG_ON(err); /* We should have caught it in the scan loop already */
+ if (err)
+ return err;
+ /* uncompress */
+ unpack(jh, super->s_je_array);
+ super->s_no_je = last_len / sizeof(__be64);
+ /* iterate over array */
+ for (i = 0; i < super->s_no_je; i++) {
+ err = read_je(sb, be64_to_cpu(super->s_je_array[i]));
+ if (err)
+ return err;
+ }
+ super->s_journal_area->a_segno = segno;
+ return 0;
+}
+
+static u64 read_gec(struct super_block *sb, u32 segno)
+{
+ struct logfs_segment_header sh;
+ __be32 crc;
+ int err;
+
+ if (!segno)
+ return 0;
+ err = wbuf_read(sb, dev_ofs(sb, segno, 0), sizeof(sh), &sh);
+ if (err)
+ return 0;
+ crc = logfs_crc32(&sh, sizeof(sh), 4);
+ if (crc != sh.crc) {
+ WARN_ON(sh.gec != cpu_to_be64(0xffffffffffffffffull));
+ /* Most likely it was just erased */
+ return 0;
+ }
+ return be64_to_cpu(sh.gec);
+}
+
+static int logfs_read_journal(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ u64 gec[LOGFS_JOURNAL_SEGS], max;
+ u32 segno;
+ int i, max_i;
+
+ max = 0;
+ max_i = -1;
+ journal_for_each(i) {
+ segno = super->s_journal_seg[i];
+ gec[i] = read_gec(sb, super->s_journal_seg[i]);
+ if (gec[i] > max) {
+ max = gec[i];
+ max_i = i;
+ }
+ }
+ if (max_i == -1)
+ return -EIO;
+ /* FIXME: Try older segments in case of error */
+ return logfs_read_segment(sb, super->s_journal_seg[max_i]);
+}
+
+/*
+ * First search the current segment (outer loop), then pick the next segment
+ * in the array, skipping any zero entries (inner loop).
+ */
+static void journal_get_free_segment(struct logfs_area *area)
+{
+ struct logfs_super *super = logfs_super(area->a_sb);
+ int i;
+
+ journal_for_each(i) {
+ if (area->a_segno != super->s_journal_seg[i])
+ continue;
+
+ do {
+ i++;
+ if (i == LOGFS_JOURNAL_SEGS)
+ i = 0;
+ } while (!super->s_journal_seg[i]);
+
+ area->a_segno = super->s_journal_seg[i];
+ area->a_erase_count = ++(super->s_journal_ec[i]);
+ log_journal("Journal now at %x (ec %x)\n", area->a_segno,
+ area->a_erase_count);
+ return;
+ }
+ BUG();
+}
+
+static void journal_get_erase_count(struct logfs_area *area)
+{
+ /* erase count is stored globally and incremented in
+ * journal_get_free_segment() - nothing to do here */
+}
+
+static int journal_erase_segment(struct logfs_area *area)
+{
+ struct super_block *sb = area->a_sb;
+ struct logfs_segment_header sh;
+ u64 ofs;
+ int err;
+
+ err = logfs_erase_segment(sb, area->a_segno, 1);
+ if (err)
+ return err;
+
+ sh.pad = 0;
+ sh.type = SEG_JOURNAL;
+ sh.level = 0;
+ sh.segno = cpu_to_be32(area->a_segno);
+ sh.ec = cpu_to_be32(area->a_erase_count);
+ sh.gec = cpu_to_be64(logfs_super(sb)->s_gec);
+ sh.crc = logfs_crc32(&sh, sizeof(sh), 4);
+
+ /* This causes a bug in segment.c. Not yet. */
+ //logfs_set_segment_erased(sb, area->a_segno, area->a_erase_count, 0);
+
+ ofs = dev_ofs(sb, area->a_segno, 0);
+ area->a_used_bytes = ALIGN(sizeof(sh), 16);
+ logfs_buf_write(area, ofs, &sh, sizeof(sh));
+ return 0;
+}
+
+static size_t __logfs_write_header(struct logfs_super *super,
+ struct logfs_journal_header *jh, size_t len, size_t datalen,
+ u16 type, u8 compr)
+{
+ jh->h_len = cpu_to_be16(len);
+ jh->h_type = cpu_to_be16(type);
+ jh->h_datalen = cpu_to_be16(datalen);
+ jh->h_compr = compr;
+ jh->h_pad[0] = 'H';
+ jh->h_pad[1] = 'E';
+ jh->h_pad[2] = 'A';
+ jh->h_pad[3] = 'D';
+ jh->h_pad[4] = 'R';
+ jh->h_crc = logfs_crc32(jh, len + sizeof(*jh), 4);
+ return ALIGN(len, 16) + sizeof(*jh);
+}
+
+static size_t logfs_write_header(struct logfs_super *super,
+ struct logfs_journal_header *jh, size_t datalen, u16 type)
+{
+ size_t len = datalen;
+
+ return __logfs_write_header(super, jh, len, datalen, type, COMPR_NONE);
+}
+
+static inline size_t logfs_journal_erasecount_size(struct logfs_super *super)
+{
+ return LOGFS_JOURNAL_SEGS * sizeof(__be32);
+}
+
+static void *logfs_write_erasecount(struct super_block *sb, void *_ec,
+ u16 *type, size_t *len)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_je_journal_ec *ec = _ec;
+ int i;
+
+ journal_for_each(i)
+ ec->ec[i] = cpu_to_be32(super->s_journal_ec[i]);
+ *type = JE_ERASECOUNT;
+ *len = logfs_journal_erasecount_size(super);
+ return ec;
+}
+
+static void account_shadow(void *_shadow, unsigned long _sb, u64 ignore,
+ size_t ignore2)
+{
+ struct logfs_shadow *shadow = _shadow;
+ struct super_block *sb = (void *)_sb;
+ struct logfs_super *super = logfs_super(sb);
+
+ /* consume new space */
+ super->s_free_bytes -= shadow->new_len;
+ super->s_used_bytes += shadow->new_len;
+ super->s_dirty_used_bytes -= shadow->new_len;
+
+ /* free up old space */
+ super->s_free_bytes += shadow->old_len;
+ super->s_used_bytes -= shadow->old_len;
+ super->s_dirty_free_bytes -= shadow->old_len;
+
+ logfs_set_segment_used(sb, shadow->old_ofs, -shadow->old_len);
+ logfs_set_segment_used(sb, shadow->new_ofs, shadow->new_len);
+
+ log_journal("account_shadow(%llx, %llx, %x) %llx->%llx %x->%x\n",
+ shadow->ino, shadow->bix, shadow->gc_level,
+ shadow->old_ofs, shadow->new_ofs,
+ shadow->old_len, shadow->new_len);
+ mempool_free(shadow, super->s_shadow_pool);
+}
+
+static void account_shadows(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct inode *inode = super->s_master_inode;
+ struct logfs_inode *li = logfs_inode(inode);
+ struct shadow_tree *tree = &super->s_shadow_tree;
+
+ btree_grim_visitor64(&tree->new, (unsigned long)sb, account_shadow);
+ btree_grim_visitor64(&tree->old, (unsigned long)sb, account_shadow);
+
+ if (li->li_block) {
+ /*
+ * We never actually use the structure, when attached to the
+ * master inode. But it is easier to always free it here than
+ * to have checks in several places elsewhere when allocating
+ * it.
+ */
+ li->li_block->ops->free_block(sb, li->li_block);
+ }
+ BUG_ON((s64)li->li_used_bytes < 0);
+}
+
+static void *__logfs_write_anchor(struct super_block *sb, void *_da,
+ u16 *type, size_t *len)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_je_anchor *da = _da;
+ struct inode *inode = super->s_master_inode;
+ struct logfs_inode *li = logfs_inode(inode);
+ int i;
+
+ da->da_height = li->li_height;
+ da->da_last_ino = cpu_to_be64(super->s_last_ino);
+ da->da_size = cpu_to_be64(i_size_read(inode));
+ da->da_used_bytes = cpu_to_be64(li->li_used_bytes);
+ for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++)
+ da->da_data[i] = cpu_to_be64(li->li_data[i]);
+ *type = JE_ANCHOR;
+ *len = sizeof(*da);
+ return da;
+}
+
+static void *logfs_write_dynsb(struct super_block *sb, void *_dynsb,
+ u16 *type, size_t *len)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_je_dynsb *dynsb = _dynsb;
+
+ dynsb->ds_gec = cpu_to_be64(super->s_gec);
+ dynsb->ds_sweeper = cpu_to_be64(super->s_sweeper);
+ dynsb->ds_victim_ino = cpu_to_be64(super->s_victim_ino);
+ dynsb->ds_rename_dir = cpu_to_be64(super->s_rename_dir);
+ dynsb->ds_rename_pos = cpu_to_be64(super->s_rename_pos);
+ dynsb->ds_used_bytes = cpu_to_be64(super->s_used_bytes);
+ dynsb->ds_generation = cpu_to_be32(super->s_generation);
+ *type = JE_DYNSB;
+ *len = sizeof(*dynsb);
+ return dynsb;
+}
+
+static void write_wbuf(struct super_block *sb, struct logfs_area *area,
+ void *wbuf)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct address_space *mapping = super->s_mapping_inode->i_mapping;
+ u64 ofs;
+ pgoff_t index;
+ int page_ofs;
+ struct page *page;
+
+ ofs = dev_ofs(sb, area->a_segno,
+ area->a_used_bytes & ~(super->s_writesize - 1));
+ index = ofs >> PAGE_SHIFT;
+ page_ofs = ofs & (PAGE_SIZE - 1);
+
+ page = find_lock_page(mapping, index);
+ BUG_ON(!page);
+ memcpy(wbuf, page_address(page) + page_ofs, super->s_writesize);
+ unlock_page(page);
+}
+
+static void *logfs_write_area(struct super_block *sb, void *_a,
+ u16 *type, size_t *len)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_area *area = super->s_area[super->s_sum_index];
+ struct logfs_je_area *a = _a;
+
+ a->vim = VIM_DEFAULT;
+ a->gc_level = super->s_sum_index;
+ a->used_bytes = cpu_to_be32(area->a_used_bytes);
+ a->segno = cpu_to_be32(area->a_segno);
+ if (super->s_writesize > 1)
+ write_wbuf(sb, area, a + 1);
+
+ *type = JE_AREA;
+ *len = sizeof(*a) + super->s_writesize;
+ return a;
+}
+
+static void *logfs_write_commit(struct super_block *sb, void *h,
+ u16 *type, size_t *len)
+{
+ struct logfs_super *super = logfs_super(sb);
+
+ *type = JE_COMMIT;
+ *len = super->s_no_je * sizeof(__be64);
+ return super->s_je_array;
+}
+
+static size_t __logfs_write_je(struct super_block *sb, void *buf, u16 type,
+ size_t len)
+{
+ struct logfs_super *super = logfs_super(sb);
+ void *header = super->s_compressed_je;
+ void *data = header + sizeof(struct logfs_journal_header);
+ ssize_t compr_len, pad_len;
+ u8 compr = COMPR_ZLIB;
+
+ if (len == 0)
+ return logfs_write_header(super, header, 0, type);
+
+ compr_len = logfs_compress(buf, data, len, sb->s_blocksize);
+ if (compr_len < 0 || type == JE_ANCHOR) {
+ BUG_ON(len > sb->s_blocksize);
+ memcpy(data, buf, len);
+ compr_len = len;
+ compr = COMPR_NONE;
+ }
+
+ pad_len = ALIGN(compr_len, 16);
+ memset(data + compr_len, 0, pad_len - compr_len);
+
+ return __logfs_write_header(super, header, compr_len, len, type, compr);
+}
+
+static s64 logfs_get_free_bytes(struct logfs_area *area, size_t *bytes,
+ int must_pad)
+{
+ u32 writesize = logfs_super(area->a_sb)->s_writesize;
+ s32 ofs;
+ int ret;
+
+ ret = logfs_open_area(area, *bytes);
+ if (ret)
+ return -EAGAIN;
+
+ ofs = area->a_used_bytes;
+ area->a_used_bytes += *bytes;
+
+ if (must_pad) {
+ area->a_used_bytes = ALIGN(area->a_used_bytes, writesize);
+ *bytes = area->a_used_bytes - ofs;
+ }
+
+ return dev_ofs(area->a_sb, area->a_segno, ofs);
+}
+
+static int logfs_write_je_buf(struct super_block *sb, void *buf, u16 type,
+ size_t buf_len)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_area *area = super->s_journal_area;
+ struct logfs_journal_header *jh = super->s_compressed_je;
+ size_t len;
+ int must_pad = 0;
+ s64 ofs;
+
+ len = __logfs_write_je(sb, buf, type, buf_len);
+ if (jh->h_type == cpu_to_be16(JE_COMMIT))
+ must_pad = 1;
+
+ ofs = logfs_get_free_bytes(area, &len, must_pad);
+ if (ofs < 0)
+ return ofs;
+ logfs_buf_write(area, ofs, super->s_compressed_je, len);
+ super->s_je_array[super->s_no_je++] = cpu_to_be64(ofs);
+ return 0;
+}
+
+static int logfs_write_je(struct super_block *sb,
+ void* (*write)(struct super_block *sb, void *scratch,
+ u16 *type, size_t *len))
+{
+ void *buf;
+ size_t len;
+ u16 type;
+
+ buf = write(sb, logfs_super(sb)->s_je, &type, &len);
+ return logfs_write_je_buf(sb, buf, type, len);
+}
+
+int write_alias_journal(struct super_block *sb, u64 ino, u64 bix,
+ level_t level, int child_no, __be64 val)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_obj_alias *oa = super->s_je;
+ int err = 0, fill = super->s_je_fill;
+
+ log_aliases("logfs_write_obj_aliases #%x(%llx, %llx, %x, %x) %llx\n",
+ fill, ino, bix, level, child_no, be64_to_cpu(val));
+ oa[fill].ino = cpu_to_be64(ino);
+ oa[fill].bix = cpu_to_be64(bix);
+ oa[fill].val = val;
+ oa[fill].level = (__force u8)level;
+ oa[fill].child_no = cpu_to_be16(child_no);
+ fill++;
+ if (fill >= sb->s_blocksize / sizeof(*oa)) {
+ err = logfs_write_je_buf(sb, oa, JE_OBJ_ALIAS, sb->s_blocksize);
+ fill = 0;
+ }
+
+ super->s_je_fill = fill;
+ return err;
+}
+
+static int logfs_write_obj_aliases(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ int err;
+
+ log_journal("logfs_write_obj_aliases: %d aliases to write\n",
+ super->s_no_object_aliases);
+ super->s_je_fill = 0;
+ err = logfs_write_obj_aliases_pagecache(sb);
+ if (err)
+ return err;
+
+ if (super->s_je_fill)
+ err = logfs_write_je_buf(sb, super->s_je, JE_OBJ_ALIAS,
+ super->s_je_fill
+ * sizeof(struct logfs_obj_alias));
+ return err;
+}
+
+/*
+ * Write all journal entries. The goto logic ensures that all journal entries
+ * are written whenever a new segment is used. It is ugly and potentially a
+ * bit wasteful, but robustness is more important. With this we can *always*
+ * erase all journal segments except the one containing the most recent commit.
+ */
+void logfs_write_anchor(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_area *area = super->s_journal_area;
+ int i, err;
+
+ if (!(super->s_flags & LOGFS_SB_FLAG_DIRTY))
+ return;
+ super->s_flags &= ~LOGFS_SB_FLAG_DIRTY;
+
+ BUG_ON(super->s_flags & LOGFS_SB_FLAG_SHUTDOWN);
+ mutex_lock(&super->s_journal_mutex);
+
+ /* Do this first or suffer corruption */
+ logfs_sync_segments(sb);
+ account_shadows(sb);
+
+again:
+ super->s_no_je = 0;
+ for_each_area(i) {
+ if (!super->s_area[i]->a_is_open)
+ continue;
+ super->s_sum_index = i;
+ err = logfs_write_je(sb, logfs_write_area);
+ if (err)
+ goto again;
+ }
+ err = logfs_write_obj_aliases(sb);
+ if (err)
+ goto again;
+ err = logfs_write_je(sb, logfs_write_erasecount);
+ if (err)
+ goto again;
+ err = logfs_write_je(sb, __logfs_write_anchor);
+ if (err)
+ goto again;
+ err = logfs_write_je(sb, logfs_write_dynsb);
+ if (err)
+ goto again;
+ /*
+ * Order is imperative. First we sync all writes, including the
+ * non-committed journal writes. Then we write the final commit and
+ * sync the current journal segment.
+ * There is a theoretical bug here. Syncing the journal segment will
+ * write a number of journal entries and the final commit. All these
+ * are written in a single operation. If the device layer writes the
+ * data back-to-front, the commit will precede the other journal
+ * entries, leaving a race window.
+ * Two fixes are possible. Preferred is to fix the device layer to
+ * ensure writes happen front-to-back. Alternatively we can insert
+ * another logfs_sync_area() super->s_devops->sync() combo before
+ * writing the commit.
+ */
+ /*
+ * On another subject, super->s_devops->sync is usually not necessary.
+ * Unless called from sys_sync or friends, a barrier would suffice.
+ */
+ super->s_devops->sync(sb);
+ err = logfs_write_je(sb, logfs_write_commit);
+ if (err)
+ goto again;
+ log_journal("Write commit to %llx\n",
+ be64_to_cpu(super->s_je_array[super->s_no_je - 1]));
+ logfs_sync_area(area);
+ BUG_ON(area->a_used_bytes != area->a_written_bytes);
+ super->s_devops->sync(sb);
+
+ mutex_unlock(&super->s_journal_mutex);
+ return;
+}
+
+void do_logfs_journal_wl_pass(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_area *area = super->s_journal_area;
+ u32 segno, ec;
+ int i, err;
+
+ log_journal("Journal requires wear-leveling.\n");
+ /* Drop old segments */
+ journal_for_each(i)
+ if (super->s_journal_seg[i]) {
+ logfs_set_segment_unreserved(sb,
+ super->s_journal_seg[i],
+ super->s_journal_ec[i]);
+ super->s_journal_seg[i] = 0;
+ super->s_journal_ec[i] = 0;
+ }
+ /* Get new segments */
+ for (i = 0; i < super->s_no_journal_segs; i++) {
+ segno = get_best_cand(sb, &super->s_reserve_list, &ec);
+ super->s_journal_seg[i] = segno;
+ super->s_journal_ec[i] = ec;
+ logfs_set_segment_reserved(sb, segno);
+ }
+ /* Manually move journal_area */
+ area->a_segno = super->s_journal_seg[0];
+ area->a_is_open = 0;
+ area->a_used_bytes = 0;
+ /* Write journal */
+ logfs_write_anchor(sb);
+ /* Write superblocks */
+ err = logfs_write_sb(sb);
+ BUG_ON(err);
+}
+
+static const struct logfs_area_ops journal_area_ops = {
+ .get_free_segment = journal_get_free_segment,
+ .get_erase_count = journal_get_erase_count,
+ .erase_segment = journal_erase_segment,
+};
+
+int logfs_init_journal(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ size_t bufsize = max_t(size_t, sb->s_blocksize, super->s_writesize)
+ + MAX_JOURNAL_HEADER;
+ int ret = -ENOMEM;
+
+ mutex_init(&super->s_journal_mutex);
+ btree_init_mempool32(&super->s_reserved_segments, super->s_btree_pool);
+
+ super->s_je = kzalloc(bufsize, GFP_KERNEL);
+ if (!super->s_je)
+ return ret;
+
+ super->s_compressed_je = kzalloc(bufsize, GFP_KERNEL);
+ if (!super->s_compressed_je)
+ return ret;
+
+ super->s_master_inode = logfs_new_meta_inode(sb, LOGFS_INO_MASTER);
+ if (IS_ERR(super->s_master_inode))
+ return PTR_ERR(super->s_master_inode);
+
+ ret = logfs_read_journal(sb);
+ if (ret)
+ return -EIO;
+
+ reserve_sb_and_journal(sb);
+ logfs_calc_free(sb);
+
+ super->s_journal_area->a_ops = &journal_area_ops;
+ return 0;
+}
+
+void logfs_cleanup_journal(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+
+ btree_grim_visitor32(&super->s_reserved_segments, 0, NULL);
+ destroy_meta_inode(super->s_master_inode);
+ super->s_master_inode = NULL;
+
+ kfree(super->s_compressed_je);
+ kfree(super->s_je);
+}
diff --git a/fs/logfs/logfs.h b/fs/logfs/logfs.h
new file mode 100644
index 00000000000..12977943137
--- /dev/null
+++ b/fs/logfs/logfs.h
@@ -0,0 +1,724 @@
+/*
+ * fs/logfs/logfs.h
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ *
+ * Private header for logfs.
+ */
+#ifndef FS_LOGFS_LOGFS_H
+#define FS_LOGFS_LOGFS_H
+
+#undef __CHECK_ENDIAN__
+#define __CHECK_ENDIAN__
+
+#include <linux/btree.h>
+#include <linux/crc32.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/mempool.h>
+#include <linux/pagemap.h>
+#include <linux/mtd/mtd.h>
+#include "logfs_abi.h"
+
+#define LOGFS_DEBUG_SUPER (0x0001)
+#define LOGFS_DEBUG_SEGMENT (0x0002)
+#define LOGFS_DEBUG_JOURNAL (0x0004)
+#define LOGFS_DEBUG_DIR (0x0008)
+#define LOGFS_DEBUG_FILE (0x0010)
+#define LOGFS_DEBUG_INODE (0x0020)
+#define LOGFS_DEBUG_READWRITE (0x0040)
+#define LOGFS_DEBUG_GC (0x0080)
+#define LOGFS_DEBUG_GC_NOISY (0x0100)
+#define LOGFS_DEBUG_ALIASES (0x0200)
+#define LOGFS_DEBUG_BLOCKMOVE (0x0400)
+#define LOGFS_DEBUG_ALL (0xffffffff)
+
+#define LOGFS_DEBUG (0x01)
+/*
+ * To enable specific log messages, simply define LOGFS_DEBUG to match any
+ * or all of the above.
+ */
+#ifndef LOGFS_DEBUG
+#define LOGFS_DEBUG (0)
+#endif
+
+#define log_cond(cond, fmt, arg...) do { \
+ if (cond) \
+ printk(KERN_DEBUG fmt, ##arg); \
+} while (0)
+
+#define log_super(fmt, arg...) \
+ log_cond(LOGFS_DEBUG & LOGFS_DEBUG_SUPER, fmt, ##arg)
+#define log_segment(fmt, arg...) \
+ log_cond(LOGFS_DEBUG & LOGFS_DEBUG_SEGMENT, fmt, ##arg)
+#define log_journal(fmt, arg...) \
+ log_cond(LOGFS_DEBUG & LOGFS_DEBUG_JOURNAL, fmt, ##arg)
+#define log_dir(fmt, arg...) \
+ log_cond(LOGFS_DEBUG & LOGFS_DEBUG_DIR, fmt, ##arg)
+#define log_file(fmt, arg...) \
+ log_cond(LOGFS_DEBUG & LOGFS_DEBUG_FILE, fmt, ##arg)
+#define log_inode(fmt, arg...) \
+ log_cond(LOGFS_DEBUG & LOGFS_DEBUG_INODE, fmt, ##arg)
+#define log_readwrite(fmt, arg...) \
+ log_cond(LOGFS_DEBUG & LOGFS_DEBUG_READWRITE, fmt, ##arg)
+#define log_gc(fmt, arg...) \
+ log_cond(LOGFS_DEBUG & LOGFS_DEBUG_GC, fmt, ##arg)
+#define log_gc_noisy(fmt, arg...) \
+ log_cond(LOGFS_DEBUG & LOGFS_DEBUG_GC_NOISY, fmt, ##arg)
+#define log_aliases(fmt, arg...) \
+ log_cond(LOGFS_DEBUG & LOGFS_DEBUG_ALIASES, fmt, ##arg)
+#define log_blockmove(fmt, arg...) \
+ log_cond(LOGFS_DEBUG & LOGFS_DEBUG_BLOCKMOVE, fmt, ##arg)
+
+#define PG_pre_locked PG_owner_priv_1
+#define PagePreLocked(page) test_bit(PG_pre_locked, &(page)->flags)
+#define SetPagePreLocked(page) set_bit(PG_pre_locked, &(page)->flags)
+#define ClearPagePreLocked(page) clear_bit(PG_pre_locked, &(page)->flags)
+
+/* FIXME: This should really be somewhere in the 64bit area. */
+#define LOGFS_LINK_MAX (1<<30)
+
+/* Read-only filesystem */
+#define LOGFS_SB_FLAG_RO 0x0001
+#define LOGFS_SB_FLAG_DIRTY 0x0002
+#define LOGFS_SB_FLAG_OBJ_ALIAS 0x0004
+#define LOGFS_SB_FLAG_SHUTDOWN 0x0008
+
+/* Write Control Flags */
+#define WF_LOCK 0x01 /* take write lock */
+#define WF_WRITE 0x02 /* write block */
+#define WF_DELETE 0x04 /* delete old block */
+
+typedef u8 __bitwise level_t;
+typedef u8 __bitwise gc_level_t;
+
+#define LEVEL(level) ((__force level_t)(level))
+#define GC_LEVEL(gc_level) ((__force gc_level_t)(gc_level))
+
+#define SUBLEVEL(level) ( (void)((level) == LEVEL(1)), \
+ (__force level_t)((__force u8)(level) - 1) )
+
+/**
+ * struct logfs_area - area management information
+ *
+ * @a_sb: the superblock this area belongs to
+ * @a_is_open: 1 if the area is currently open, else 0
+ * @a_segno: segment number of area
+ * @a_written_bytes: number of bytes already written back
+ * @a_used_bytes: number of used bytes
+ * @a_ops: area operations (either journal or ostore)
+ * @a_erase_count: erase count
+ * @a_level: GC level
+ */
+struct logfs_area { /* a segment open for writing */
+ struct super_block *a_sb;
+ int a_is_open;
+ u32 a_segno;
+ u32 a_written_bytes;
+ u32 a_used_bytes;
+ const struct logfs_area_ops *a_ops;
+ u32 a_erase_count;
+ gc_level_t a_level;
+};
+
+/**
+ * struct logfs_area_ops - area operations
+ *
+ * @get_free_segment: fill area->ofs with the offset of a free segment
+ * @get_erase_count: fill area->erase_count (needs area->ofs)
+ * @erase_segment: erase and setup segment
+ */
+struct logfs_area_ops {
+ void (*get_free_segment)(struct logfs_area *area);
+ void (*get_erase_count)(struct logfs_area *area);
+ int (*erase_segment)(struct logfs_area *area);
+};
+
+/**
+ * struct logfs_device_ops - device access operations
+ *
+ * @readpage: read one page (mm page)
+ * @writeseg: write one segment. may be a partial segment
+ * @erase: erase one segment
+ * @read: read from the device
+ * @erase: erase part of the device
+ */
+struct logfs_device_ops {
+ struct page *(*find_first_sb)(struct super_block *sb, u64 *ofs);
+ struct page *(*find_last_sb)(struct super_block *sb, u64 *ofs);
+ int (*write_sb)(struct super_block *sb, struct page *page);
+ int (*readpage)(void *_sb, struct page *page);
+ void (*writeseg)(struct super_block *sb, u64 ofs, size_t len);
+ int (*erase)(struct super_block *sb, loff_t ofs, size_t len,
+ int ensure_write);
+ void (*sync)(struct super_block *sb);
+ void (*put_device)(struct super_block *sb);
+};
+
+/**
+ * struct candidate_list - list of similar candidates
+ */
+struct candidate_list {
+ struct rb_root rb_tree;
+ int count;
+ int maxcount;
+ int sort_by_ec;
+};
+
+/**
+ * struct gc_candidate - "candidate" segment to be garbage collected next
+ *
+ * @list: list (either free of low)
+ * @segno: segment number
+ * @valid: number of valid bytes
+ * @erase_count: erase count of segment
+ * @dist: distance from tree root
+ *
+ * Candidates can be on two lists. The free list contains electees rather
+ * than candidates - segments that no longer contain any valid data. The
+ * low list contains candidates to be picked for GC. It should be kept
+ * short. It is not required to always pick a perfect candidate. In the
+ * worst case GC will have to move more data than absolutely necessary.
+ */
+struct gc_candidate {
+ struct rb_node rb_node;
+ struct candidate_list *list;
+ u32 segno;
+ u32 valid;
+ u32 erase_count;
+ u8 dist;
+};
+
+/**
+ * struct logfs_journal_entry - temporary structure used during journal scan
+ *
+ * @used:
+ * @version: normalized version
+ * @len: length
+ * @offset: offset
+ */
+struct logfs_journal_entry {
+ int used;
+ s16 version;
+ u16 len;
+ u16 datalen;
+ u64 offset;
+};
+
+enum transaction_state {
+ CREATE_1 = 1,
+ CREATE_2,
+ UNLINK_1,
+ UNLINK_2,
+ CROSS_RENAME_1,
+ CROSS_RENAME_2,
+ TARGET_RENAME_1,
+ TARGET_RENAME_2,
+ TARGET_RENAME_3
+};
+
+/**
+ * struct logfs_transaction - essential fields to support atomic dirops
+ *
+ * @ino: target inode
+ * @dir: inode of directory containing dentry
+ * @pos: pos of dentry in directory
+ */
+struct logfs_transaction {
+ enum transaction_state state;
+ u64 ino;
+ u64 dir;
+ u64 pos;
+};
+
+/**
+ * struct logfs_shadow - old block in the shadow of a not-yet-committed new one
+ * @old_ofs: offset of old block on medium
+ * @new_ofs: offset of new block on medium
+ * @ino: inode number
+ * @bix: block index
+ * @old_len: size of old block, including header
+ * @new_len: size of new block, including header
+ * @level: block level
+ */
+struct logfs_shadow {
+ u64 old_ofs;
+ u64 new_ofs;
+ u64 ino;
+ u64 bix;
+ int old_len;
+ int new_len;
+ gc_level_t gc_level;
+};
+
+/**
+ * struct shadow_tree
+ * @new: shadows where old_ofs==0, indexed by new_ofs
+ * @old: shadows where old_ofs!=0, indexed by old_ofs
+ */
+struct shadow_tree {
+ struct btree_head64 new;
+ struct btree_head64 old;
+};
+
+struct object_alias_item {
+ struct list_head list;
+ __be64 val;
+ int child_no;
+};
+
+/**
+ * struct logfs_block - contains any block state
+ * @type: indirect block or inode
+ * @full: number of fully populated children
+ * @partial: number of partially populated children
+ *
+ * Most blocks are directly represented by page cache pages. But when a block
+ * becomes dirty, is part of a transaction, contains aliases or is otherwise
+ * special, a struct logfs_block is allocated to track the additional state.
+ * Inodes are very similar to indirect blocks, so they can also get one of
+ * these structures added when appropriate.
+ */
+#define BLOCK_INDIRECT 1 /* Indirect block */
+#define BLOCK_INODE 2 /* Inode */
+struct logfs_block_ops;
+struct logfs_block {
+ struct list_head alias_list;
+ struct list_head item_list;
+ struct super_block *sb;
+ u64 ino;
+ u64 bix;
+ level_t level;
+ struct page *page;
+ struct inode *inode;
+ struct logfs_transaction *ta;
+ unsigned long alias_map[LOGFS_BLOCK_FACTOR / BITS_PER_LONG];
+ struct logfs_block_ops *ops;
+ int full;
+ int partial;
+ int reserved_bytes;
+};
+
+typedef int write_alias_t(struct super_block *sb, u64 ino, u64 bix,
+ level_t level, int child_no, __be64 val);
+struct logfs_block_ops {
+ void (*write_block)(struct logfs_block *block);
+ gc_level_t (*block_level)(struct logfs_block *block);
+ void (*free_block)(struct super_block *sb, struct logfs_block*block);
+ int (*write_alias)(struct super_block *sb,
+ struct logfs_block *block,
+ write_alias_t *write_one_alias);
+};
+
+struct logfs_super {
+ struct mtd_info *s_mtd; /* underlying device */
+ struct block_device *s_bdev; /* underlying device */
+ const struct logfs_device_ops *s_devops;/* device access */
+ struct inode *s_master_inode; /* inode file */
+ struct inode *s_segfile_inode; /* segment file */
+ struct inode *s_mapping_inode; /* device mapping */
+ atomic_t s_pending_writes; /* outstanting bios */
+ long s_flags;
+ mempool_t *s_btree_pool; /* for btree nodes */
+ mempool_t *s_alias_pool; /* aliases in segment.c */
+ u64 s_feature_incompat;
+ u64 s_feature_ro_compat;
+ u64 s_feature_compat;
+ u64 s_feature_flags;
+ u64 s_sb_ofs[2];
+ struct page *s_erase_page; /* for dev_bdev.c */
+ /* alias.c fields */
+ struct btree_head32 s_segment_alias; /* remapped segments */
+ int s_no_object_aliases;
+ struct list_head s_object_alias; /* remapped objects */
+ struct btree_head128 s_object_alias_tree; /* remapped objects */
+ struct mutex s_object_alias_mutex;
+ /* dir.c fields */
+ struct mutex s_dirop_mutex; /* for creat/unlink/rename */
+ u64 s_victim_ino; /* used for atomic dir-ops */
+ u64 s_rename_dir; /* source directory ino */
+ u64 s_rename_pos; /* position of source dd */
+ /* gc.c fields */
+ long s_segsize; /* size of a segment */
+ int s_segshift; /* log2 of segment size */
+ long s_segmask; /* 1 << s_segshift - 1 */
+ long s_no_segs; /* segments on device */
+ long s_no_journal_segs; /* segments used for journal */
+ long s_no_blocks; /* blocks per segment */
+ long s_writesize; /* minimum write size */
+ int s_writeshift; /* log2 of write size */
+ u64 s_size; /* filesystem size */
+ struct logfs_area *s_area[LOGFS_NO_AREAS]; /* open segment array */
+ u64 s_gec; /* global erase count */
+ u64 s_wl_gec_ostore; /* time of last wl event */
+ u64 s_wl_gec_journal; /* time of last wl event */
+ u64 s_sweeper; /* current sweeper pos */
+ u8 s_ifile_levels; /* max level of ifile */
+ u8 s_iblock_levels; /* max level of regular files */
+ u8 s_data_levels; /* # of segments to leaf block*/
+ u8 s_total_levels; /* sum of above three */
+ struct btree_head32 s_cand_tree; /* all candidates */
+ struct candidate_list s_free_list; /* 100% free segments */
+ struct candidate_list s_reserve_list; /* Bad segment reserve */
+ struct candidate_list s_low_list[LOGFS_NO_AREAS];/* good candidates */
+ struct candidate_list s_ec_list; /* wear level candidates */
+ struct btree_head32 s_reserved_segments;/* sb, journal, bad, etc. */
+ /* inode.c fields */
+ u64 s_last_ino; /* highest ino used */
+ long s_inos_till_wrap;
+ u32 s_generation; /* i_generation for new files */
+ struct list_head s_freeing_list; /* inodes being freed */
+ /* journal.c fields */
+ struct mutex s_journal_mutex;
+ void *s_je; /* journal entry to compress */
+ void *s_compressed_je; /* block to write to journal */
+ u32 s_journal_seg[LOGFS_JOURNAL_SEGS]; /* journal segments */
+ u32 s_journal_ec[LOGFS_JOURNAL_SEGS]; /* journal erasecounts */
+ u64 s_last_version;
+ struct logfs_area *s_journal_area; /* open journal segment */
+ __be64 s_je_array[64];
+ int s_no_je;
+
+ int s_sum_index; /* for the 12 summaries */
+ struct shadow_tree s_shadow_tree;
+ int s_je_fill; /* index of current je */
+ /* readwrite.c fields */
+ struct mutex s_write_mutex;
+ int s_lock_count;
+ mempool_t *s_block_pool; /* struct logfs_block pool */
+ mempool_t *s_shadow_pool; /* struct logfs_shadow pool */
+ /*
+ * Space accounting:
+ * - s_used_bytes specifies space used to store valid data objects.
+ * - s_dirty_used_bytes is space used to store non-committed data
+ * objects. Those objects have already been written themselves,
+ * but they don't become valid until all indirect blocks up to the
+ * journal have been written as well.
+ * - s_dirty_free_bytes is space used to store the old copy of a
+ * replaced object, as long as the replacement is non-committed.
+ * In other words, it is the amount of space freed when all dirty
+ * blocks are written back.
+ * - s_free_bytes is the amount of free space available for any
+ * purpose.
+ * - s_root_reserve is the amount of free space available only to
+ * the root user. Non-privileged users can no longer write once
+ * this watermark has been reached.
+ * - s_speed_reserve is space which remains unused to speed up
+ * garbage collection performance.
+ * - s_dirty_pages is the space reserved for currently dirty pages.
+ * It is a pessimistic estimate, so some/most will get freed on
+ * page writeback.
+ *
+ * s_used_bytes + s_free_bytes + s_speed_reserve = total usable size
+ */
+ u64 s_free_bytes;
+ u64 s_used_bytes;
+ u64 s_dirty_free_bytes;
+ u64 s_dirty_used_bytes;
+ u64 s_root_reserve;
+ u64 s_speed_reserve;
+ u64 s_dirty_pages;
+ /* Bad block handling:
+ * - s_bad_seg_reserve is a number of segments usually kept
+ * free. When encountering bad blocks, the affected segment's data
+ * is _temporarily_ moved to a reserved segment.
+ * - s_bad_segments is the number of known bad segments.
+ */
+ u32 s_bad_seg_reserve;
+ u32 s_bad_segments;
+};
+
+/**
+ * struct logfs_inode - in-memory inode
+ *
+ * @vfs_inode: struct inode
+ * @li_data: data pointers
+ * @li_used_bytes: number of used bytes
+ * @li_freeing_list: used to track inodes currently being freed
+ * @li_flags: inode flags
+ * @li_refcount: number of internal (GC-induced) references
+ */
+struct logfs_inode {
+ struct inode vfs_inode;
+ u64 li_data[LOGFS_EMBEDDED_FIELDS];
+ u64 li_used_bytes;
+ struct list_head li_freeing_list;
+ struct logfs_block *li_block;
+ u32 li_flags;
+ u8 li_height;
+ int li_refcount;
+};
+
+#define journal_for_each(__i) for (__i = 0; __i < LOGFS_JOURNAL_SEGS; __i++)
+#define for_each_area(__i) for (__i = 0; __i < LOGFS_NO_AREAS; __i++)
+#define for_each_area_down(__i) for (__i = LOGFS_NO_AREAS - 1; __i >= 0; __i--)
+
+/* compr.c */
+int logfs_compress(void *in, void *out, size_t inlen, size_t outlen);
+int logfs_uncompress(void *in, void *out, size_t inlen, size_t outlen);
+int __init logfs_compr_init(void);
+void logfs_compr_exit(void);
+
+/* dev_bdev.c */
+#ifdef CONFIG_BLOCK
+int logfs_get_sb_bdev(struct file_system_type *type, int flags,
+ const char *devname, struct vfsmount *mnt);
+#else
+static inline int logfs_get_sb_bdev(struct file_system_type *type, int flags,
+ const char *devname, struct vfsmount *mnt)
+{
+ return -ENODEV;
+}
+#endif
+
+/* dev_mtd.c */
+#ifdef CONFIG_MTD
+int logfs_get_sb_mtd(struct file_system_type *type, int flags,
+ int mtdnr, struct vfsmount *mnt);
+#else
+static inline int logfs_get_sb_mtd(struct file_system_type *type, int flags,
+ int mtdnr, struct vfsmount *mnt)
+{
+ return -ENODEV;
+}
+#endif
+
+/* dir.c */
+extern const struct inode_operations logfs_symlink_iops;
+extern const struct inode_operations logfs_dir_iops;
+extern const struct file_operations logfs_dir_fops;
+int logfs_replay_journal(struct super_block *sb);
+
+/* file.c */
+extern const struct inode_operations logfs_reg_iops;
+extern const struct file_operations logfs_reg_fops;
+extern const struct address_space_operations logfs_reg_aops;
+int logfs_readpage(struct file *file, struct page *page);
+int logfs_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg);
+int logfs_fsync(struct file *file, struct dentry *dentry, int datasync);
+
+/* gc.c */
+u32 get_best_cand(struct super_block *sb, struct candidate_list *list, u32 *ec);
+void logfs_gc_pass(struct super_block *sb);
+int logfs_check_areas(struct super_block *sb);
+int logfs_init_gc(struct super_block *sb);
+void logfs_cleanup_gc(struct super_block *sb);
+
+/* inode.c */
+extern const struct super_operations logfs_super_operations;
+struct inode *logfs_iget(struct super_block *sb, ino_t ino);
+struct inode *logfs_safe_iget(struct super_block *sb, ino_t ino, int *cookie);
+void logfs_safe_iput(struct inode *inode, int cookie);
+struct inode *logfs_new_inode(struct inode *dir, int mode);
+struct inode *logfs_new_meta_inode(struct super_block *sb, u64 ino);
+struct inode *logfs_read_meta_inode(struct super_block *sb, u64 ino);
+int logfs_init_inode_cache(void);
+void logfs_destroy_inode_cache(void);
+void destroy_meta_inode(struct inode *inode);
+void logfs_set_blocks(struct inode *inode, u64 no);
+/* these logically belong into inode.c but actually reside in readwrite.c */
+int logfs_read_inode(struct inode *inode);
+int __logfs_write_inode(struct inode *inode, long flags);
+void logfs_delete_inode(struct inode *inode);
+void logfs_clear_inode(struct inode *inode);
+
+/* journal.c */
+void logfs_write_anchor(struct super_block *sb);
+int logfs_init_journal(struct super_block *sb);
+void logfs_cleanup_journal(struct super_block *sb);
+int write_alias_journal(struct super_block *sb, u64 ino, u64 bix,
+ level_t level, int child_no, __be64 val);
+void do_logfs_journal_wl_pass(struct super_block *sb);
+
+/* readwrite.c */
+pgoff_t logfs_pack_index(u64 bix, level_t level);
+void logfs_unpack_index(pgoff_t index, u64 *bix, level_t *level);
+int logfs_inode_write(struct inode *inode, const void *buf, size_t count,
+ loff_t bix, long flags, struct shadow_tree *shadow_tree);
+int logfs_readpage_nolock(struct page *page);
+int logfs_write_buf(struct inode *inode, struct page *page, long flags);
+int logfs_delete(struct inode *inode, pgoff_t index,
+ struct shadow_tree *shadow_tree);
+int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs,
+ gc_level_t gc_level, long flags);
+int logfs_is_valid_block(struct super_block *sb, u64 ofs, u64 ino, u64 bix,
+ gc_level_t gc_level);
+int logfs_truncate(struct inode *inode, u64 size);
+u64 logfs_seek_hole(struct inode *inode, u64 bix);
+u64 logfs_seek_data(struct inode *inode, u64 bix);
+int logfs_open_segfile(struct super_block *sb);
+int logfs_init_rw(struct super_block *sb);
+void logfs_cleanup_rw(struct super_block *sb);
+void logfs_add_transaction(struct inode *inode, struct logfs_transaction *ta);
+void logfs_del_transaction(struct inode *inode, struct logfs_transaction *ta);
+void logfs_write_block(struct logfs_block *block, long flags);
+int logfs_write_obj_aliases_pagecache(struct super_block *sb);
+void logfs_get_segment_entry(struct super_block *sb, u32 segno,
+ struct logfs_segment_entry *se);
+void logfs_set_segment_used(struct super_block *sb, u64 ofs, int increment);
+void logfs_set_segment_erased(struct super_block *sb, u32 segno, u32 ec,
+ gc_level_t gc_level);
+void logfs_set_segment_reserved(struct super_block *sb, u32 segno);
+void logfs_set_segment_unreserved(struct super_block *sb, u32 segno, u32 ec);
+struct logfs_block *__alloc_block(struct super_block *sb,
+ u64 ino, u64 bix, level_t level);
+void __free_block(struct super_block *sb, struct logfs_block *block);
+void btree_write_block(struct logfs_block *block);
+void initialize_block_counters(struct page *page, struct logfs_block *block,
+ __be64 *array, int page_is_empty);
+int logfs_exist_block(struct inode *inode, u64 bix);
+int get_page_reserve(struct inode *inode, struct page *page);
+extern struct logfs_block_ops indirect_block_ops;
+
+/* segment.c */
+int logfs_erase_segment(struct super_block *sb, u32 ofs, int ensure_erase);
+int wbuf_read(struct super_block *sb, u64 ofs, size_t len, void *buf);
+int logfs_segment_read(struct inode *inode, struct page *page, u64 ofs, u64 bix,
+ level_t level);
+int logfs_segment_write(struct inode *inode, struct page *page,
+ struct logfs_shadow *shadow);
+int logfs_segment_delete(struct inode *inode, struct logfs_shadow *shadow);
+int logfs_load_object_aliases(struct super_block *sb,
+ struct logfs_obj_alias *oa, int count);
+void move_page_to_btree(struct page *page);
+int logfs_init_mapping(struct super_block *sb);
+void logfs_sync_area(struct logfs_area *area);
+void logfs_sync_segments(struct super_block *sb);
+
+/* area handling */
+int logfs_init_areas(struct super_block *sb);
+void logfs_cleanup_areas(struct super_block *sb);
+int logfs_open_area(struct logfs_area *area, size_t bytes);
+void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
+ int use_filler);
+
+static inline void logfs_buf_write(struct logfs_area *area, u64 ofs,
+ void *buf, size_t len)
+{
+ __logfs_buf_write(area, ofs, buf, len, 0);
+}
+
+static inline void logfs_buf_recover(struct logfs_area *area, u64 ofs,
+ void *buf, size_t len)
+{
+ __logfs_buf_write(area, ofs, buf, len, 1);
+}
+
+/* super.c */
+struct page *emergency_read_begin(struct address_space *mapping, pgoff_t index);
+void emergency_read_end(struct page *page);
+void logfs_crash_dump(struct super_block *sb);
+void *memchr_inv(const void *s, int c, size_t n);
+int logfs_statfs(struct dentry *dentry, struct kstatfs *stats);
+int logfs_get_sb_device(struct file_system_type *type, int flags,
+ struct mtd_info *mtd, struct block_device *bdev,
+ const struct logfs_device_ops *devops, struct vfsmount *mnt);
+int logfs_check_ds(struct logfs_disk_super *ds);
+int logfs_write_sb(struct super_block *sb);
+
+static inline struct logfs_super *logfs_super(struct super_block *sb)
+{
+ return sb->s_fs_info;
+}
+
+static inline struct logfs_inode *logfs_inode(struct inode *inode)
+{
+ return container_of(inode, struct logfs_inode, vfs_inode);
+}
+
+static inline void logfs_set_ro(struct super_block *sb)
+{
+ logfs_super(sb)->s_flags |= LOGFS_SB_FLAG_RO;
+}
+
+#define LOGFS_BUG(sb) do { \
+ struct super_block *__sb = sb; \
+ logfs_crash_dump(__sb); \
+ logfs_super(__sb)->s_flags |= LOGFS_SB_FLAG_RO; \
+ BUG(); \
+} while (0)
+
+#define LOGFS_BUG_ON(condition, sb) \
+ do { if (unlikely(condition)) LOGFS_BUG((sb)); } while (0)
+
+static inline __be32 logfs_crc32(void *data, size_t len, size_t skip)
+{
+ return cpu_to_be32(crc32(~0, data+skip, len-skip));
+}
+
+static inline u8 logfs_type(struct inode *inode)
+{
+ return (inode->i_mode >> 12) & 15;
+}
+
+static inline pgoff_t logfs_index(struct super_block *sb, u64 pos)
+{
+ return pos >> sb->s_blocksize_bits;
+}
+
+static inline u64 dev_ofs(struct super_block *sb, u32 segno, u32 ofs)
+{
+ return ((u64)segno << logfs_super(sb)->s_segshift) + ofs;
+}
+
+static inline u32 seg_no(struct super_block *sb, u64 ofs)
+{
+ return ofs >> logfs_super(sb)->s_segshift;
+}
+
+static inline u32 seg_ofs(struct super_block *sb, u64 ofs)
+{
+ return ofs & logfs_super(sb)->s_segmask;
+}
+
+static inline u64 seg_align(struct super_block *sb, u64 ofs)
+{
+ return ofs & ~logfs_super(sb)->s_segmask;
+}
+
+static inline struct logfs_block *logfs_block(struct page *page)
+{
+ return (void *)page->private;
+}
+
+static inline level_t shrink_level(gc_level_t __level)
+{
+ u8 level = (__force u8)__level;
+
+ if (level >= LOGFS_MAX_LEVELS)
+ level -= LOGFS_MAX_LEVELS;
+ return (__force level_t)level;
+}
+
+static inline gc_level_t expand_level(u64 ino, level_t __level)
+{
+ u8 level = (__force u8)__level;
+
+ if (ino == LOGFS_INO_MASTER) {
+ /* ifile has seperate areas */
+ level += LOGFS_MAX_LEVELS;
+ }
+ return (__force gc_level_t)level;
+}
+
+static inline int logfs_block_shift(struct super_block *sb, level_t level)
+{
+ level = shrink_level((__force gc_level_t)level);
+ return (__force int)level * (sb->s_blocksize_bits - 3);
+}
+
+static inline u64 logfs_block_mask(struct super_block *sb, level_t level)
+{
+ return ~0ull << logfs_block_shift(sb, level);
+}
+
+static inline struct logfs_area *get_area(struct super_block *sb,
+ gc_level_t gc_level)
+{
+ return logfs_super(sb)->s_area[(__force u8)gc_level];
+}
+
+#endif
diff --git a/fs/logfs/logfs_abi.h b/fs/logfs/logfs_abi.h
new file mode 100644
index 00000000000..f674725663f
--- /dev/null
+++ b/fs/logfs/logfs_abi.h
@@ -0,0 +1,629 @@
+/*
+ * fs/logfs/logfs_abi.h
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ *
+ * Public header for logfs.
+ */
+#ifndef FS_LOGFS_LOGFS_ABI_H
+#define FS_LOGFS_LOGFS_ABI_H
+
+/* For out-of-kernel compiles */
+#ifndef BUILD_BUG_ON
+#define BUILD_BUG_ON(condition) /**/
+#endif
+
+#define SIZE_CHECK(type, size) \
+static inline void check_##type(void) \
+{ \
+ BUILD_BUG_ON(sizeof(struct type) != (size)); \
+}
+
+/*
+ * Throughout the logfs code, we're constantly dealing with blocks at
+ * various positions or offsets. To remove confusion, we stricly
+ * distinguish between a "position" - the logical position within a
+ * file and an "offset" - the physical location within the device.
+ *
+ * Any usage of the term offset for a logical location or position for
+ * a physical one is a bug and should get fixed.
+ */
+
+/*
+ * Block are allocated in one of several segments depending on their
+ * level. The following levels are used:
+ * 0 - regular data block
+ * 1 - i1 indirect blocks
+ * 2 - i2 indirect blocks
+ * 3 - i3 indirect blocks
+ * 4 - i4 indirect blocks
+ * 5 - i5 indirect blocks
+ * 6 - ifile data blocks
+ * 7 - ifile i1 indirect blocks
+ * 8 - ifile i2 indirect blocks
+ * 9 - ifile i3 indirect blocks
+ * 10 - ifile i4 indirect blocks
+ * 11 - ifile i5 indirect blocks
+ * Potential levels to be used in the future:
+ * 12 - gc recycled blocks, long-lived data
+ * 13 - replacement blocks, short-lived data
+ *
+ * Levels 1-11 are necessary for robust gc operations and help seperate
+ * short-lived metadata from longer-lived file data. In the future,
+ * file data should get seperated into several segments based on simple
+ * heuristics. Old data recycled during gc operation is expected to be
+ * long-lived. New data is of uncertain life expectancy. New data
+ * used to replace older blocks in existing files is expected to be
+ * short-lived.
+ */
+
+
+/* Magic numbers. 64bit for superblock, 32bit for statfs f_type */
+#define LOGFS_MAGIC 0x7a3a8e5cb9d5bf67ull
+#define LOGFS_MAGIC_U32 0xc97e8168u
+
+/*
+ * Various blocksize related macros. Blocksize is currently fixed at 4KiB.
+ * Sooner or later that should become configurable and the macros replaced
+ * by something superblock-dependent. Pointers in indirect blocks are and
+ * will remain 64bit.
+ *
+ * LOGFS_BLOCKSIZE - self-explaining
+ * LOGFS_BLOCK_FACTOR - number of pointers per indirect block
+ * LOGFS_BLOCK_BITS - log2 of LOGFS_BLOCK_FACTOR, used for shifts
+ */
+#define LOGFS_BLOCKSIZE (4096ull)
+#define LOGFS_BLOCK_FACTOR (LOGFS_BLOCKSIZE / sizeof(u64))
+#define LOGFS_BLOCK_BITS (9)
+
+/*
+ * Number of blocks at various levels of indirection. There are 16 direct
+ * block pointers plus a single indirect pointer.
+ */
+#define I0_BLOCKS (16)
+#define I1_BLOCKS LOGFS_BLOCK_FACTOR
+#define I2_BLOCKS (LOGFS_BLOCK_FACTOR * I1_BLOCKS)
+#define I3_BLOCKS (LOGFS_BLOCK_FACTOR * I2_BLOCKS)
+#define I4_BLOCKS (LOGFS_BLOCK_FACTOR * I3_BLOCKS)
+#define I5_BLOCKS (LOGFS_BLOCK_FACTOR * I4_BLOCKS)
+
+#define INDIRECT_INDEX I0_BLOCKS
+#define LOGFS_EMBEDDED_FIELDS (I0_BLOCKS + 1)
+
+/*
+ * Sizes at which files require another level of indirection. Files smaller
+ * than LOGFS_EMBEDDED_SIZE can be completely stored in the inode itself,
+ * similar like ext2 fast symlinks.
+ *
+ * Data at a position smaller than LOGFS_I0_SIZE is accessed through the
+ * direct pointers, else through the 1x indirect pointer and so forth.
+ */
+#define LOGFS_EMBEDDED_SIZE (LOGFS_EMBEDDED_FIELDS * sizeof(u64))
+#define LOGFS_I0_SIZE (I0_BLOCKS * LOGFS_BLOCKSIZE)
+#define LOGFS_I1_SIZE (I1_BLOCKS * LOGFS_BLOCKSIZE)
+#define LOGFS_I2_SIZE (I2_BLOCKS * LOGFS_BLOCKSIZE)
+#define LOGFS_I3_SIZE (I3_BLOCKS * LOGFS_BLOCKSIZE)
+#define LOGFS_I4_SIZE (I4_BLOCKS * LOGFS_BLOCKSIZE)
+#define LOGFS_I5_SIZE (I5_BLOCKS * LOGFS_BLOCKSIZE)
+
+/*
+ * Each indirect block pointer must have this flag set, if all block pointers
+ * behind it are set, i.e. there is no hole hidden in the shadow of this
+ * indirect block pointer.
+ */
+#define LOGFS_FULLY_POPULATED (1ULL << 63)
+#define pure_ofs(ofs) (ofs & ~LOGFS_FULLY_POPULATED)
+
+/*
+ * LogFS needs to seperate data into levels. Each level is defined as the
+ * maximal possible distance from the master inode (inode of the inode file).
+ * Data blocks reside on level 0, 1x indirect block on level 1, etc.
+ * Inodes reside on level 6, indirect blocks for the inode file on levels 7-11.
+ * This effort is necessary to guarantee garbage collection to always make
+ * progress.
+ *
+ * LOGFS_MAX_INDIRECT is the maximal indirection through indirect blocks,
+ * LOGFS_MAX_LEVELS is one more for the actual data level of a file. It is
+ * the maximal number of levels for one file.
+ * LOGFS_NO_AREAS is twice that, as the inode file and regular files are
+ * effectively stacked on top of each other.
+ */
+#define LOGFS_MAX_INDIRECT (5)
+#define LOGFS_MAX_LEVELS (LOGFS_MAX_INDIRECT + 1)
+#define LOGFS_NO_AREAS (2 * LOGFS_MAX_LEVELS)
+
+/* Maximum size of filenames */
+#define LOGFS_MAX_NAMELEN (255)
+
+/* Number of segments in the primary journal. */
+#define LOGFS_JOURNAL_SEGS (16)
+
+/* Maximum number of free/erased/etc. segments in journal entries */
+#define MAX_CACHED_SEGS (64)
+
+
+/*
+ * LOGFS_OBJECT_HEADERSIZE is the size of a single header in the object store,
+ * LOGFS_MAX_OBJECTSIZE the size of the largest possible object, including
+ * its header,
+ * LOGFS_SEGMENT_RESERVE is the amount of space reserved for each segment for
+ * its segment header and the padded space at the end when no further objects
+ * fit.
+ */
+#define LOGFS_OBJECT_HEADERSIZE (0x1c)
+#define LOGFS_SEGMENT_HEADERSIZE (0x18)
+#define LOGFS_MAX_OBJECTSIZE (LOGFS_OBJECT_HEADERSIZE + LOGFS_BLOCKSIZE)
+#define LOGFS_SEGMENT_RESERVE \
+ (LOGFS_SEGMENT_HEADERSIZE + LOGFS_MAX_OBJECTSIZE - 1)
+
+/*
+ * Segment types:
+ * SEG_SUPER - Data or indirect block
+ * SEG_JOURNAL - Inode
+ * SEG_OSTORE - Dentry
+ */
+enum {
+ SEG_SUPER = 0x01,
+ SEG_JOURNAL = 0x02,
+ SEG_OSTORE = 0x03,
+};
+
+/**
+ * struct logfs_segment_header - per-segment header in the ostore
+ *
+ * @crc: crc32 of header (there is no data)
+ * @pad: unused, must be 0
+ * @type: segment type, see above
+ * @level: GC level for all objects in this segment
+ * @segno: segment number
+ * @ec: erase count for this segment
+ * @gec: global erase count at time of writing
+ */
+struct logfs_segment_header {
+ __be32 crc;
+ __be16 pad;
+ __u8 type;
+ __u8 level;
+ __be32 segno;
+ __be32 ec;
+ __be64 gec;
+};
+
+SIZE_CHECK(logfs_segment_header, LOGFS_SEGMENT_HEADERSIZE);
+
+#define LOGFS_FEATURES_INCOMPAT (0ull)
+#define LOGFS_FEATURES_RO_COMPAT (0ull)
+#define LOGFS_FEATURES_COMPAT (0ull)
+
+/**
+ * struct logfs_disk_super - on-medium superblock
+ *
+ * @ds_magic: magic number, must equal LOGFS_MAGIC
+ * @ds_crc: crc32 of structure starting with the next field
+ * @ds_ifile_levels: maximum number of levels for ifile
+ * @ds_iblock_levels: maximum number of levels for regular files
+ * @ds_data_levels: number of seperate levels for data
+ * @pad0: reserved, must be 0
+ * @ds_feature_incompat: incompatible filesystem features
+ * @ds_feature_ro_compat: read-only compatible filesystem features
+ * @ds_feature_compat: compatible filesystem features
+ * @ds_flags: flags
+ * @ds_segment_shift: log2 of segment size
+ * @ds_block_shift: log2 of block size
+ * @ds_write_shift: log2 of write size
+ * @pad1: reserved, must be 0
+ * @ds_journal_seg: segments used by primary journal
+ * @ds_root_reserve: bytes reserved for the superuser
+ * @ds_speed_reserve: bytes reserved to speed up GC
+ * @ds_bad_seg_reserve: number of segments reserved to handle bad blocks
+ * @pad2: reserved, must be 0
+ * @pad3: reserved, must be 0
+ *
+ * Contains only read-only fields. Read-write fields like the amount of used
+ * space is tracked in the dynamic superblock, which is stored in the journal.
+ */
+struct logfs_disk_super {
+ struct logfs_segment_header ds_sh;
+ __be64 ds_magic;
+
+ __be32 ds_crc;
+ __u8 ds_ifile_levels;
+ __u8 ds_iblock_levels;
+ __u8 ds_data_levels;
+ __u8 ds_segment_shift;
+ __u8 ds_block_shift;
+ __u8 ds_write_shift;
+ __u8 pad0[6];
+
+ __be64 ds_filesystem_size;
+ __be32 ds_segment_size;
+ __be32 ds_bad_seg_reserve;
+
+ __be64 ds_feature_incompat;
+ __be64 ds_feature_ro_compat;
+
+ __be64 ds_feature_compat;
+ __be64 ds_feature_flags;
+
+ __be64 ds_root_reserve;
+ __be64 ds_speed_reserve;
+
+ __be32 ds_journal_seg[LOGFS_JOURNAL_SEGS];
+
+ __be64 ds_super_ofs[2];
+ __be64 pad3[8];
+};
+
+SIZE_CHECK(logfs_disk_super, 256);
+
+/*
+ * Object types:
+ * OBJ_BLOCK - Data or indirect block
+ * OBJ_INODE - Inode
+ * OBJ_DENTRY - Dentry
+ */
+enum {
+ OBJ_BLOCK = 0x04,
+ OBJ_INODE = 0x05,
+ OBJ_DENTRY = 0x06,
+};
+
+/**
+ * struct logfs_object_header - per-object header in the ostore
+ *
+ * @crc: crc32 of header, excluding data_crc
+ * @len: length of data
+ * @type: object type, see above
+ * @compr: compression type
+ * @ino: inode number
+ * @bix: block index
+ * @data_crc: crc32 of payload
+ */
+struct logfs_object_header {
+ __be32 crc;
+ __be16 len;
+ __u8 type;
+ __u8 compr;
+ __be64 ino;
+ __be64 bix;
+ __be32 data_crc;
+} __attribute__((packed));
+
+SIZE_CHECK(logfs_object_header, LOGFS_OBJECT_HEADERSIZE);
+
+/*
+ * Reserved inode numbers:
+ * LOGFS_INO_MASTER - master inode (for inode file)
+ * LOGFS_INO_ROOT - root directory
+ * LOGFS_INO_SEGFILE - per-segment used bytes and erase count
+ */
+enum {
+ LOGFS_INO_MAPPING = 0x00,
+ LOGFS_INO_MASTER = 0x01,
+ LOGFS_INO_ROOT = 0x02,
+ LOGFS_INO_SEGFILE = 0x03,
+ LOGFS_RESERVED_INOS = 0x10,
+};
+
+/*
+ * Inode flags. High bits should never be written to the medium. They are
+ * reserved for in-memory usage.
+ * Low bits should either remain in sync with the corresponding FS_*_FL or
+ * reuse slots that obviously don't make sense for logfs.
+ *
+ * LOGFS_IF_DIRTY Inode must be written back
+ * LOGFS_IF_ZOMBIE Inode has been deleted
+ * LOGFS_IF_STILLBORN -ENOSPC happened when creating inode
+ */
+#define LOGFS_IF_COMPRESSED 0x00000004 /* == FS_COMPR_FL */
+#define LOGFS_IF_DIRTY 0x20000000
+#define LOGFS_IF_ZOMBIE 0x40000000
+#define LOGFS_IF_STILLBORN 0x80000000
+
+/* Flags available to chattr */
+#define LOGFS_FL_USER_VISIBLE (LOGFS_IF_COMPRESSED)
+#define LOGFS_FL_USER_MODIFIABLE (LOGFS_IF_COMPRESSED)
+/* Flags inherited from parent directory on file/directory creation */
+#define LOGFS_FL_INHERITED (LOGFS_IF_COMPRESSED)
+
+/**
+ * struct logfs_disk_inode - on-medium inode
+ *
+ * @di_mode: file mode
+ * @di_pad: reserved, must be 0
+ * @di_flags: inode flags, see above
+ * @di_uid: user id
+ * @di_gid: group id
+ * @di_ctime: change time
+ * @di_mtime: modify time
+ * @di_refcount: reference count (aka nlink or link count)
+ * @di_generation: inode generation, for nfs
+ * @di_used_bytes: number of bytes used
+ * @di_size: file size
+ * @di_data: data pointers
+ */
+struct logfs_disk_inode {
+ __be16 di_mode;
+ __u8 di_height;
+ __u8 di_pad;
+ __be32 di_flags;
+ __be32 di_uid;
+ __be32 di_gid;
+
+ __be64 di_ctime;
+ __be64 di_mtime;
+
+ __be64 di_atime;
+ __be32 di_refcount;
+ __be32 di_generation;
+
+ __be64 di_used_bytes;
+ __be64 di_size;
+
+ __be64 di_data[LOGFS_EMBEDDED_FIELDS];
+};
+
+SIZE_CHECK(logfs_disk_inode, 200);
+
+#define INODE_POINTER_OFS \
+ (offsetof(struct logfs_disk_inode, di_data) / sizeof(__be64))
+#define INODE_USED_OFS \
+ (offsetof(struct logfs_disk_inode, di_used_bytes) / sizeof(__be64))
+#define INODE_SIZE_OFS \
+ (offsetof(struct logfs_disk_inode, di_size) / sizeof(__be64))
+#define INODE_HEIGHT_OFS (0)
+
+/**
+ * struct logfs_disk_dentry - on-medium dentry structure
+ *
+ * @ino: inode number
+ * @namelen: length of file name
+ * @type: file type, identical to bits 12..15 of mode
+ * @name: file name
+ */
+/* FIXME: add 6 bytes of padding to remove the __packed */
+struct logfs_disk_dentry {
+ __be64 ino;
+ __be16 namelen;
+ __u8 type;
+ __u8 name[LOGFS_MAX_NAMELEN];
+} __attribute__((packed));
+
+SIZE_CHECK(logfs_disk_dentry, 266);
+
+#define RESERVED 0xffffffff
+#define BADSEG 0xffffffff
+/**
+ * struct logfs_segment_entry - segment file entry
+ *
+ * @ec_level: erase count and level
+ * @valid: number of valid bytes
+ *
+ * Segment file contains one entry for every segment. ec_level contains the
+ * erasecount in the upper 28 bits and the level in the lower 4 bits. An
+ * ec_level of BADSEG (-1) identifies bad segments. valid contains the number
+ * of valid bytes or RESERVED (-1 again) if the segment is used for either the
+ * superblock or the journal, or when the segment is bad.
+ */
+struct logfs_segment_entry {
+ __be32 ec_level;
+ __be32 valid;
+};
+
+SIZE_CHECK(logfs_segment_entry, 8);
+
+/**
+ * struct logfs_journal_header - header for journal entries (JEs)
+ *
+ * @h_crc: crc32 of journal entry
+ * @h_len: length of compressed journal entry,
+ * not including header
+ * @h_datalen: length of uncompressed data
+ * @h_type: JE type
+ * @h_compr: compression type
+ * @h_pad: reserved
+ */
+struct logfs_journal_header {
+ __be32 h_crc;
+ __be16 h_len;
+ __be16 h_datalen;
+ __be16 h_type;
+ __u8 h_compr;
+ __u8 h_pad[5];
+};
+
+SIZE_CHECK(logfs_journal_header, 16);
+
+/*
+ * Life expectency of data.
+ * VIM_DEFAULT - default vim
+ * VIM_SEGFILE - for segment file only - very short-living
+ * VIM_GC - GC'd data - likely long-living
+ */
+enum logfs_vim {
+ VIM_DEFAULT = 0,
+ VIM_SEGFILE = 1,
+};
+
+/**
+ * struct logfs_je_area - wbuf header
+ *
+ * @segno: segment number of area
+ * @used_bytes: number of bytes already used
+ * @gc_level: GC level
+ * @vim: life expectancy of data
+ *
+ * "Areas" are segments currently being used for writing. There is at least
+ * one area per GC level. Several may be used to seperate long-living from
+ * short-living data. If an area with unknown vim is encountered, it can
+ * simply be closed.
+ * The write buffer immediately follow this header.
+ */
+struct logfs_je_area {
+ __be32 segno;
+ __be32 used_bytes;
+ __u8 gc_level;
+ __u8 vim;
+} __attribute__((packed));
+
+SIZE_CHECK(logfs_je_area, 10);
+
+#define MAX_JOURNAL_HEADER \
+ (sizeof(struct logfs_journal_header) + sizeof(struct logfs_je_area))
+
+/**
+ * struct logfs_je_dynsb - dynamic superblock
+ *
+ * @ds_gec: global erase count
+ * @ds_sweeper: current position of GC "sweeper"
+ * @ds_rename_dir: source directory ino (see dir.c documentation)
+ * @ds_rename_pos: position of source dd (see dir.c documentation)
+ * @ds_victim_ino: victims of incomplete dir operation (see dir.c)
+ * @ds_victim_ino: parent inode of victim (see dir.c)
+ * @ds_used_bytes: number of used bytes
+ */
+struct logfs_je_dynsb {
+ __be64 ds_gec;
+ __be64 ds_sweeper;
+
+ __be64 ds_rename_dir;
+ __be64 ds_rename_pos;
+
+ __be64 ds_victim_ino;
+ __be64 ds_victim_parent; /* XXX */
+
+ __be64 ds_used_bytes;
+ __be32 ds_generation;
+ __be32 pad;
+};
+
+SIZE_CHECK(logfs_je_dynsb, 64);
+
+/**
+ * struct logfs_je_anchor - anchor of filesystem tree, aka master inode
+ *
+ * @da_size: size of inode file
+ * @da_last_ino: last created inode
+ * @da_used_bytes: number of bytes used
+ * @da_data: data pointers
+ */
+struct logfs_je_anchor {
+ __be64 da_size;
+ __be64 da_last_ino;
+
+ __be64 da_used_bytes;
+ u8 da_height;
+ u8 pad[7];
+
+ __be64 da_data[LOGFS_EMBEDDED_FIELDS];
+};
+
+SIZE_CHECK(logfs_je_anchor, 168);
+
+/**
+ * struct logfs_je_spillout - spillout entry (from 1st to 2nd journal)
+ *
+ * @so_segment: segments used for 2nd journal
+ *
+ * Length of the array is given by h_len field in the header.
+ */
+struct logfs_je_spillout {
+ __be64 so_segment[0];
+};
+
+SIZE_CHECK(logfs_je_spillout, 0);
+
+/**
+ * struct logfs_je_journal_ec - erase counts for all journal segments
+ *
+ * @ec: erase count
+ *
+ * Length of the array is given by h_len field in the header.
+ */
+struct logfs_je_journal_ec {
+ __be32 ec[0];
+};
+
+SIZE_CHECK(logfs_je_journal_ec, 0);
+
+/**
+ * struct logfs_je_free_segments - list of free segmetns with erase count
+ */
+struct logfs_je_free_segments {
+ __be32 segno;
+ __be32 ec;
+};
+
+SIZE_CHECK(logfs_je_free_segments, 8);
+
+/**
+ * struct logfs_seg_alias - list of segment aliases
+ */
+struct logfs_seg_alias {
+ __be32 old_segno;
+ __be32 new_segno;
+};
+
+SIZE_CHECK(logfs_seg_alias, 8);
+
+/**
+ * struct logfs_obj_alias - list of object aliases
+ */
+struct logfs_obj_alias {
+ __be64 ino;
+ __be64 bix;
+ __be64 val;
+ u8 level;
+ u8 pad[5];
+ __be16 child_no;
+};
+
+SIZE_CHECK(logfs_obj_alias, 32);
+
+/**
+ * Compression types.
+ *
+ * COMPR_NONE - uncompressed
+ * COMPR_ZLIB - compressed with zlib
+ */
+enum {
+ COMPR_NONE = 0,
+ COMPR_ZLIB = 1,
+};
+
+/*
+ * Journal entries come in groups of 16. First group contains unique
+ * entries, next groups contain one entry per level
+ *
+ * JE_FIRST - smallest possible journal entry number
+ *
+ * JEG_BASE - base group, containing unique entries
+ * JE_COMMIT - commit entry, validates all previous entries
+ * JE_DYNSB - dynamic superblock, anything that ought to be in the
+ * superblock but cannot because it is read-write data
+ * JE_ANCHOR - anchor aka master inode aka inode file's inode
+ * JE_ERASECOUNT erasecounts for all journal segments
+ * JE_SPILLOUT - unused
+ * JE_SEG_ALIAS - aliases segments
+ * JE_AREA - area description
+ *
+ * JE_LAST - largest possible journal entry number
+ */
+enum {
+ JE_FIRST = 0x01,
+
+ JEG_BASE = 0x00,
+ JE_COMMIT = 0x02,
+ JE_DYNSB = 0x03,
+ JE_ANCHOR = 0x04,
+ JE_ERASECOUNT = 0x05,
+ JE_SPILLOUT = 0x06,
+ JE_OBJ_ALIAS = 0x0d,
+ JE_AREA = 0x0e,
+
+ JE_LAST = 0x0e,
+};
+
+#endif
diff --git a/fs/logfs/readwrite.c b/fs/logfs/readwrite.c
new file mode 100644
index 00000000000..7a23b3e7c0a
--- /dev/null
+++ b/fs/logfs/readwrite.c
@@ -0,0 +1,2246 @@
+/*
+ * fs/logfs/readwrite.c
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ *
+ *
+ * Actually contains five sets of very similar functions:
+ * read read blocks from a file
+ * seek_hole find next hole
+ * seek_data find next data block
+ * valid check whether a block still belongs to a file
+ * write write blocks to a file
+ * delete delete a block (for directories and ifile)
+ * rewrite move existing blocks of a file to a new location (gc helper)
+ * truncate truncate a file
+ */
+#include "logfs.h"
+#include <linux/sched.h>
+
+static u64 adjust_bix(u64 bix, level_t level)
+{
+ switch (level) {
+ case 0:
+ return bix;
+ case LEVEL(1):
+ return max_t(u64, bix, I0_BLOCKS);
+ case LEVEL(2):
+ return max_t(u64, bix, I1_BLOCKS);
+ case LEVEL(3):
+ return max_t(u64, bix, I2_BLOCKS);
+ case LEVEL(4):
+ return max_t(u64, bix, I3_BLOCKS);
+ case LEVEL(5):
+ return max_t(u64, bix, I4_BLOCKS);
+ default:
+ WARN_ON(1);
+ return bix;
+ }
+}
+
+static inline u64 maxbix(u8 height)
+{
+ return 1ULL << (LOGFS_BLOCK_BITS * height);
+}
+
+/**
+ * The inode address space is cut in two halves. Lower half belongs to data
+ * pages, upper half to indirect blocks. If the high bit (INDIRECT_BIT) is
+ * set, the actual block index (bix) and level can be derived from the page
+ * index.
+ *
+ * The lowest three bits of the block index are set to 0 after packing and
+ * unpacking. Since the lowest n bits (9 for 4KiB blocksize) are ignored
+ * anyway this is harmless.
+ */
+#define ARCH_SHIFT (BITS_PER_LONG - 32)
+#define INDIRECT_BIT (0x80000000UL << ARCH_SHIFT)
+#define LEVEL_SHIFT (28 + ARCH_SHIFT)
+static inline pgoff_t first_indirect_block(void)
+{
+ return INDIRECT_BIT | (1ULL << LEVEL_SHIFT);
+}
+
+pgoff_t logfs_pack_index(u64 bix, level_t level)
+{
+ pgoff_t index;
+
+ BUG_ON(bix >= INDIRECT_BIT);
+ if (level == 0)
+ return bix;
+
+ index = INDIRECT_BIT;
+ index |= (__force long)level << LEVEL_SHIFT;
+ index |= bix >> ((__force u8)level * LOGFS_BLOCK_BITS);
+ return index;
+}
+
+void logfs_unpack_index(pgoff_t index, u64 *bix, level_t *level)
+{
+ u8 __level;
+
+ if (!(index & INDIRECT_BIT)) {
+ *bix = index;
+ *level = 0;
+ return;
+ }
+
+ __level = (index & ~INDIRECT_BIT) >> LEVEL_SHIFT;
+ *level = LEVEL(__level);
+ *bix = (index << (__level * LOGFS_BLOCK_BITS)) & ~INDIRECT_BIT;
+ *bix = adjust_bix(*bix, *level);
+ return;
+}
+#undef ARCH_SHIFT
+#undef INDIRECT_BIT
+#undef LEVEL_SHIFT
+
+/*
+ * Time is stored as nanoseconds since the epoch.
+ */
+static struct timespec be64_to_timespec(__be64 betime)
+{
+ return ns_to_timespec(be64_to_cpu(betime));
+}
+
+static __be64 timespec_to_be64(struct timespec tsp)
+{
+ return cpu_to_be64((u64)tsp.tv_sec * NSEC_PER_SEC + tsp.tv_nsec);
+}
+
+static void logfs_disk_to_inode(struct logfs_disk_inode *di, struct inode*inode)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+ int i;
+
+ inode->i_mode = be16_to_cpu(di->di_mode);
+ li->li_height = di->di_height;
+ li->li_flags = be32_to_cpu(di->di_flags);
+ inode->i_uid = be32_to_cpu(di->di_uid);
+ inode->i_gid = be32_to_cpu(di->di_gid);
+ inode->i_size = be64_to_cpu(di->di_size);
+ logfs_set_blocks(inode, be64_to_cpu(di->di_used_bytes));
+ inode->i_atime = be64_to_timespec(di->di_atime);
+ inode->i_ctime = be64_to_timespec(di->di_ctime);
+ inode->i_mtime = be64_to_timespec(di->di_mtime);
+ inode->i_nlink = be32_to_cpu(di->di_refcount);
+ inode->i_generation = be32_to_cpu(di->di_generation);
+
+ switch (inode->i_mode & S_IFMT) {
+ case S_IFSOCK: /* fall through */
+ case S_IFBLK: /* fall through */
+ case S_IFCHR: /* fall through */
+ case S_IFIFO:
+ inode->i_rdev = be64_to_cpu(di->di_data[0]);
+ break;
+ case S_IFDIR: /* fall through */
+ case S_IFREG: /* fall through */
+ case S_IFLNK:
+ for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++)
+ li->li_data[i] = be64_to_cpu(di->di_data[i]);
+ break;
+ default:
+ BUG();
+ }
+}
+
+static void logfs_inode_to_disk(struct inode *inode, struct logfs_disk_inode*di)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+ int i;
+
+ di->di_mode = cpu_to_be16(inode->i_mode);
+ di->di_height = li->li_height;
+ di->di_pad = 0;
+ di->di_flags = cpu_to_be32(li->li_flags);
+ di->di_uid = cpu_to_be32(inode->i_uid);
+ di->di_gid = cpu_to_be32(inode->i_gid);
+ di->di_size = cpu_to_be64(i_size_read(inode));
+ di->di_used_bytes = cpu_to_be64(li->li_used_bytes);
+ di->di_atime = timespec_to_be64(inode->i_atime);
+ di->di_ctime = timespec_to_be64(inode->i_ctime);
+ di->di_mtime = timespec_to_be64(inode->i_mtime);
+ di->di_refcount = cpu_to_be32(inode->i_nlink);
+ di->di_generation = cpu_to_be32(inode->i_generation);
+
+ switch (inode->i_mode & S_IFMT) {
+ case S_IFSOCK: /* fall through */
+ case S_IFBLK: /* fall through */
+ case S_IFCHR: /* fall through */
+ case S_IFIFO:
+ di->di_data[0] = cpu_to_be64(inode->i_rdev);
+ break;
+ case S_IFDIR: /* fall through */
+ case S_IFREG: /* fall through */
+ case S_IFLNK:
+ for (i = 0; i < LOGFS_EMBEDDED_FIELDS; i++)
+ di->di_data[i] = cpu_to_be64(li->li_data[i]);
+ break;
+ default:
+ BUG();
+ }
+}
+
+static void __logfs_set_blocks(struct inode *inode)
+{
+ struct super_block *sb = inode->i_sb;
+ struct logfs_inode *li = logfs_inode(inode);
+
+ inode->i_blocks = ULONG_MAX;
+ if (li->li_used_bytes >> sb->s_blocksize_bits < ULONG_MAX)
+ inode->i_blocks = ALIGN(li->li_used_bytes, 512) >> 9;
+}
+
+void logfs_set_blocks(struct inode *inode, u64 bytes)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+
+ li->li_used_bytes = bytes;
+ __logfs_set_blocks(inode);
+}
+
+static void prelock_page(struct super_block *sb, struct page *page, int lock)
+{
+ struct logfs_super *super = logfs_super(sb);
+
+ BUG_ON(!PageLocked(page));
+ if (lock) {
+ BUG_ON(PagePreLocked(page));
+ SetPagePreLocked(page);
+ } else {
+ /* We are in GC path. */
+ if (PagePreLocked(page))
+ super->s_lock_count++;
+ else
+ SetPagePreLocked(page);
+ }
+}
+
+static void preunlock_page(struct super_block *sb, struct page *page, int lock)
+{
+ struct logfs_super *super = logfs_super(sb);
+
+ BUG_ON(!PageLocked(page));
+ if (lock)
+ ClearPagePreLocked(page);
+ else {
+ /* We are in GC path. */
+ BUG_ON(!PagePreLocked(page));
+ if (super->s_lock_count)
+ super->s_lock_count--;
+ else
+ ClearPagePreLocked(page);
+ }
+}
+
+/*
+ * Logfs is prone to an AB-BA deadlock where one task tries to acquire
+ * s_write_mutex with a locked page and GC tries to get that page while holding
+ * s_write_mutex.
+ * To solve this issue logfs will ignore the page lock iff the page in question
+ * is waiting for s_write_mutex. We annotate this fact by setting PG_pre_locked
+ * in addition to PG_locked.
+ */
+static void logfs_get_wblocks(struct super_block *sb, struct page *page,
+ int lock)
+{
+ struct logfs_super *super = logfs_super(sb);
+
+ if (page)
+ prelock_page(sb, page, lock);
+
+ if (lock) {
+ mutex_lock(&super->s_write_mutex);
+ logfs_gc_pass(sb);
+ /* FIXME: We also have to check for shadowed space
+ * and mempool fill grade */
+ }
+}
+
+static void logfs_put_wblocks(struct super_block *sb, struct page *page,
+ int lock)
+{
+ struct logfs_super *super = logfs_super(sb);
+
+ if (page)
+ preunlock_page(sb, page, lock);
+ /* Order matters - we must clear PG_pre_locked before releasing
+ * s_write_mutex or we could race against another task. */
+ if (lock)
+ mutex_unlock(&super->s_write_mutex);
+}
+
+static struct page *logfs_get_read_page(struct inode *inode, u64 bix,
+ level_t level)
+{
+ return find_or_create_page(inode->i_mapping,
+ logfs_pack_index(bix, level), GFP_NOFS);
+}
+
+static void logfs_put_read_page(struct page *page)
+{
+ unlock_page(page);
+ page_cache_release(page);
+}
+
+static void logfs_lock_write_page(struct page *page)
+{
+ int loop = 0;
+
+ while (unlikely(!trylock_page(page))) {
+ if (loop++ > 0x1000) {
+ /* Has been observed once so far... */
+ printk(KERN_ERR "stack at %p\n", &loop);
+ BUG();
+ }
+ if (PagePreLocked(page)) {
+ /* Holder of page lock is waiting for us, it
+ * is safe to use this page. */
+ break;
+ }
+ /* Some other process has this page locked and has
+ * nothing to do with us. Wait for it to finish.
+ */
+ schedule();
+ }
+ BUG_ON(!PageLocked(page));
+}
+
+static struct page *logfs_get_write_page(struct inode *inode, u64 bix,
+ level_t level)
+{
+ struct address_space *mapping = inode->i_mapping;
+ pgoff_t index = logfs_pack_index(bix, level);
+ struct page *page;
+ int err;
+
+repeat:
+ page = find_get_page(mapping, index);
+ if (!page) {
+ page = __page_cache_alloc(GFP_NOFS);
+ if (!page)
+ return NULL;
+ err = add_to_page_cache_lru(page, mapping, index, GFP_NOFS);
+ if (unlikely(err)) {
+ page_cache_release(page);
+ if (err == -EEXIST)
+ goto repeat;
+ return NULL;
+ }
+ } else logfs_lock_write_page(page);
+ BUG_ON(!PageLocked(page));
+ return page;
+}
+
+static void logfs_unlock_write_page(struct page *page)
+{
+ if (!PagePreLocked(page))
+ unlock_page(page);
+}
+
+static void logfs_put_write_page(struct page *page)
+{
+ logfs_unlock_write_page(page);
+ page_cache_release(page);
+}
+
+static struct page *logfs_get_page(struct inode *inode, u64 bix, level_t level,
+ int rw)
+{
+ if (rw == READ)
+ return logfs_get_read_page(inode, bix, level);
+ else
+ return logfs_get_write_page(inode, bix, level);
+}
+
+static void logfs_put_page(struct page *page, int rw)
+{
+ if (rw == READ)
+ logfs_put_read_page(page);
+ else
+ logfs_put_write_page(page);
+}
+
+static unsigned long __get_bits(u64 val, int skip, int no)
+{
+ u64 ret = val;
+
+ ret >>= skip * no;
+ ret <<= 64 - no;
+ ret >>= 64 - no;
+ return ret;
+}
+
+static unsigned long get_bits(u64 val, level_t skip)
+{
+ return __get_bits(val, (__force int)skip, LOGFS_BLOCK_BITS);
+}
+
+static inline void init_shadow_tree(struct super_block *sb,
+ struct shadow_tree *tree)
+{
+ struct logfs_super *super = logfs_super(sb);
+
+ btree_init_mempool64(&tree->new, super->s_btree_pool);
+ btree_init_mempool64(&tree->old, super->s_btree_pool);
+}
+
+static void indirect_write_block(struct logfs_block *block)
+{
+ struct page *page;
+ struct inode *inode;
+ int ret;
+
+ page = block->page;
+ inode = page->mapping->host;
+ logfs_lock_write_page(page);
+ ret = logfs_write_buf(inode, page, 0);
+ logfs_unlock_write_page(page);
+ /*
+ * This needs some rework. Unless you want your filesystem to run
+ * completely synchronously (you don't), the filesystem will always
+ * report writes as 'successful' before the actual work has been
+ * done. The actual work gets done here and this is where any errors
+ * will show up. And there isn't much we can do about it, really.
+ *
+ * Some attempts to fix the errors (move from bad blocks, retry io,...)
+ * have already been done, so anything left should be either a broken
+ * device or a bug somewhere in logfs itself. Being relatively new,
+ * the odds currently favor a bug, so for now the line below isn't
+ * entirely tasteles.
+ */
+ BUG_ON(ret);
+}
+
+static void inode_write_block(struct logfs_block *block)
+{
+ struct inode *inode;
+ int ret;
+
+ inode = block->inode;
+ if (inode->i_ino == LOGFS_INO_MASTER)
+ logfs_write_anchor(inode->i_sb);
+ else {
+ ret = __logfs_write_inode(inode, 0);
+ /* see indirect_write_block comment */
+ BUG_ON(ret);
+ }
+}
+
+static gc_level_t inode_block_level(struct logfs_block *block)
+{
+ BUG_ON(block->inode->i_ino == LOGFS_INO_MASTER);
+ return GC_LEVEL(LOGFS_MAX_LEVELS);
+}
+
+static gc_level_t indirect_block_level(struct logfs_block *block)
+{
+ struct page *page;
+ struct inode *inode;
+ u64 bix;
+ level_t level;
+
+ page = block->page;
+ inode = page->mapping->host;
+ logfs_unpack_index(page->index, &bix, &level);
+ return expand_level(inode->i_ino, level);
+}
+
+/*
+ * This silences a false, yet annoying gcc warning. I hate it when my editor
+ * jumps into bitops.h each time I recompile this file.
+ * TODO: Complain to gcc folks about this and upgrade compiler.
+ */
+static unsigned long fnb(const unsigned long *addr,
+ unsigned long size, unsigned long offset)
+{
+ return find_next_bit(addr, size, offset);
+}
+
+static __be64 inode_val0(struct inode *inode)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+ u64 val;
+
+ /*
+ * Explicit shifting generates good code, but must match the format
+ * of the structure. Add some paranoia just in case.
+ */
+ BUILD_BUG_ON(offsetof(struct logfs_disk_inode, di_mode) != 0);
+ BUILD_BUG_ON(offsetof(struct logfs_disk_inode, di_height) != 2);
+ BUILD_BUG_ON(offsetof(struct logfs_disk_inode, di_flags) != 4);
+
+ val = (u64)inode->i_mode << 48 |
+ (u64)li->li_height << 40 |
+ (u64)li->li_flags;
+ return cpu_to_be64(val);
+}
+
+static int inode_write_alias(struct super_block *sb,
+ struct logfs_block *block, write_alias_t *write_one_alias)
+{
+ struct inode *inode = block->inode;
+ struct logfs_inode *li = logfs_inode(inode);
+ unsigned long pos;
+ u64 ino , bix;
+ __be64 val;
+ level_t level;
+ int err;
+
+ for (pos = 0; ; pos++) {
+ pos = fnb(block->alias_map, LOGFS_BLOCK_FACTOR, pos);
+ if (pos >= LOGFS_EMBEDDED_FIELDS + INODE_POINTER_OFS)
+ return 0;
+
+ switch (pos) {
+ case INODE_HEIGHT_OFS:
+ val = inode_val0(inode);
+ break;
+ case INODE_USED_OFS:
+ val = cpu_to_be64(li->li_used_bytes);;
+ break;
+ case INODE_SIZE_OFS:
+ val = cpu_to_be64(i_size_read(inode));
+ break;
+ case INODE_POINTER_OFS ... INODE_POINTER_OFS + LOGFS_EMBEDDED_FIELDS - 1:
+ val = cpu_to_be64(li->li_data[pos - INODE_POINTER_OFS]);
+ break;
+ default:
+ BUG();
+ }
+
+ ino = LOGFS_INO_MASTER;
+ bix = inode->i_ino;
+ level = LEVEL(0);
+ err = write_one_alias(sb, ino, bix, level, pos, val);
+ if (err)
+ return err;
+ }
+}
+
+static int indirect_write_alias(struct super_block *sb,
+ struct logfs_block *block, write_alias_t *write_one_alias)
+{
+ unsigned long pos;
+ struct page *page = block->page;
+ u64 ino , bix;
+ __be64 *child, val;
+ level_t level;
+ int err;
+
+ for (pos = 0; ; pos++) {
+ pos = fnb(block->alias_map, LOGFS_BLOCK_FACTOR, pos);
+ if (pos >= LOGFS_BLOCK_FACTOR)
+ return 0;
+
+ ino = page->mapping->host->i_ino;
+ logfs_unpack_index(page->index, &bix, &level);
+ child = kmap_atomic(page, KM_USER0);
+ val = child[pos];
+ kunmap_atomic(child, KM_USER0);
+ err = write_one_alias(sb, ino, bix, level, pos, val);
+ if (err)
+ return err;
+ }
+}
+
+int logfs_write_obj_aliases_pagecache(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_block *block;
+ int err;
+
+ list_for_each_entry(block, &super->s_object_alias, alias_list) {
+ err = block->ops->write_alias(sb, block, write_alias_journal);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+void __free_block(struct super_block *sb, struct logfs_block *block)
+{
+ BUG_ON(!list_empty(&block->item_list));
+ list_del(&block->alias_list);
+ mempool_free(block, logfs_super(sb)->s_block_pool);
+}
+
+static void inode_free_block(struct super_block *sb, struct logfs_block *block)
+{
+ struct inode *inode = block->inode;
+
+ logfs_inode(inode)->li_block = NULL;
+ __free_block(sb, block);
+}
+
+static void indirect_free_block(struct super_block *sb,
+ struct logfs_block *block)
+{
+ ClearPagePrivate(block->page);
+ block->page->private = 0;
+ __free_block(sb, block);
+}
+
+
+static struct logfs_block_ops inode_block_ops = {
+ .write_block = inode_write_block,
+ .block_level = inode_block_level,
+ .free_block = inode_free_block,
+ .write_alias = inode_write_alias,
+};
+
+struct logfs_block_ops indirect_block_ops = {
+ .write_block = indirect_write_block,
+ .block_level = indirect_block_level,
+ .free_block = indirect_free_block,
+ .write_alias = indirect_write_alias,
+};
+
+struct logfs_block *__alloc_block(struct super_block *sb,
+ u64 ino, u64 bix, level_t level)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_block *block;
+
+ block = mempool_alloc(super->s_block_pool, GFP_NOFS);
+ memset(block, 0, sizeof(*block));
+ INIT_LIST_HEAD(&block->alias_list);
+ INIT_LIST_HEAD(&block->item_list);
+ block->sb = sb;
+ block->ino = ino;
+ block->bix = bix;
+ block->level = level;
+ return block;
+}
+
+static void alloc_inode_block(struct inode *inode)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+ struct logfs_block *block;
+
+ if (li->li_block)
+ return;
+
+ block = __alloc_block(inode->i_sb, LOGFS_INO_MASTER, inode->i_ino, 0);
+ block->inode = inode;
+ li->li_block = block;
+ block->ops = &inode_block_ops;
+}
+
+void initialize_block_counters(struct page *page, struct logfs_block *block,
+ __be64 *array, int page_is_empty)
+{
+ u64 ptr;
+ int i, start;
+
+ block->partial = 0;
+ block->full = 0;
+ start = 0;
+ if (page->index < first_indirect_block()) {
+ /* Counters are pointless on level 0 */
+ return;
+ }
+ if (page->index == first_indirect_block()) {
+ /* Skip unused pointers */
+ start = I0_BLOCKS;
+ block->full = I0_BLOCKS;
+ }
+ if (!page_is_empty) {
+ for (i = start; i < LOGFS_BLOCK_FACTOR; i++) {
+ ptr = be64_to_cpu(array[i]);
+ if (ptr)
+ block->partial++;
+ if (ptr & LOGFS_FULLY_POPULATED)
+ block->full++;
+ }
+ }
+}
+
+static void alloc_data_block(struct inode *inode, struct page *page)
+{
+ struct logfs_block *block;
+ u64 bix;
+ level_t level;
+
+ if (PagePrivate(page))
+ return;
+
+ logfs_unpack_index(page->index, &bix, &level);
+ block = __alloc_block(inode->i_sb, inode->i_ino, bix, level);
+ block->page = page;
+ SetPagePrivate(page);
+ page->private = (unsigned long)block;
+ block->ops = &indirect_block_ops;
+}
+
+static void alloc_indirect_block(struct inode *inode, struct page *page,
+ int page_is_empty)
+{
+ struct logfs_block *block;
+ __be64 *array;
+
+ if (PagePrivate(page))
+ return;
+
+ alloc_data_block(inode, page);
+
+ block = logfs_block(page);
+ array = kmap_atomic(page, KM_USER0);
+ initialize_block_counters(page, block, array, page_is_empty);
+ kunmap_atomic(array, KM_USER0);
+}
+
+static void block_set_pointer(struct page *page, int index, u64 ptr)
+{
+ struct logfs_block *block = logfs_block(page);
+ __be64 *array;
+ u64 oldptr;
+
+ BUG_ON(!block);
+ array = kmap_atomic(page, KM_USER0);
+ oldptr = be64_to_cpu(array[index]);
+ array[index] = cpu_to_be64(ptr);
+ kunmap_atomic(array, KM_USER0);
+ SetPageUptodate(page);
+
+ block->full += !!(ptr & LOGFS_FULLY_POPULATED)
+ - !!(oldptr & LOGFS_FULLY_POPULATED);
+ block->partial += !!ptr - !!oldptr;
+}
+
+static u64 block_get_pointer(struct page *page, int index)
+{
+ __be64 *block;
+ u64 ptr;
+
+ block = kmap_atomic(page, KM_USER0);
+ ptr = be64_to_cpu(block[index]);
+ kunmap_atomic(block, KM_USER0);
+ return ptr;
+}
+
+static int logfs_read_empty(struct page *page)
+{
+ zero_user_segment(page, 0, PAGE_CACHE_SIZE);
+ return 0;
+}
+
+static int logfs_read_direct(struct inode *inode, struct page *page)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+ pgoff_t index = page->index;
+ u64 block;
+
+ block = li->li_data[index];
+ if (!block)
+ return logfs_read_empty(page);
+
+ return logfs_segment_read(inode, page, block, index, 0);
+}
+
+static int logfs_read_loop(struct inode *inode, struct page *page,
+ int rw_context)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+ u64 bix, bofs = li->li_data[INDIRECT_INDEX];
+ level_t level, target_level;
+ int ret;
+ struct page *ipage;
+
+ logfs_unpack_index(page->index, &bix, &target_level);
+ if (!bofs)
+ return logfs_read_empty(page);
+
+ if (bix >= maxbix(li->li_height))
+ return logfs_read_empty(page);
+
+ for (level = LEVEL(li->li_height);
+ (__force u8)level > (__force u8)target_level;
+ level = SUBLEVEL(level)){
+ ipage = logfs_get_page(inode, bix, level, rw_context);
+ if (!ipage)
+ return -ENOMEM;
+
+ ret = logfs_segment_read(inode, ipage, bofs, bix, level);
+ if (ret) {
+ logfs_put_read_page(ipage);
+ return ret;
+ }
+
+ bofs = block_get_pointer(ipage, get_bits(bix, SUBLEVEL(level)));
+ logfs_put_page(ipage, rw_context);
+ if (!bofs)
+ return logfs_read_empty(page);
+ }
+
+ return logfs_segment_read(inode, page, bofs, bix, 0);
+}
+
+static int logfs_read_block(struct inode *inode, struct page *page,
+ int rw_context)
+{
+ pgoff_t index = page->index;
+
+ if (index < I0_BLOCKS)
+ return logfs_read_direct(inode, page);
+ return logfs_read_loop(inode, page, rw_context);
+}
+
+static int logfs_exist_loop(struct inode *inode, u64 bix)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+ u64 bofs = li->li_data[INDIRECT_INDEX];
+ level_t level;
+ int ret;
+ struct page *ipage;
+
+ if (!bofs)
+ return 0;
+ if (bix >= maxbix(li->li_height))
+ return 0;
+
+ for (level = LEVEL(li->li_height); level != 0; level = SUBLEVEL(level)) {
+ ipage = logfs_get_read_page(inode, bix, level);
+ if (!ipage)
+ return -ENOMEM;
+
+ ret = logfs_segment_read(inode, ipage, bofs, bix, level);
+ if (ret) {
+ logfs_put_read_page(ipage);
+ return ret;
+ }
+
+ bofs = block_get_pointer(ipage, get_bits(bix, SUBLEVEL(level)));
+ logfs_put_read_page(ipage);
+ if (!bofs)
+ return 0;
+ }
+
+ return 1;
+}
+
+int logfs_exist_block(struct inode *inode, u64 bix)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+
+ if (bix < I0_BLOCKS)
+ return !!li->li_data[bix];
+ return logfs_exist_loop(inode, bix);
+}
+
+static u64 seek_holedata_direct(struct inode *inode, u64 bix, int data)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+
+ for (; bix < I0_BLOCKS; bix++)
+ if (data ^ (li->li_data[bix] == 0))
+ return bix;
+ return I0_BLOCKS;
+}
+
+static u64 seek_holedata_loop(struct inode *inode, u64 bix, int data)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+ __be64 *rblock;
+ u64 increment, bofs = li->li_data[INDIRECT_INDEX];
+ level_t level;
+ int ret, slot;
+ struct page *page;
+
+ BUG_ON(!bofs);
+
+ for (level = LEVEL(li->li_height); level != 0; level = SUBLEVEL(level)) {
+ increment = 1 << (LOGFS_BLOCK_BITS * ((__force u8)level-1));
+ page = logfs_get_read_page(inode, bix, level);
+ if (!page)
+ return bix;
+
+ ret = logfs_segment_read(inode, page, bofs, bix, level);
+ if (ret) {
+ logfs_put_read_page(page);
+ return bix;
+ }
+
+ slot = get_bits(bix, SUBLEVEL(level));
+ rblock = kmap_atomic(page, KM_USER0);
+ while (slot < LOGFS_BLOCK_FACTOR) {
+ if (data && (rblock[slot] != 0))
+ break;
+ if (!data && !(be64_to_cpu(rblock[slot]) & LOGFS_FULLY_POPULATED))
+ break;
+ slot++;
+ bix += increment;
+ bix &= ~(increment - 1);
+ }
+ if (slot >= LOGFS_BLOCK_FACTOR) {
+ kunmap_atomic(rblock, KM_USER0);
+ logfs_put_read_page(page);
+ return bix;
+ }
+ bofs = be64_to_cpu(rblock[slot]);
+ kunmap_atomic(rblock, KM_USER0);
+ logfs_put_read_page(page);
+ if (!bofs) {
+ BUG_ON(data);
+ return bix;
+ }
+ }
+ return bix;
+}
+
+/**
+ * logfs_seek_hole - find next hole starting at a given block index
+ * @inode: inode to search in
+ * @bix: block index to start searching
+ *
+ * Returns next hole. If the file doesn't contain any further holes, the
+ * block address next to eof is returned instead.
+ */
+u64 logfs_seek_hole(struct inode *inode, u64 bix)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+
+ if (bix < I0_BLOCKS) {
+ bix = seek_holedata_direct(inode, bix, 0);
+ if (bix < I0_BLOCKS)
+ return bix;
+ }
+
+ if (!li->li_data[INDIRECT_INDEX])
+ return bix;
+ else if (li->li_data[INDIRECT_INDEX] & LOGFS_FULLY_POPULATED)
+ bix = maxbix(li->li_height);
+ else {
+ bix = seek_holedata_loop(inode, bix, 0);
+ if (bix < maxbix(li->li_height))
+ return bix;
+ /* Should not happen anymore. But if some port writes semi-
+ * corrupt images (as this one used to) we might run into it.
+ */
+ WARN_ON_ONCE(bix == maxbix(li->li_height));
+ }
+
+ return bix;
+}
+
+static u64 __logfs_seek_data(struct inode *inode, u64 bix)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+
+ if (bix < I0_BLOCKS) {
+ bix = seek_holedata_direct(inode, bix, 1);
+ if (bix < I0_BLOCKS)
+ return bix;
+ }
+
+ if (bix < maxbix(li->li_height)) {
+ if (!li->li_data[INDIRECT_INDEX])
+ bix = maxbix(li->li_height);
+ else
+ return seek_holedata_loop(inode, bix, 1);
+ }
+
+ return bix;
+}
+
+/**
+ * logfs_seek_data - find next data block after a given block index
+ * @inode: inode to search in
+ * @bix: block index to start searching
+ *
+ * Returns next data block. If the file doesn't contain any further data
+ * blocks, the last block in the file is returned instead.
+ */
+u64 logfs_seek_data(struct inode *inode, u64 bix)
+{
+ struct super_block *sb = inode->i_sb;
+ u64 ret, end;
+
+ ret = __logfs_seek_data(inode, bix);
+ end = i_size_read(inode) >> sb->s_blocksize_bits;
+ if (ret >= end)
+ ret = max(bix, end);
+ return ret;
+}
+
+static int logfs_is_valid_direct(struct logfs_inode *li, u64 bix, u64 ofs)
+{
+ return pure_ofs(li->li_data[bix]) == ofs;
+}
+
+static int __logfs_is_valid_loop(struct inode *inode, u64 bix,
+ u64 ofs, u64 bofs)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+ level_t level;
+ int ret;
+ struct page *page;
+
+ for (level = LEVEL(li->li_height); level != 0; level = SUBLEVEL(level)){
+ page = logfs_get_write_page(inode, bix, level);
+ BUG_ON(!page);
+
+ ret = logfs_segment_read(inode, page, bofs, bix, level);
+ if (ret) {
+ logfs_put_write_page(page);
+ return 0;
+ }
+
+ bofs = block_get_pointer(page, get_bits(bix, SUBLEVEL(level)));
+ logfs_put_write_page(page);
+ if (!bofs)
+ return 0;
+
+ if (pure_ofs(bofs) == ofs)
+ return 1;
+ }
+ return 0;
+}
+
+static int logfs_is_valid_loop(struct inode *inode, u64 bix, u64 ofs)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+ u64 bofs = li->li_data[INDIRECT_INDEX];
+
+ if (!bofs)
+ return 0;
+
+ if (bix >= maxbix(li->li_height))
+ return 0;
+
+ if (pure_ofs(bofs) == ofs)
+ return 1;
+
+ return __logfs_is_valid_loop(inode, bix, ofs, bofs);
+}
+
+static int __logfs_is_valid_block(struct inode *inode, u64 bix, u64 ofs)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+
+ if ((inode->i_nlink == 0) && atomic_read(&inode->i_count) == 1)
+ return 0;
+
+ if (bix < I0_BLOCKS)
+ return logfs_is_valid_direct(li, bix, ofs);
+ return logfs_is_valid_loop(inode, bix, ofs);
+}
+
+/**
+ * logfs_is_valid_block - check whether this block is still valid
+ *
+ * @sb - superblock
+ * @ofs - block physical offset
+ * @ino - block inode number
+ * @bix - block index
+ * @level - block level
+ *
+ * Returns 0 if the block is invalid, 1 if it is valid and 2 if it will
+ * become invalid once the journal is written.
+ */
+int logfs_is_valid_block(struct super_block *sb, u64 ofs, u64 ino, u64 bix,
+ gc_level_t gc_level)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct inode *inode;
+ int ret, cookie;
+
+ /* Umount closes a segment with free blocks remaining. Those
+ * blocks are by definition invalid. */
+ if (ino == -1)
+ return 0;
+
+ LOGFS_BUG_ON((u64)(u_long)ino != ino, sb);
+
+ inode = logfs_safe_iget(sb, ino, &cookie);
+ if (IS_ERR(inode))
+ goto invalid;
+
+ ret = __logfs_is_valid_block(inode, bix, ofs);
+ logfs_safe_iput(inode, cookie);
+ if (ret)
+ return ret;
+
+invalid:
+ /* Block is nominally invalid, but may still sit in the shadow tree,
+ * waiting for a journal commit.
+ */
+ if (btree_lookup64(&super->s_shadow_tree.old, ofs))
+ return 2;
+ return 0;
+}
+
+int logfs_readpage_nolock(struct page *page)
+{
+ struct inode *inode = page->mapping->host;
+ int ret = -EIO;
+
+ ret = logfs_read_block(inode, page, READ);
+
+ if (ret) {
+ ClearPageUptodate(page);
+ SetPageError(page);
+ } else {
+ SetPageUptodate(page);
+ ClearPageError(page);
+ }
+ flush_dcache_page(page);
+
+ return ret;
+}
+
+static int logfs_reserve_bytes(struct inode *inode, int bytes)
+{
+ struct logfs_super *super = logfs_super(inode->i_sb);
+ u64 available = super->s_free_bytes + super->s_dirty_free_bytes
+ - super->s_dirty_used_bytes - super->s_dirty_pages;
+
+ if (!bytes)
+ return 0;
+
+ if (available < bytes)
+ return -ENOSPC;
+
+ if (available < bytes + super->s_root_reserve &&
+ !capable(CAP_SYS_RESOURCE))
+ return -ENOSPC;
+
+ return 0;
+}
+
+int get_page_reserve(struct inode *inode, struct page *page)
+{
+ struct logfs_super *super = logfs_super(inode->i_sb);
+ int ret;
+
+ if (logfs_block(page) && logfs_block(page)->reserved_bytes)
+ return 0;
+
+ logfs_get_wblocks(inode->i_sb, page, WF_LOCK);
+ ret = logfs_reserve_bytes(inode, 6 * LOGFS_MAX_OBJECTSIZE);
+ if (!ret) {
+ alloc_data_block(inode, page);
+ logfs_block(page)->reserved_bytes += 6 * LOGFS_MAX_OBJECTSIZE;
+ super->s_dirty_pages += 6 * LOGFS_MAX_OBJECTSIZE;
+ }
+ logfs_put_wblocks(inode->i_sb, page, WF_LOCK);
+ return ret;
+}
+
+/*
+ * We are protected by write lock. Push victims up to superblock level
+ * and release transaction when appropriate.
+ */
+/* FIXME: This is currently called from the wrong spots. */
+static void logfs_handle_transaction(struct inode *inode,
+ struct logfs_transaction *ta)
+{
+ struct logfs_super *super = logfs_super(inode->i_sb);
+
+ if (!ta)
+ return;
+ logfs_inode(inode)->li_block->ta = NULL;
+
+ if (inode->i_ino != LOGFS_INO_MASTER) {
+ BUG(); /* FIXME: Yes, this needs more thought */
+ /* just remember the transaction until inode is written */
+ //BUG_ON(logfs_inode(inode)->li_transaction);
+ //logfs_inode(inode)->li_transaction = ta;
+ return;
+ }
+
+ switch (ta->state) {
+ case CREATE_1: /* fall through */
+ case UNLINK_1:
+ BUG_ON(super->s_victim_ino);
+ super->s_victim_ino = ta->ino;
+ break;
+ case CREATE_2: /* fall through */
+ case UNLINK_2:
+ BUG_ON(super->s_victim_ino != ta->ino);
+ super->s_victim_ino = 0;
+ /* transaction ends here - free it */
+ kfree(ta);
+ break;
+ case CROSS_RENAME_1:
+ BUG_ON(super->s_rename_dir);
+ BUG_ON(super->s_rename_pos);
+ super->s_rename_dir = ta->dir;
+ super->s_rename_pos = ta->pos;
+ break;
+ case CROSS_RENAME_2:
+ BUG_ON(super->s_rename_dir != ta->dir);
+ BUG_ON(super->s_rename_pos != ta->pos);
+ super->s_rename_dir = 0;
+ super->s_rename_pos = 0;
+ kfree(ta);
+ break;
+ case TARGET_RENAME_1:
+ BUG_ON(super->s_rename_dir);
+ BUG_ON(super->s_rename_pos);
+ BUG_ON(super->s_victim_ino);
+ super->s_rename_dir = ta->dir;
+ super->s_rename_pos = ta->pos;
+ super->s_victim_ino = ta->ino;
+ break;
+ case TARGET_RENAME_2:
+ BUG_ON(super->s_rename_dir != ta->dir);
+ BUG_ON(super->s_rename_pos != ta->pos);
+ BUG_ON(super->s_victim_ino != ta->ino);
+ super->s_rename_dir = 0;
+ super->s_rename_pos = 0;
+ break;
+ case TARGET_RENAME_3:
+ BUG_ON(super->s_rename_dir);
+ BUG_ON(super->s_rename_pos);
+ BUG_ON(super->s_victim_ino != ta->ino);
+ super->s_victim_ino = 0;
+ kfree(ta);
+ break;
+ default:
+ BUG();
+ }
+}
+
+/*
+ * Not strictly a reservation, but rather a check that we still have enough
+ * space to satisfy the write.
+ */
+static int logfs_reserve_blocks(struct inode *inode, int blocks)
+{
+ return logfs_reserve_bytes(inode, blocks * LOGFS_MAX_OBJECTSIZE);
+}
+
+struct write_control {
+ u64 ofs;
+ long flags;
+};
+
+static struct logfs_shadow *alloc_shadow(struct inode *inode, u64 bix,
+ level_t level, u64 old_ofs)
+{
+ struct logfs_super *super = logfs_super(inode->i_sb);
+ struct logfs_shadow *shadow;
+
+ shadow = mempool_alloc(super->s_shadow_pool, GFP_NOFS);
+ memset(shadow, 0, sizeof(*shadow));
+ shadow->ino = inode->i_ino;
+ shadow->bix = bix;
+ shadow->gc_level = expand_level(inode->i_ino, level);
+ shadow->old_ofs = old_ofs & ~LOGFS_FULLY_POPULATED;
+ return shadow;
+}
+
+static void free_shadow(struct inode *inode, struct logfs_shadow *shadow)
+{
+ struct logfs_super *super = logfs_super(inode->i_sb);
+
+ mempool_free(shadow, super->s_shadow_pool);
+}
+
+/**
+ * fill_shadow_tree - Propagate shadow tree changes due to a write
+ * @inode: Inode owning the page
+ * @page: Struct page that was written
+ * @shadow: Shadow for the current write
+ *
+ * Writes in logfs can result in two semi-valid objects. The old object
+ * is still valid as long as it can be reached by following pointers on
+ * the medium. Only when writes propagate all the way up to the journal
+ * has the new object safely replaced the old one.
+ *
+ * To handle this problem, a struct logfs_shadow is used to represent
+ * every single write. It is attached to the indirect block, which is
+ * marked dirty. When the indirect block is written, its shadows are
+ * handed up to the next indirect block (or inode). Untimately they
+ * will reach the master inode and be freed upon journal commit.
+ *
+ * This function handles a single step in the propagation. It adds the
+ * shadow for the current write to the tree, along with any shadows in
+ * the page's tree, in case it was an indirect block. If a page is
+ * written, the inode parameter is left NULL, if an inode is written,
+ * the page parameter is left NULL.
+ */
+static void fill_shadow_tree(struct inode *inode, struct page *page,
+ struct logfs_shadow *shadow)
+{
+ struct logfs_super *super = logfs_super(inode->i_sb);
+ struct logfs_block *block = logfs_block(page);
+ struct shadow_tree *tree = &super->s_shadow_tree;
+
+ if (PagePrivate(page)) {
+ if (block->alias_map)
+ super->s_no_object_aliases -= bitmap_weight(
+ block->alias_map, LOGFS_BLOCK_FACTOR);
+ logfs_handle_transaction(inode, block->ta);
+ block->ops->free_block(inode->i_sb, block);
+ }
+ if (shadow) {
+ if (shadow->old_ofs)
+ btree_insert64(&tree->old, shadow->old_ofs, shadow,
+ GFP_NOFS);
+ else
+ btree_insert64(&tree->new, shadow->new_ofs, shadow,
+ GFP_NOFS);
+
+ super->s_dirty_used_bytes += shadow->new_len;
+ super->s_dirty_free_bytes += shadow->old_len;
+ }
+}
+
+static void logfs_set_alias(struct super_block *sb, struct logfs_block *block,
+ long child_no)
+{
+ struct logfs_super *super = logfs_super(sb);
+
+ if (block->inode && block->inode->i_ino == LOGFS_INO_MASTER) {
+ /* Aliases in the master inode are pointless. */
+ return;
+ }
+
+ if (!test_bit(child_no, block->alias_map)) {
+ set_bit(child_no, block->alias_map);
+ super->s_no_object_aliases++;
+ }
+ list_move_tail(&block->alias_list, &super->s_object_alias);
+}
+
+/*
+ * Object aliases can and often do change the size and occupied space of a
+ * file. So not only do we have to change the pointers, we also have to
+ * change inode->i_size and li->li_used_bytes. Which is done by setting
+ * another two object aliases for the inode itself.
+ */
+static void set_iused(struct inode *inode, struct logfs_shadow *shadow)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+
+ if (shadow->new_len == shadow->old_len)
+ return;
+
+ alloc_inode_block(inode);
+ li->li_used_bytes += shadow->new_len - shadow->old_len;
+ __logfs_set_blocks(inode);
+ logfs_set_alias(inode->i_sb, li->li_block, INODE_USED_OFS);
+ logfs_set_alias(inode->i_sb, li->li_block, INODE_SIZE_OFS);
+}
+
+static int logfs_write_i0(struct inode *inode, struct page *page,
+ struct write_control *wc)
+{
+ struct logfs_shadow *shadow;
+ u64 bix;
+ level_t level;
+ int full, err = 0;
+
+ logfs_unpack_index(page->index, &bix, &level);
+ if (wc->ofs == 0)
+ if (logfs_reserve_blocks(inode, 1))
+ return -ENOSPC;
+
+ shadow = alloc_shadow(inode, bix, level, wc->ofs);
+ if (wc->flags & WF_WRITE)
+ err = logfs_segment_write(inode, page, shadow);
+ if (wc->flags & WF_DELETE)
+ logfs_segment_delete(inode, shadow);
+ if (err) {
+ free_shadow(inode, shadow);
+ return err;
+ }
+
+ set_iused(inode, shadow);
+ full = 1;
+ if (level != 0) {
+ alloc_indirect_block(inode, page, 0);
+ full = logfs_block(page)->full == LOGFS_BLOCK_FACTOR;
+ }
+ fill_shadow_tree(inode, page, shadow);
+ wc->ofs = shadow->new_ofs;
+ if (wc->ofs && full)
+ wc->ofs |= LOGFS_FULLY_POPULATED;
+ return 0;
+}
+
+static int logfs_write_direct(struct inode *inode, struct page *page,
+ long flags)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+ struct write_control wc = {
+ .ofs = li->li_data[page->index],
+ .flags = flags,
+ };
+ int err;
+
+ alloc_inode_block(inode);
+
+ err = logfs_write_i0(inode, page, &wc);
+ if (err)
+ return err;
+
+ li->li_data[page->index] = wc.ofs;
+ logfs_set_alias(inode->i_sb, li->li_block,
+ page->index + INODE_POINTER_OFS);
+ return 0;
+}
+
+static int ptr_change(u64 ofs, struct page *page)
+{
+ struct logfs_block *block = logfs_block(page);
+ int empty0, empty1, full0, full1;
+
+ empty0 = ofs == 0;
+ empty1 = block->partial == 0;
+ if (empty0 != empty1)
+ return 1;
+
+ /* The !! is necessary to shrink result to int */
+ full0 = !!(ofs & LOGFS_FULLY_POPULATED);
+ full1 = block->full == LOGFS_BLOCK_FACTOR;
+ if (full0 != full1)
+ return 1;
+ return 0;
+}
+
+static int __logfs_write_rec(struct inode *inode, struct page *page,
+ struct write_control *this_wc,
+ pgoff_t bix, level_t target_level, level_t level)
+{
+ int ret, page_empty = 0;
+ int child_no = get_bits(bix, SUBLEVEL(level));
+ struct page *ipage;
+ struct write_control child_wc = {
+ .flags = this_wc->flags,
+ };
+
+ ipage = logfs_get_write_page(inode, bix, level);
+ if (!ipage)
+ return -ENOMEM;
+
+ if (this_wc->ofs) {
+ ret = logfs_segment_read(inode, ipage, this_wc->ofs, bix, level);
+ if (ret)
+ goto out;
+ } else if (!PageUptodate(ipage)) {
+ page_empty = 1;
+ logfs_read_empty(ipage);
+ }
+
+ child_wc.ofs = block_get_pointer(ipage, child_no);
+
+ if ((__force u8)level-1 > (__force u8)target_level)
+ ret = __logfs_write_rec(inode, page, &child_wc, bix,
+ target_level, SUBLEVEL(level));
+ else
+ ret = logfs_write_i0(inode, page, &child_wc);
+
+ if (ret)
+ goto out;
+
+ alloc_indirect_block(inode, ipage, page_empty);
+ block_set_pointer(ipage, child_no, child_wc.ofs);
+ /* FIXME: first condition seems superfluous */
+ if (child_wc.ofs || logfs_block(ipage)->partial)
+ this_wc->flags |= WF_WRITE;
+ /* the condition on this_wc->ofs ensures that we won't consume extra
+ * space for indirect blocks in the future, which we cannot reserve */
+ if (!this_wc->ofs || ptr_change(this_wc->ofs, ipage))
+ ret = logfs_write_i0(inode, ipage, this_wc);
+ else
+ logfs_set_alias(inode->i_sb, logfs_block(ipage), child_no);
+out:
+ logfs_put_write_page(ipage);
+ return ret;
+}
+
+static int logfs_write_rec(struct inode *inode, struct page *page,
+ pgoff_t bix, level_t target_level, long flags)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+ struct write_control wc = {
+ .ofs = li->li_data[INDIRECT_INDEX],
+ .flags = flags,
+ };
+ int ret;
+
+ alloc_inode_block(inode);
+
+ if (li->li_height > (__force u8)target_level)
+ ret = __logfs_write_rec(inode, page, &wc, bix, target_level,
+ LEVEL(li->li_height));
+ else
+ ret = logfs_write_i0(inode, page, &wc);
+ if (ret)
+ return ret;
+
+ if (li->li_data[INDIRECT_INDEX] != wc.ofs) {
+ li->li_data[INDIRECT_INDEX] = wc.ofs;
+ logfs_set_alias(inode->i_sb, li->li_block,
+ INDIRECT_INDEX + INODE_POINTER_OFS);
+ }
+ return ret;
+}
+
+void logfs_add_transaction(struct inode *inode, struct logfs_transaction *ta)
+{
+ alloc_inode_block(inode);
+ logfs_inode(inode)->li_block->ta = ta;
+}
+
+void logfs_del_transaction(struct inode *inode, struct logfs_transaction *ta)
+{
+ struct logfs_block *block = logfs_inode(inode)->li_block;
+
+ if (block && block->ta)
+ block->ta = NULL;
+}
+
+static int grow_inode(struct inode *inode, u64 bix, level_t level)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+ u8 height = (__force u8)level;
+ struct page *page;
+ struct write_control wc = {
+ .flags = WF_WRITE,
+ };
+ int err;
+
+ BUG_ON(height > 5 || li->li_height > 5);
+ while (height > li->li_height || bix >= maxbix(li->li_height)) {
+ page = logfs_get_write_page(inode, I0_BLOCKS + 1,
+ LEVEL(li->li_height + 1));
+ if (!page)
+ return -ENOMEM;
+ logfs_read_empty(page);
+ alloc_indirect_block(inode, page, 1);
+ block_set_pointer(page, 0, li->li_data[INDIRECT_INDEX]);
+ err = logfs_write_i0(inode, page, &wc);
+ logfs_put_write_page(page);
+ if (err)
+ return err;
+ li->li_data[INDIRECT_INDEX] = wc.ofs;
+ wc.ofs = 0;
+ li->li_height++;
+ logfs_set_alias(inode->i_sb, li->li_block, INODE_HEIGHT_OFS);
+ }
+ return 0;
+}
+
+static int __logfs_write_buf(struct inode *inode, struct page *page, long flags)
+{
+ struct logfs_super *super = logfs_super(inode->i_sb);
+ pgoff_t index = page->index;
+ u64 bix;
+ level_t level;
+ int err;
+
+ flags |= WF_WRITE | WF_DELETE;
+ inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+
+ logfs_unpack_index(index, &bix, &level);
+ if (logfs_block(page) && logfs_block(page)->reserved_bytes)
+ super->s_dirty_pages -= logfs_block(page)->reserved_bytes;
+
+ if (index < I0_BLOCKS)
+ return logfs_write_direct(inode, page, flags);
+
+ bix = adjust_bix(bix, level);
+ err = grow_inode(inode, bix, level);
+ if (err)
+ return err;
+ return logfs_write_rec(inode, page, bix, level, flags);
+}
+
+int logfs_write_buf(struct inode *inode, struct page *page, long flags)
+{
+ struct super_block *sb = inode->i_sb;
+ int ret;
+
+ logfs_get_wblocks(sb, page, flags & WF_LOCK);
+ ret = __logfs_write_buf(inode, page, flags);
+ logfs_put_wblocks(sb, page, flags & WF_LOCK);
+ return ret;
+}
+
+static int __logfs_delete(struct inode *inode, struct page *page)
+{
+ long flags = WF_DELETE;
+
+ inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+
+ if (page->index < I0_BLOCKS)
+ return logfs_write_direct(inode, page, flags);
+ return logfs_write_rec(inode, page, page->index, 0, flags);
+}
+
+int logfs_delete(struct inode *inode, pgoff_t index,
+ struct shadow_tree *shadow_tree)
+{
+ struct super_block *sb = inode->i_sb;
+ struct page *page;
+ int ret;
+
+ page = logfs_get_read_page(inode, index, 0);
+ if (!page)
+ return -ENOMEM;
+
+ logfs_get_wblocks(sb, page, 1);
+ ret = __logfs_delete(inode, page);
+ logfs_put_wblocks(sb, page, 1);
+
+ logfs_put_read_page(page);
+
+ return ret;
+}
+
+/* Rewrite cannot mark the inode dirty but has to write it immediatly. */
+int logfs_rewrite_block(struct inode *inode, u64 bix, u64 ofs,
+ gc_level_t gc_level, long flags)
+{
+ level_t level = shrink_level(gc_level);
+ struct page *page;
+ int err;
+
+ page = logfs_get_write_page(inode, bix, level);
+ if (!page)
+ return -ENOMEM;
+
+ err = logfs_segment_read(inode, page, ofs, bix, level);
+ if (!err) {
+ if (level != 0)
+ alloc_indirect_block(inode, page, 0);
+ err = logfs_write_buf(inode, page, flags);
+ }
+ logfs_put_write_page(page);
+ return err;
+}
+
+static int truncate_data_block(struct inode *inode, struct page *page,
+ u64 ofs, struct logfs_shadow *shadow, u64 size)
+{
+ loff_t pageofs = page->index << inode->i_sb->s_blocksize_bits;
+ u64 bix;
+ level_t level;
+ int err;
+
+ /* Does truncation happen within this page? */
+ if (size <= pageofs || size - pageofs >= PAGE_SIZE)
+ return 0;
+
+ logfs_unpack_index(page->index, &bix, &level);
+ BUG_ON(level != 0);
+
+ err = logfs_segment_read(inode, page, ofs, bix, level);
+ if (err)
+ return err;
+
+ zero_user_segment(page, size - pageofs, PAGE_CACHE_SIZE);
+ return logfs_segment_write(inode, page, shadow);
+}
+
+static int logfs_truncate_i0(struct inode *inode, struct page *page,
+ struct write_control *wc, u64 size)
+{
+ struct logfs_shadow *shadow;
+ u64 bix;
+ level_t level;
+ int err = 0;
+
+ logfs_unpack_index(page->index, &bix, &level);
+ BUG_ON(level != 0);
+ shadow = alloc_shadow(inode, bix, level, wc->ofs);
+
+ err = truncate_data_block(inode, page, wc->ofs, shadow, size);
+ if (err) {
+ free_shadow(inode, shadow);
+ return err;
+ }
+
+ logfs_segment_delete(inode, shadow);
+ set_iused(inode, shadow);
+ fill_shadow_tree(inode, page, shadow);
+ wc->ofs = shadow->new_ofs;
+ return 0;
+}
+
+static int logfs_truncate_direct(struct inode *inode, u64 size)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+ struct write_control wc;
+ struct page *page;
+ int e;
+ int err;
+
+ alloc_inode_block(inode);
+
+ for (e = I0_BLOCKS - 1; e >= 0; e--) {
+ if (size > (e+1) * LOGFS_BLOCKSIZE)
+ break;
+
+ wc.ofs = li->li_data[e];
+ if (!wc.ofs)
+ continue;
+
+ page = logfs_get_write_page(inode, e, 0);
+ if (!page)
+ return -ENOMEM;
+ err = logfs_segment_read(inode, page, wc.ofs, e, 0);
+ if (err) {
+ logfs_put_write_page(page);
+ return err;
+ }
+ err = logfs_truncate_i0(inode, page, &wc, size);
+ logfs_put_write_page(page);
+ if (err)
+ return err;
+
+ li->li_data[e] = wc.ofs;
+ }
+ return 0;
+}
+
+/* FIXME: these need to become per-sb once we support different blocksizes */
+static u64 __logfs_step[] = {
+ 1,
+ I1_BLOCKS,
+ I2_BLOCKS,
+ I3_BLOCKS,
+};
+
+static u64 __logfs_start_index[] = {
+ I0_BLOCKS,
+ I1_BLOCKS,
+ I2_BLOCKS,
+ I3_BLOCKS
+};
+
+static inline u64 logfs_step(level_t level)
+{
+ return __logfs_step[(__force u8)level];
+}
+
+static inline u64 logfs_factor(u8 level)
+{
+ return __logfs_step[level] * LOGFS_BLOCKSIZE;
+}
+
+static inline u64 logfs_start_index(level_t level)
+{
+ return __logfs_start_index[(__force u8)level];
+}
+
+static void logfs_unpack_raw_index(pgoff_t index, u64 *bix, level_t *level)
+{
+ logfs_unpack_index(index, bix, level);
+ if (*bix <= logfs_start_index(SUBLEVEL(*level)))
+ *bix = 0;
+}
+
+static int __logfs_truncate_rec(struct inode *inode, struct page *ipage,
+ struct write_control *this_wc, u64 size)
+{
+ int truncate_happened = 0;
+ int e, err = 0;
+ u64 bix, child_bix, next_bix;
+ level_t level;
+ struct page *page;
+ struct write_control child_wc = { /* FIXME: flags */ };
+
+ logfs_unpack_raw_index(ipage->index, &bix, &level);
+ err = logfs_segment_read(inode, ipage, this_wc->ofs, bix, level);
+ if (err)
+ return err;
+
+ for (e = LOGFS_BLOCK_FACTOR - 1; e >= 0; e--) {
+ child_bix = bix + e * logfs_step(SUBLEVEL(level));
+ next_bix = child_bix + logfs_step(SUBLEVEL(level));
+ if (size > next_bix * LOGFS_BLOCKSIZE)
+ break;
+
+ child_wc.ofs = pure_ofs(block_get_pointer(ipage, e));
+ if (!child_wc.ofs)
+ continue;
+
+ page = logfs_get_write_page(inode, child_bix, SUBLEVEL(level));
+ if (!page)
+ return -ENOMEM;
+
+ if ((__force u8)level > 1)
+ err = __logfs_truncate_rec(inode, page, &child_wc, size);
+ else
+ err = logfs_truncate_i0(inode, page, &child_wc, size);
+ logfs_put_write_page(page);
+ if (err)
+ return err;
+
+ truncate_happened = 1;
+ alloc_indirect_block(inode, ipage, 0);
+ block_set_pointer(ipage, e, child_wc.ofs);
+ }
+
+ if (!truncate_happened) {
+ printk("ineffectual truncate (%lx, %lx, %llx)\n", inode->i_ino, ipage->index, size);
+ return 0;
+ }
+
+ this_wc->flags = WF_DELETE;
+ if (logfs_block(ipage)->partial)
+ this_wc->flags |= WF_WRITE;
+
+ return logfs_write_i0(inode, ipage, this_wc);
+}
+
+static int logfs_truncate_rec(struct inode *inode, u64 size)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+ struct write_control wc = {
+ .ofs = li->li_data[INDIRECT_INDEX],
+ };
+ struct page *page;
+ int err;
+
+ alloc_inode_block(inode);
+
+ if (!wc.ofs)
+ return 0;
+
+ page = logfs_get_write_page(inode, 0, LEVEL(li->li_height));
+ if (!page)
+ return -ENOMEM;
+
+ err = __logfs_truncate_rec(inode, page, &wc, size);
+ logfs_put_write_page(page);
+ if (err)
+ return err;
+
+ if (li->li_data[INDIRECT_INDEX] != wc.ofs)
+ li->li_data[INDIRECT_INDEX] = wc.ofs;
+ return 0;
+}
+
+static int __logfs_truncate(struct inode *inode, u64 size)
+{
+ int ret;
+
+ if (size >= logfs_factor(logfs_inode(inode)->li_height))
+ return 0;
+
+ ret = logfs_truncate_rec(inode, size);
+ if (ret)
+ return ret;
+
+ return logfs_truncate_direct(inode, size);
+}
+
+int logfs_truncate(struct inode *inode, u64 size)
+{
+ struct super_block *sb = inode->i_sb;
+ int err;
+
+ logfs_get_wblocks(sb, NULL, 1);
+ err = __logfs_truncate(inode, size);
+ if (!err)
+ err = __logfs_write_inode(inode, 0);
+ logfs_put_wblocks(sb, NULL, 1);
+
+ if (!err)
+ err = vmtruncate(inode, size);
+
+ /* I don't trust error recovery yet. */
+ WARN_ON(err);
+ return err;
+}
+
+static void move_page_to_inode(struct inode *inode, struct page *page)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+ struct logfs_block *block = logfs_block(page);
+
+ if (!block)
+ return;
+
+ log_blockmove("move_page_to_inode(%llx, %llx, %x)\n",
+ block->ino, block->bix, block->level);
+ BUG_ON(li->li_block);
+ block->ops = &inode_block_ops;
+ block->inode = inode;
+ li->li_block = block;
+
+ block->page = NULL;
+ page->private = 0;
+ ClearPagePrivate(page);
+}
+
+static void move_inode_to_page(struct page *page, struct inode *inode)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+ struct logfs_block *block = li->li_block;
+
+ if (!block)
+ return;
+
+ log_blockmove("move_inode_to_page(%llx, %llx, %x)\n",
+ block->ino, block->bix, block->level);
+ BUG_ON(PagePrivate(page));
+ block->ops = &indirect_block_ops;
+ block->page = page;
+ page->private = (unsigned long)block;
+ SetPagePrivate(page);
+
+ block->inode = NULL;
+ li->li_block = NULL;
+}
+
+int logfs_read_inode(struct inode *inode)
+{
+ struct super_block *sb = inode->i_sb;
+ struct logfs_super *super = logfs_super(sb);
+ struct inode *master_inode = super->s_master_inode;
+ struct page *page;
+ struct logfs_disk_inode *di;
+ u64 ino = inode->i_ino;
+
+ if (ino << sb->s_blocksize_bits > i_size_read(master_inode))
+ return -ENODATA;
+ if (!logfs_exist_block(master_inode, ino))
+ return -ENODATA;
+
+ page = read_cache_page(master_inode->i_mapping, ino,
+ (filler_t *)logfs_readpage, NULL);
+ if (IS_ERR(page))
+ return PTR_ERR(page);
+
+ di = kmap_atomic(page, KM_USER0);
+ logfs_disk_to_inode(di, inode);
+ kunmap_atomic(di, KM_USER0);
+ move_page_to_inode(inode, page);
+ page_cache_release(page);
+ return 0;
+}
+
+/* Caller must logfs_put_write_page(page); */
+static struct page *inode_to_page(struct inode *inode)
+{
+ struct inode *master_inode = logfs_super(inode->i_sb)->s_master_inode;
+ struct logfs_disk_inode *di;
+ struct page *page;
+
+ BUG_ON(inode->i_ino == LOGFS_INO_MASTER);
+
+ page = logfs_get_write_page(master_inode, inode->i_ino, 0);
+ if (!page)
+ return NULL;
+
+ di = kmap_atomic(page, KM_USER0);
+ logfs_inode_to_disk(inode, di);
+ kunmap_atomic(di, KM_USER0);
+ move_inode_to_page(page, inode);
+ return page;
+}
+
+/* Cheaper version of write_inode. All changes are concealed in
+ * aliases, which are moved back. No write to the medium happens.
+ */
+void logfs_clear_inode(struct inode *inode)
+{
+ struct super_block *sb = inode->i_sb;
+ struct logfs_inode *li = logfs_inode(inode);
+ struct logfs_block *block = li->li_block;
+ struct page *page;
+
+ /* Only deleted files may be dirty at this point */
+ BUG_ON(inode->i_state & I_DIRTY && inode->i_nlink);
+ if (!block)
+ return;
+ if ((logfs_super(sb)->s_flags & LOGFS_SB_FLAG_SHUTDOWN)) {
+ block->ops->free_block(inode->i_sb, block);
+ return;
+ }
+
+ BUG_ON(inode->i_ino < LOGFS_RESERVED_INOS);
+ page = inode_to_page(inode);
+ BUG_ON(!page); /* FIXME: Use emergency page */
+ logfs_put_write_page(page);
+}
+
+static int do_write_inode(struct inode *inode)
+{
+ struct super_block *sb = inode->i_sb;
+ struct inode *master_inode = logfs_super(sb)->s_master_inode;
+ loff_t size = (inode->i_ino + 1) << inode->i_sb->s_blocksize_bits;
+ struct page *page;
+ int err;
+
+ BUG_ON(inode->i_ino == LOGFS_INO_MASTER);
+ /* FIXME: lock inode */
+
+ if (i_size_read(master_inode) < size)
+ i_size_write(master_inode, size);
+
+ /* TODO: Tell vfs this inode is clean now */
+
+ page = inode_to_page(inode);
+ if (!page)
+ return -ENOMEM;
+
+ /* FIXME: transaction is part of logfs_block now. Is that enough? */
+ err = logfs_write_buf(master_inode, page, 0);
+ logfs_put_write_page(page);
+ return err;
+}
+
+static void logfs_mod_segment_entry(struct super_block *sb, u32 segno,
+ int write,
+ void (*change_se)(struct logfs_segment_entry *, long),
+ long arg)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct inode *inode;
+ struct page *page;
+ struct logfs_segment_entry *se;
+ pgoff_t page_no;
+ int child_no;
+
+ page_no = segno >> (sb->s_blocksize_bits - 3);
+ child_no = segno & ((sb->s_blocksize >> 3) - 1);
+
+ inode = super->s_segfile_inode;
+ page = logfs_get_write_page(inode, page_no, 0);
+ BUG_ON(!page); /* FIXME: We need some reserve page for this case */
+ if (!PageUptodate(page))
+ logfs_read_block(inode, page, WRITE);
+
+ if (write)
+ alloc_indirect_block(inode, page, 0);
+ se = kmap_atomic(page, KM_USER0);
+ change_se(se + child_no, arg);
+ if (write) {
+ logfs_set_alias(sb, logfs_block(page), child_no);
+ BUG_ON((int)be32_to_cpu(se[child_no].valid) > super->s_segsize);
+ }
+ kunmap_atomic(se, KM_USER0);
+
+ logfs_put_write_page(page);
+}
+
+static void __get_segment_entry(struct logfs_segment_entry *se, long _target)
+{
+ struct logfs_segment_entry *target = (void *)_target;
+
+ *target = *se;
+}
+
+void logfs_get_segment_entry(struct super_block *sb, u32 segno,
+ struct logfs_segment_entry *se)
+{
+ logfs_mod_segment_entry(sb, segno, 0, __get_segment_entry, (long)se);
+}
+
+static void __set_segment_used(struct logfs_segment_entry *se, long increment)
+{
+ u32 valid;
+
+ valid = be32_to_cpu(se->valid);
+ valid += increment;
+ se->valid = cpu_to_be32(valid);
+}
+
+void logfs_set_segment_used(struct super_block *sb, u64 ofs, int increment)
+{
+ struct logfs_super *super = logfs_super(sb);
+ u32 segno = ofs >> super->s_segshift;
+
+ if (!increment)
+ return;
+
+ logfs_mod_segment_entry(sb, segno, 1, __set_segment_used, increment);
+}
+
+static void __set_segment_erased(struct logfs_segment_entry *se, long ec_level)
+{
+ se->ec_level = cpu_to_be32(ec_level);
+}
+
+void logfs_set_segment_erased(struct super_block *sb, u32 segno, u32 ec,
+ gc_level_t gc_level)
+{
+ u32 ec_level = ec << 4 | (__force u8)gc_level;
+
+ logfs_mod_segment_entry(sb, segno, 1, __set_segment_erased, ec_level);
+}
+
+static void __set_segment_reserved(struct logfs_segment_entry *se, long ignore)
+{
+ se->valid = cpu_to_be32(RESERVED);
+}
+
+void logfs_set_segment_reserved(struct super_block *sb, u32 segno)
+{
+ logfs_mod_segment_entry(sb, segno, 1, __set_segment_reserved, 0);
+}
+
+static void __set_segment_unreserved(struct logfs_segment_entry *se,
+ long ec_level)
+{
+ se->valid = 0;
+ se->ec_level = cpu_to_be32(ec_level);
+}
+
+void logfs_set_segment_unreserved(struct super_block *sb, u32 segno, u32 ec)
+{
+ u32 ec_level = ec << 4;
+
+ logfs_mod_segment_entry(sb, segno, 1, __set_segment_unreserved,
+ ec_level);
+}
+
+int __logfs_write_inode(struct inode *inode, long flags)
+{
+ struct super_block *sb = inode->i_sb;
+ int ret;
+
+ logfs_get_wblocks(sb, NULL, flags & WF_LOCK);
+ ret = do_write_inode(inode);
+ logfs_put_wblocks(sb, NULL, flags & WF_LOCK);
+ return ret;
+}
+
+static int do_delete_inode(struct inode *inode)
+{
+ struct super_block *sb = inode->i_sb;
+ struct inode *master_inode = logfs_super(sb)->s_master_inode;
+ struct page *page;
+ int ret;
+
+ page = logfs_get_write_page(master_inode, inode->i_ino, 0);
+ if (!page)
+ return -ENOMEM;
+
+ move_inode_to_page(page, inode);
+
+ logfs_get_wblocks(sb, page, 1);
+ ret = __logfs_delete(master_inode, page);
+ logfs_put_wblocks(sb, page, 1);
+
+ logfs_put_write_page(page);
+ return ret;
+}
+
+/*
+ * ZOMBIE inodes have already been deleted before and should remain dead,
+ * if it weren't for valid checking. No need to kill them again here.
+ */
+void logfs_delete_inode(struct inode *inode)
+{
+ struct logfs_inode *li = logfs_inode(inode);
+
+ if (!(li->li_flags & LOGFS_IF_ZOMBIE)) {
+ li->li_flags |= LOGFS_IF_ZOMBIE;
+ if (i_size_read(inode) > 0)
+ logfs_truncate(inode, 0);
+ do_delete_inode(inode);
+ }
+ truncate_inode_pages(&inode->i_data, 0);
+ clear_inode(inode);
+}
+
+void btree_write_block(struct logfs_block *block)
+{
+ struct inode *inode;
+ struct page *page;
+ int err, cookie;
+
+ inode = logfs_safe_iget(block->sb, block->ino, &cookie);
+ page = logfs_get_write_page(inode, block->bix, block->level);
+
+ err = logfs_readpage_nolock(page);
+ BUG_ON(err);
+ BUG_ON(!PagePrivate(page));
+ BUG_ON(logfs_block(page) != block);
+ err = __logfs_write_buf(inode, page, 0);
+ BUG_ON(err);
+ BUG_ON(PagePrivate(page) || page->private);
+
+ logfs_put_write_page(page);
+ logfs_safe_iput(inode, cookie);
+}
+
+/**
+ * logfs_inode_write - write inode or dentry objects
+ *
+ * @inode: parent inode (ifile or directory)
+ * @buf: object to write (inode or dentry)
+ * @n: object size
+ * @_pos: object number (file position in blocks/objects)
+ * @flags: write flags
+ * @lock: 0 if write lock is already taken, 1 otherwise
+ * @shadow_tree: shadow below this inode
+ *
+ * FIXME: All caller of this put a 200-300 byte variable on the stack,
+ * only to call here and do a memcpy from that stack variable. A good
+ * example of wasted performance and stack space.
+ */
+int logfs_inode_write(struct inode *inode, const void *buf, size_t count,
+ loff_t bix, long flags, struct shadow_tree *shadow_tree)
+{
+ loff_t pos = bix << inode->i_sb->s_blocksize_bits;
+ int err;
+ struct page *page;
+ void *pagebuf;
+
+ BUG_ON(pos & (LOGFS_BLOCKSIZE-1));
+ BUG_ON(count > LOGFS_BLOCKSIZE);
+ page = logfs_get_write_page(inode, bix, 0);
+ if (!page)
+ return -ENOMEM;
+
+ pagebuf = kmap_atomic(page, KM_USER0);
+ memcpy(pagebuf, buf, count);
+ flush_dcache_page(page);
+ kunmap_atomic(pagebuf, KM_USER0);
+
+ if (i_size_read(inode) < pos + LOGFS_BLOCKSIZE)
+ i_size_write(inode, pos + LOGFS_BLOCKSIZE);
+
+ err = logfs_write_buf(inode, page, flags);
+ logfs_put_write_page(page);
+ return err;
+}
+
+int logfs_open_segfile(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct inode *inode;
+
+ inode = logfs_read_meta_inode(sb, LOGFS_INO_SEGFILE);
+ if (IS_ERR(inode))
+ return PTR_ERR(inode);
+ super->s_segfile_inode = inode;
+ return 0;
+}
+
+int logfs_init_rw(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ int min_fill = 3 * super->s_no_blocks;
+
+ INIT_LIST_HEAD(&super->s_object_alias);
+ mutex_init(&super->s_write_mutex);
+ super->s_block_pool = mempool_create_kmalloc_pool(min_fill,
+ sizeof(struct logfs_block));
+ super->s_shadow_pool = mempool_create_kmalloc_pool(min_fill,
+ sizeof(struct logfs_shadow));
+ return 0;
+}
+
+void logfs_cleanup_rw(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+
+ destroy_meta_inode(super->s_segfile_inode);
+ if (super->s_block_pool)
+ mempool_destroy(super->s_block_pool);
+ if (super->s_shadow_pool)
+ mempool_destroy(super->s_shadow_pool);
+}
diff --git a/fs/logfs/segment.c b/fs/logfs/segment.c
new file mode 100644
index 00000000000..1a14f9910d5
--- /dev/null
+++ b/fs/logfs/segment.c
@@ -0,0 +1,927 @@
+/*
+ * fs/logfs/segment.c - Handling the Object Store
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ *
+ * Object store or ostore makes up the complete device with exception of
+ * the superblock and journal areas. Apart from its own metadata it stores
+ * three kinds of objects: inodes, dentries and blocks, both data and indirect.
+ */
+#include "logfs.h"
+
+static int logfs_mark_segment_bad(struct super_block *sb, u32 segno)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct btree_head32 *head = &super->s_reserved_segments;
+ int err;
+
+ err = btree_insert32(head, segno, (void *)1, GFP_NOFS);
+ if (err)
+ return err;
+ logfs_super(sb)->s_bad_segments++;
+ /* FIXME: write to journal */
+ return 0;
+}
+
+int logfs_erase_segment(struct super_block *sb, u32 segno, int ensure_erase)
+{
+ struct logfs_super *super = logfs_super(sb);
+
+ super->s_gec++;
+
+ return super->s_devops->erase(sb, (u64)segno << super->s_segshift,
+ super->s_segsize, ensure_erase);
+}
+
+static s64 logfs_get_free_bytes(struct logfs_area *area, size_t bytes)
+{
+ s32 ofs;
+
+ logfs_open_area(area, bytes);
+
+ ofs = area->a_used_bytes;
+ area->a_used_bytes += bytes;
+ BUG_ON(area->a_used_bytes >= logfs_super(area->a_sb)->s_segsize);
+
+ return dev_ofs(area->a_sb, area->a_segno, ofs);
+}
+
+static struct page *get_mapping_page(struct super_block *sb, pgoff_t index,
+ int use_filler)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct address_space *mapping = super->s_mapping_inode->i_mapping;
+ filler_t *filler = super->s_devops->readpage;
+ struct page *page;
+
+ BUG_ON(mapping_gfp_mask(mapping) & __GFP_FS);
+ if (use_filler)
+ page = read_cache_page(mapping, index, filler, sb);
+ else {
+ page = find_or_create_page(mapping, index, GFP_NOFS);
+ unlock_page(page);
+ }
+ return page;
+}
+
+void __logfs_buf_write(struct logfs_area *area, u64 ofs, void *buf, size_t len,
+ int use_filler)
+{
+ pgoff_t index = ofs >> PAGE_SHIFT;
+ struct page *page;
+ long offset = ofs & (PAGE_SIZE-1);
+ long copylen;
+
+ /* Only logfs_wbuf_recover may use len==0 */
+ BUG_ON(!len && !use_filler);
+ do {
+ copylen = min((ulong)len, PAGE_SIZE - offset);
+
+ page = get_mapping_page(area->a_sb, index, use_filler);
+ SetPageUptodate(page);
+ BUG_ON(!page); /* FIXME: reserve a pool */
+ memcpy(page_address(page) + offset, buf, copylen);
+ SetPagePrivate(page);
+ page_cache_release(page);
+
+ buf += copylen;
+ len -= copylen;
+ offset = 0;
+ index++;
+ } while (len);
+}
+
+/*
+ * bdev_writeseg will write full pages. Memset the tail to prevent data leaks.
+ */
+static void pad_wbuf(struct logfs_area *area, int final)
+{
+ struct super_block *sb = area->a_sb;
+ struct logfs_super *super = logfs_super(sb);
+ struct page *page;
+ u64 ofs = dev_ofs(sb, area->a_segno, area->a_used_bytes);
+ pgoff_t index = ofs >> PAGE_SHIFT;
+ long offset = ofs & (PAGE_SIZE-1);
+ u32 len = PAGE_SIZE - offset;
+
+ if (len == PAGE_SIZE) {
+ /* The math in this function can surely use some love */
+ len = 0;
+ }
+ if (len) {
+ BUG_ON(area->a_used_bytes >= super->s_segsize);
+
+ page = get_mapping_page(area->a_sb, index, 0);
+ BUG_ON(!page); /* FIXME: reserve a pool */
+ memset(page_address(page) + offset, 0xff, len);
+ SetPagePrivate(page);
+ page_cache_release(page);
+ }
+
+ if (!final)
+ return;
+
+ area->a_used_bytes += len;
+ for ( ; area->a_used_bytes < super->s_segsize;
+ area->a_used_bytes += PAGE_SIZE) {
+ /* Memset another page */
+ index++;
+ page = get_mapping_page(area->a_sb, index, 0);
+ BUG_ON(!page); /* FIXME: reserve a pool */
+ memset(page_address(page), 0xff, PAGE_SIZE);
+ SetPagePrivate(page);
+ page_cache_release(page);
+ }
+}
+
+/*
+ * We have to be careful with the alias tree. Since lookup is done by bix,
+ * it needs to be normalized, so 14, 15, 16, etc. all match when dealing with
+ * indirect blocks. So always use it through accessor functions.
+ */
+static void *alias_tree_lookup(struct super_block *sb, u64 ino, u64 bix,
+ level_t level)
+{
+ struct btree_head128 *head = &logfs_super(sb)->s_object_alias_tree;
+ pgoff_t index = logfs_pack_index(bix, level);
+
+ return btree_lookup128(head, ino, index);
+}
+
+static int alias_tree_insert(struct super_block *sb, u64 ino, u64 bix,
+ level_t level, void *val)
+{
+ struct btree_head128 *head = &logfs_super(sb)->s_object_alias_tree;
+ pgoff_t index = logfs_pack_index(bix, level);
+
+ return btree_insert128(head, ino, index, val, GFP_NOFS);
+}
+
+static int btree_write_alias(struct super_block *sb, struct logfs_block *block,
+ write_alias_t *write_one_alias)
+{
+ struct object_alias_item *item;
+ int err;
+
+ list_for_each_entry(item, &block->item_list, list) {
+ err = write_alias_journal(sb, block->ino, block->bix,
+ block->level, item->child_no, item->val);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+static gc_level_t btree_block_level(struct logfs_block *block)
+{
+ return expand_level(block->ino, block->level);
+}
+
+static struct logfs_block_ops btree_block_ops = {
+ .write_block = btree_write_block,
+ .block_level = btree_block_level,
+ .free_block = __free_block,
+ .write_alias = btree_write_alias,
+};
+
+int logfs_load_object_aliases(struct super_block *sb,
+ struct logfs_obj_alias *oa, int count)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_block *block;
+ struct object_alias_item *item;
+ u64 ino, bix;
+ level_t level;
+ int i, err;
+
+ super->s_flags |= LOGFS_SB_FLAG_OBJ_ALIAS;
+ count /= sizeof(*oa);
+ for (i = 0; i < count; i++) {
+ item = mempool_alloc(super->s_alias_pool, GFP_NOFS);
+ if (!item)
+ return -ENOMEM;
+ memset(item, 0, sizeof(*item));
+
+ super->s_no_object_aliases++;
+ item->val = oa[i].val;
+ item->child_no = be16_to_cpu(oa[i].child_no);
+
+ ino = be64_to_cpu(oa[i].ino);
+ bix = be64_to_cpu(oa[i].bix);
+ level = LEVEL(oa[i].level);
+
+ log_aliases("logfs_load_object_aliases(%llx, %llx, %x, %x) %llx\n",
+ ino, bix, level, item->child_no,
+ be64_to_cpu(item->val));
+ block = alias_tree_lookup(sb, ino, bix, level);
+ if (!block) {
+ block = __alloc_block(sb, ino, bix, level);
+ block->ops = &btree_block_ops;
+ err = alias_tree_insert(sb, ino, bix, level, block);
+ BUG_ON(err); /* mempool empty */
+ }
+ if (test_and_set_bit(item->child_no, block->alias_map)) {
+ printk(KERN_ERR"LogFS: Alias collision detected\n");
+ return -EIO;
+ }
+ list_move_tail(&block->alias_list, &super->s_object_alias);
+ list_add(&item->list, &block->item_list);
+ }
+ return 0;
+}
+
+static void kill_alias(void *_block, unsigned long ignore0,
+ u64 ignore1, u64 ignore2, size_t ignore3)
+{
+ struct logfs_block *block = _block;
+ struct super_block *sb = block->sb;
+ struct logfs_super *super = logfs_super(sb);
+ struct object_alias_item *item;
+
+ while (!list_empty(&block->item_list)) {
+ item = list_entry(block->item_list.next, typeof(*item), list);
+ list_del(&item->list);
+ mempool_free(item, super->s_alias_pool);
+ }
+ block->ops->free_block(sb, block);
+}
+
+static int obj_type(struct inode *inode, level_t level)
+{
+ if (level == 0) {
+ if (S_ISDIR(inode->i_mode))
+ return OBJ_DENTRY;
+ if (inode->i_ino == LOGFS_INO_MASTER)
+ return OBJ_INODE;
+ }
+ return OBJ_BLOCK;
+}
+
+static int obj_len(struct super_block *sb, int obj_type)
+{
+ switch (obj_type) {
+ case OBJ_DENTRY:
+ return sizeof(struct logfs_disk_dentry);
+ case OBJ_INODE:
+ return sizeof(struct logfs_disk_inode);
+ case OBJ_BLOCK:
+ return sb->s_blocksize;
+ default:
+ BUG();
+ }
+}
+
+static int __logfs_segment_write(struct inode *inode, void *buf,
+ struct logfs_shadow *shadow, int type, int len, int compr)
+{
+ struct logfs_area *area;
+ struct super_block *sb = inode->i_sb;
+ s64 ofs;
+ struct logfs_object_header h;
+ int acc_len;
+
+ if (shadow->gc_level == 0)
+ acc_len = len;
+ else
+ acc_len = obj_len(sb, type);
+
+ area = get_area(sb, shadow->gc_level);
+ ofs = logfs_get_free_bytes(area, len + LOGFS_OBJECT_HEADERSIZE);
+ LOGFS_BUG_ON(ofs <= 0, sb);
+ /*
+ * Order is important. logfs_get_free_bytes(), by modifying the
+ * segment file, may modify the content of the very page we're about
+ * to write now. Which is fine, as long as the calculated crc and
+ * written data still match. So do the modifications _before_
+ * calculating the crc.
+ */
+
+ h.len = cpu_to_be16(len);
+ h.type = type;
+ h.compr = compr;
+ h.ino = cpu_to_be64(inode->i_ino);
+ h.bix = cpu_to_be64(shadow->bix);
+ h.crc = logfs_crc32(&h, sizeof(h) - 4, 4);
+ h.data_crc = logfs_crc32(buf, len, 0);
+
+ logfs_buf_write(area, ofs, &h, sizeof(h));
+ logfs_buf_write(area, ofs + LOGFS_OBJECT_HEADERSIZE, buf, len);
+
+ shadow->new_ofs = ofs;
+ shadow->new_len = acc_len + LOGFS_OBJECT_HEADERSIZE;
+
+ return 0;
+}
+
+static s64 logfs_segment_write_compress(struct inode *inode, void *buf,
+ struct logfs_shadow *shadow, int type, int len)
+{
+ struct super_block *sb = inode->i_sb;
+ void *compressor_buf = logfs_super(sb)->s_compressed_je;
+ ssize_t compr_len;
+ int ret;
+
+ mutex_lock(&logfs_super(sb)->s_journal_mutex);
+ compr_len = logfs_compress(buf, compressor_buf, len, len);
+
+ if (compr_len >= 0) {
+ ret = __logfs_segment_write(inode, compressor_buf, shadow,
+ type, compr_len, COMPR_ZLIB);
+ } else {
+ ret = __logfs_segment_write(inode, buf, shadow, type, len,
+ COMPR_NONE);
+ }
+ mutex_unlock(&logfs_super(sb)->s_journal_mutex);
+ return ret;
+}
+
+/**
+ * logfs_segment_write - write data block to object store
+ * @inode: inode containing data
+ *
+ * Returns an errno or zero.
+ */
+int logfs_segment_write(struct inode *inode, struct page *page,
+ struct logfs_shadow *shadow)
+{
+ struct super_block *sb = inode->i_sb;
+ struct logfs_super *super = logfs_super(sb);
+ int do_compress, type, len;
+ int ret;
+ void *buf;
+
+ super->s_flags |= LOGFS_SB_FLAG_DIRTY;
+ BUG_ON(super->s_flags & LOGFS_SB_FLAG_SHUTDOWN);
+ do_compress = logfs_inode(inode)->li_flags & LOGFS_IF_COMPRESSED;
+ if (shadow->gc_level != 0) {
+ /* temporarily disable compression for indirect blocks */
+ do_compress = 0;
+ }
+
+ type = obj_type(inode, shrink_level(shadow->gc_level));
+ len = obj_len(sb, type);
+ buf = kmap(page);
+ if (do_compress)
+ ret = logfs_segment_write_compress(inode, buf, shadow, type,
+ len);
+ else
+ ret = __logfs_segment_write(inode, buf, shadow, type, len,
+ COMPR_NONE);
+ kunmap(page);
+
+ log_segment("logfs_segment_write(%llx, %llx, %x) %llx->%llx %x->%x\n",
+ shadow->ino, shadow->bix, shadow->gc_level,
+ shadow->old_ofs, shadow->new_ofs,
+ shadow->old_len, shadow->new_len);
+ /* this BUG_ON did catch a locking bug. useful */
+ BUG_ON(!(shadow->new_ofs & (super->s_segsize - 1)));
+ return ret;
+}
+
+int wbuf_read(struct super_block *sb, u64 ofs, size_t len, void *buf)
+{
+ pgoff_t index = ofs >> PAGE_SHIFT;
+ struct page *page;
+ long offset = ofs & (PAGE_SIZE-1);
+ long copylen;
+
+ while (len) {
+ copylen = min((ulong)len, PAGE_SIZE - offset);
+
+ page = get_mapping_page(sb, index, 1);
+ if (IS_ERR(page))
+ return PTR_ERR(page);
+ memcpy(buf, page_address(page) + offset, copylen);
+ page_cache_release(page);
+
+ buf += copylen;
+ len -= copylen;
+ offset = 0;
+ index++;
+ }
+ return 0;
+}
+
+/*
+ * The "position" of indirect blocks is ambiguous. It can be the position
+ * of any data block somewhere behind this indirect block. So we need to
+ * normalize the positions through logfs_block_mask() before comparing.
+ */
+static int check_pos(struct super_block *sb, u64 pos1, u64 pos2, level_t level)
+{
+ return (pos1 & logfs_block_mask(sb, level)) !=
+ (pos2 & logfs_block_mask(sb, level));
+}
+
+#if 0
+static int read_seg_header(struct super_block *sb, u64 ofs,
+ struct logfs_segment_header *sh)
+{
+ __be32 crc;
+ int err;
+
+ err = wbuf_read(sb, ofs, sizeof(*sh), sh);
+ if (err)
+ return err;
+ crc = logfs_crc32(sh, sizeof(*sh), 4);
+ if (crc != sh->crc) {
+ printk(KERN_ERR"LOGFS: header crc error at %llx: expected %x, "
+ "got %x\n", ofs, be32_to_cpu(sh->crc),
+ be32_to_cpu(crc));
+ return -EIO;
+ }
+ return 0;
+}
+#endif
+
+static int read_obj_header(struct super_block *sb, u64 ofs,
+ struct logfs_object_header *oh)
+{
+ __be32 crc;
+ int err;
+
+ err = wbuf_read(sb, ofs, sizeof(*oh), oh);
+ if (err)
+ return err;
+ crc = logfs_crc32(oh, sizeof(*oh) - 4, 4);
+ if (crc != oh->crc) {
+ printk(KERN_ERR"LOGFS: header crc error at %llx: expected %x, "
+ "got %x\n", ofs, be32_to_cpu(oh->crc),
+ be32_to_cpu(crc));
+ return -EIO;
+ }
+ return 0;
+}
+
+static void move_btree_to_page(struct inode *inode, struct page *page,
+ __be64 *data)
+{
+ struct super_block *sb = inode->i_sb;
+ struct logfs_super *super = logfs_super(sb);
+ struct btree_head128 *head = &super->s_object_alias_tree;
+ struct logfs_block *block;
+ struct object_alias_item *item, *next;
+
+ if (!(super->s_flags & LOGFS_SB_FLAG_OBJ_ALIAS))
+ return;
+
+ block = btree_remove128(head, inode->i_ino, page->index);
+ if (!block)
+ return;
+
+ log_blockmove("move_btree_to_page(%llx, %llx, %x)\n",
+ block->ino, block->bix, block->level);
+ list_for_each_entry_safe(item, next, &block->item_list, list) {
+ data[item->child_no] = item->val;
+ list_del(&item->list);
+ mempool_free(item, super->s_alias_pool);
+ }
+ block->page = page;
+ SetPagePrivate(page);
+ page->private = (unsigned long)block;
+ block->ops = &indirect_block_ops;
+ initialize_block_counters(page, block, data, 0);
+}
+
+/*
+ * This silences a false, yet annoying gcc warning. I hate it when my editor
+ * jumps into bitops.h each time I recompile this file.
+ * TODO: Complain to gcc folks about this and upgrade compiler.
+ */
+static unsigned long fnb(const unsigned long *addr,
+ unsigned long size, unsigned long offset)
+{
+ return find_next_bit(addr, size, offset);
+}
+
+void move_page_to_btree(struct page *page)
+{
+ struct logfs_block *block = logfs_block(page);
+ struct super_block *sb = block->sb;
+ struct logfs_super *super = logfs_super(sb);
+ struct object_alias_item *item;
+ unsigned long pos;
+ __be64 *child;
+ int err;
+
+ if (super->s_flags & LOGFS_SB_FLAG_SHUTDOWN) {
+ block->ops->free_block(sb, block);
+ return;
+ }
+ log_blockmove("move_page_to_btree(%llx, %llx, %x)\n",
+ block->ino, block->bix, block->level);
+ super->s_flags |= LOGFS_SB_FLAG_OBJ_ALIAS;
+
+ for (pos = 0; ; pos++) {
+ pos = fnb(block->alias_map, LOGFS_BLOCK_FACTOR, pos);
+ if (pos >= LOGFS_BLOCK_FACTOR)
+ break;
+
+ item = mempool_alloc(super->s_alias_pool, GFP_NOFS);
+ BUG_ON(!item); /* mempool empty */
+ memset(item, 0, sizeof(*item));
+
+ child = kmap_atomic(page, KM_USER0);
+ item->val = child[pos];
+ kunmap_atomic(child, KM_USER0);
+ item->child_no = pos;
+ list_add(&item->list, &block->item_list);
+ }
+ block->page = NULL;
+ ClearPagePrivate(page);
+ page->private = 0;
+ block->ops = &btree_block_ops;
+ err = alias_tree_insert(block->sb, block->ino, block->bix, block->level,
+ block);
+ BUG_ON(err); /* mempool empty */
+ ClearPageUptodate(page);
+}
+
+static int __logfs_segment_read(struct inode *inode, void *buf,
+ u64 ofs, u64 bix, level_t level)
+{
+ struct super_block *sb = inode->i_sb;
+ void *compressor_buf = logfs_super(sb)->s_compressed_je;
+ struct logfs_object_header oh;
+ __be32 crc;
+ u16 len;
+ int err, block_len;
+
+ block_len = obj_len(sb, obj_type(inode, level));
+ err = read_obj_header(sb, ofs, &oh);
+ if (err)
+ goto out_err;
+
+ err = -EIO;
+ if (be64_to_cpu(oh.ino) != inode->i_ino
+ || check_pos(sb, be64_to_cpu(oh.bix), bix, level)) {
+ printk(KERN_ERR"LOGFS: (ino, bix) don't match at %llx: "
+ "expected (%lx, %llx), got (%llx, %llx)\n",
+ ofs, inode->i_ino, bix,
+ be64_to_cpu(oh.ino), be64_to_cpu(oh.bix));
+ goto out_err;
+ }
+
+ len = be16_to_cpu(oh.len);
+
+ switch (oh.compr) {
+ case COMPR_NONE:
+ err = wbuf_read(sb, ofs + LOGFS_OBJECT_HEADERSIZE, len, buf);
+ if (err)
+ goto out_err;
+ crc = logfs_crc32(buf, len, 0);
+ if (crc != oh.data_crc) {
+ printk(KERN_ERR"LOGFS: uncompressed data crc error at "
+ "%llx: expected %x, got %x\n", ofs,
+ be32_to_cpu(oh.data_crc),
+ be32_to_cpu(crc));
+ goto out_err;
+ }
+ break;
+ case COMPR_ZLIB:
+ mutex_lock(&logfs_super(sb)->s_journal_mutex);
+ err = wbuf_read(sb, ofs + LOGFS_OBJECT_HEADERSIZE, len,
+ compressor_buf);
+ if (err) {
+ mutex_unlock(&logfs_super(sb)->s_journal_mutex);
+ goto out_err;
+ }
+ crc = logfs_crc32(compressor_buf, len, 0);
+ if (crc != oh.data_crc) {
+ printk(KERN_ERR"LOGFS: compressed data crc error at "
+ "%llx: expected %x, got %x\n", ofs,
+ be32_to_cpu(oh.data_crc),
+ be32_to_cpu(crc));
+ mutex_unlock(&logfs_super(sb)->s_journal_mutex);
+ goto out_err;
+ }
+ err = logfs_uncompress(compressor_buf, buf, len, block_len);
+ mutex_unlock(&logfs_super(sb)->s_journal_mutex);
+ if (err) {
+ printk(KERN_ERR"LOGFS: uncompress error at %llx\n", ofs);
+ goto out_err;
+ }
+ break;
+ default:
+ LOGFS_BUG(sb);
+ err = -EIO;
+ goto out_err;
+ }
+ return 0;
+
+out_err:
+ logfs_set_ro(sb);
+ printk(KERN_ERR"LOGFS: device is read-only now\n");
+ LOGFS_BUG(sb);
+ return err;
+}
+
+/**
+ * logfs_segment_read - read data block from object store
+ * @inode: inode containing data
+ * @buf: data buffer
+ * @ofs: physical data offset
+ * @bix: block index
+ * @level: block level
+ *
+ * Returns 0 on success or a negative errno.
+ */
+int logfs_segment_read(struct inode *inode, struct page *page,
+ u64 ofs, u64 bix, level_t level)
+{
+ int err;
+ void *buf;
+
+ if (PageUptodate(page))
+ return 0;
+
+ ofs &= ~LOGFS_FULLY_POPULATED;
+
+ buf = kmap(page);
+ err = __logfs_segment_read(inode, buf, ofs, bix, level);
+ if (!err) {
+ move_btree_to_page(inode, page, buf);
+ SetPageUptodate(page);
+ }
+ kunmap(page);
+ log_segment("logfs_segment_read(%lx, %llx, %x) %llx (%d)\n",
+ inode->i_ino, bix, level, ofs, err);
+ return err;
+}
+
+int logfs_segment_delete(struct inode *inode, struct logfs_shadow *shadow)
+{
+ struct super_block *sb = inode->i_sb;
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_object_header h;
+ u16 len;
+ int err;
+
+ super->s_flags |= LOGFS_SB_FLAG_DIRTY;
+ BUG_ON(super->s_flags & LOGFS_SB_FLAG_SHUTDOWN);
+ BUG_ON(shadow->old_ofs & LOGFS_FULLY_POPULATED);
+ if (!shadow->old_ofs)
+ return 0;
+
+ log_segment("logfs_segment_delete(%llx, %llx, %x) %llx->%llx %x->%x\n",
+ shadow->ino, shadow->bix, shadow->gc_level,
+ shadow->old_ofs, shadow->new_ofs,
+ shadow->old_len, shadow->new_len);
+ err = read_obj_header(sb, shadow->old_ofs, &h);
+ LOGFS_BUG_ON(err, sb);
+ LOGFS_BUG_ON(be64_to_cpu(h.ino) != inode->i_ino, sb);
+ LOGFS_BUG_ON(check_pos(sb, shadow->bix, be64_to_cpu(h.bix),
+ shrink_level(shadow->gc_level)), sb);
+
+ if (shadow->gc_level == 0)
+ len = be16_to_cpu(h.len);
+ else
+ len = obj_len(sb, h.type);
+ shadow->old_len = len + sizeof(h);
+ return 0;
+}
+
+static void freeseg(struct super_block *sb, u32 segno)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct address_space *mapping = super->s_mapping_inode->i_mapping;
+ struct page *page;
+ u64 ofs, start, end;
+
+ start = dev_ofs(sb, segno, 0);
+ end = dev_ofs(sb, segno + 1, 0);
+ for (ofs = start; ofs < end; ofs += PAGE_SIZE) {
+ page = find_get_page(mapping, ofs >> PAGE_SHIFT);
+ if (!page)
+ continue;
+ ClearPagePrivate(page);
+ page_cache_release(page);
+ }
+}
+
+int logfs_open_area(struct logfs_area *area, size_t bytes)
+{
+ struct super_block *sb = area->a_sb;
+ struct logfs_super *super = logfs_super(sb);
+ int err, closed = 0;
+
+ if (area->a_is_open && area->a_used_bytes + bytes <= super->s_segsize)
+ return 0;
+
+ if (area->a_is_open) {
+ u64 ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes);
+ u32 len = super->s_segsize - area->a_written_bytes;
+
+ log_gc("logfs_close_area(%x)\n", area->a_segno);
+ pad_wbuf(area, 1);
+ super->s_devops->writeseg(area->a_sb, ofs, len);
+ freeseg(sb, area->a_segno);
+ closed = 1;
+ }
+
+ area->a_used_bytes = 0;
+ area->a_written_bytes = 0;
+again:
+ area->a_ops->get_free_segment(area);
+ area->a_ops->get_erase_count(area);
+
+ log_gc("logfs_open_area(%x, %x)\n", area->a_segno, area->a_level);
+ err = area->a_ops->erase_segment(area);
+ if (err) {
+ printk(KERN_WARNING "LogFS: Error erasing segment %x\n",
+ area->a_segno);
+ logfs_mark_segment_bad(sb, area->a_segno);
+ goto again;
+ }
+ area->a_is_open = 1;
+ return closed;
+}
+
+void logfs_sync_area(struct logfs_area *area)
+{
+ struct super_block *sb = area->a_sb;
+ struct logfs_super *super = logfs_super(sb);
+ u64 ofs = dev_ofs(sb, area->a_segno, area->a_written_bytes);
+ u32 len = (area->a_used_bytes - area->a_written_bytes);
+
+ if (super->s_writesize)
+ len &= ~(super->s_writesize - 1);
+ if (len == 0)
+ return;
+ pad_wbuf(area, 0);
+ super->s_devops->writeseg(sb, ofs, len);
+ area->a_written_bytes += len;
+}
+
+void logfs_sync_segments(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ int i;
+
+ for_each_area(i)
+ logfs_sync_area(super->s_area[i]);
+}
+
+/*
+ * Pick a free segment to be used for this area. Effectively takes a
+ * candidate from the free list (not really a candidate anymore).
+ */
+static void ostore_get_free_segment(struct logfs_area *area)
+{
+ struct super_block *sb = area->a_sb;
+ struct logfs_super *super = logfs_super(sb);
+
+ if (super->s_free_list.count == 0) {
+ printk(KERN_ERR"LOGFS: ran out of free segments\n");
+ LOGFS_BUG(sb);
+ }
+
+ area->a_segno = get_best_cand(sb, &super->s_free_list, NULL);
+}
+
+static void ostore_get_erase_count(struct logfs_area *area)
+{
+ struct logfs_segment_entry se;
+ u32 ec_level;
+
+ logfs_get_segment_entry(area->a_sb, area->a_segno, &se);
+ BUG_ON(se.ec_level == cpu_to_be32(BADSEG) ||
+ se.valid == cpu_to_be32(RESERVED));
+
+ ec_level = be32_to_cpu(se.ec_level);
+ area->a_erase_count = (ec_level >> 4) + 1;
+}
+
+static int ostore_erase_segment(struct logfs_area *area)
+{
+ struct super_block *sb = area->a_sb;
+ struct logfs_segment_header sh;
+ u64 ofs;
+ int err;
+
+ err = logfs_erase_segment(sb, area->a_segno, 0);
+ if (err)
+ return err;
+
+ sh.pad = 0;
+ sh.type = SEG_OSTORE;
+ sh.level = (__force u8)area->a_level;
+ sh.segno = cpu_to_be32(area->a_segno);
+ sh.ec = cpu_to_be32(area->a_erase_count);
+ sh.gec = cpu_to_be64(logfs_super(sb)->s_gec);
+ sh.crc = logfs_crc32(&sh, sizeof(sh), 4);
+
+ logfs_set_segment_erased(sb, area->a_segno, area->a_erase_count,
+ area->a_level);
+
+ ofs = dev_ofs(sb, area->a_segno, 0);
+ area->a_used_bytes = sizeof(sh);
+ logfs_buf_write(area, ofs, &sh, sizeof(sh));
+ return 0;
+}
+
+static const struct logfs_area_ops ostore_area_ops = {
+ .get_free_segment = ostore_get_free_segment,
+ .get_erase_count = ostore_get_erase_count,
+ .erase_segment = ostore_erase_segment,
+};
+
+static void free_area(struct logfs_area *area)
+{
+ if (area)
+ freeseg(area->a_sb, area->a_segno);
+ kfree(area);
+}
+
+static struct logfs_area *alloc_area(struct super_block *sb)
+{
+ struct logfs_area *area;
+
+ area = kzalloc(sizeof(*area), GFP_KERNEL);
+ if (!area)
+ return NULL;
+
+ area->a_sb = sb;
+ return area;
+}
+
+static void map_invalidatepage(struct page *page, unsigned long l)
+{
+ BUG();
+}
+
+static int map_releasepage(struct page *page, gfp_t g)
+{
+ /* Don't release these pages */
+ return 0;
+}
+
+static const struct address_space_operations mapping_aops = {
+ .invalidatepage = map_invalidatepage,
+ .releasepage = map_releasepage,
+ .set_page_dirty = __set_page_dirty_nobuffers,
+};
+
+int logfs_init_mapping(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct address_space *mapping;
+ struct inode *inode;
+
+ inode = logfs_new_meta_inode(sb, LOGFS_INO_MAPPING);
+ if (IS_ERR(inode))
+ return PTR_ERR(inode);
+ super->s_mapping_inode = inode;
+ mapping = inode->i_mapping;
+ mapping->a_ops = &mapping_aops;
+ /* Would it be possible to use __GFP_HIGHMEM as well? */
+ mapping_set_gfp_mask(mapping, GFP_NOFS);
+ return 0;
+}
+
+int logfs_init_areas(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ int i = -1;
+
+ super->s_alias_pool = mempool_create_kmalloc_pool(600,
+ sizeof(struct object_alias_item));
+ if (!super->s_alias_pool)
+ return -ENOMEM;
+
+ super->s_journal_area = alloc_area(sb);
+ if (!super->s_journal_area)
+ goto err;
+
+ for_each_area(i) {
+ super->s_area[i] = alloc_area(sb);
+ if (!super->s_area[i])
+ goto err;
+ super->s_area[i]->a_level = GC_LEVEL(i);
+ super->s_area[i]->a_ops = &ostore_area_ops;
+ }
+ btree_init_mempool128(&super->s_object_alias_tree,
+ super->s_btree_pool);
+ return 0;
+
+err:
+ for (i--; i >= 0; i--)
+ free_area(super->s_area[i]);
+ free_area(super->s_journal_area);
+ mempool_destroy(super->s_alias_pool);
+ return -ENOMEM;
+}
+
+void logfs_cleanup_areas(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ int i;
+
+ btree_grim_visitor128(&super->s_object_alias_tree, 0, kill_alias);
+ for_each_area(i)
+ free_area(super->s_area[i]);
+ free_area(super->s_journal_area);
+ destroy_meta_inode(super->s_mapping_inode);
+}
diff --git a/fs/logfs/super.c b/fs/logfs/super.c
new file mode 100644
index 00000000000..c66beab78de
--- /dev/null
+++ b/fs/logfs/super.c
@@ -0,0 +1,650 @@
+/*
+ * fs/logfs/super.c
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org>
+ *
+ * Generally contains mount/umount code and also serves as a dump area for
+ * any functions that don't fit elsewhere and neither justify a file of their
+ * own.
+ */
+#include "logfs.h"
+#include <linux/bio.h>
+#include <linux/mtd/mtd.h>
+#include <linux/statfs.h>
+#include <linux/buffer_head.h>
+
+static DEFINE_MUTEX(emergency_mutex);
+static struct page *emergency_page;
+
+struct page *emergency_read_begin(struct address_space *mapping, pgoff_t index)
+{
+ filler_t *filler = (filler_t *)mapping->a_ops->readpage;
+ struct page *page;
+ int err;
+
+ page = read_cache_page(mapping, index, filler, NULL);
+ if (page)
+ return page;
+
+ /* No more pages available, switch to emergency page */
+ printk(KERN_INFO"Logfs: Using emergency page\n");
+ mutex_lock(&emergency_mutex);
+ err = filler(NULL, emergency_page);
+ if (err) {
+ mutex_unlock(&emergency_mutex);
+ printk(KERN_EMERG"Logfs: Error reading emergency page\n");
+ return ERR_PTR(err);
+ }
+ return emergency_page;
+}
+
+void emergency_read_end(struct page *page)
+{
+ if (page == emergency_page)
+ mutex_unlock(&emergency_mutex);
+ else
+ page_cache_release(page);
+}
+
+static void dump_segfile(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_segment_entry se;
+ u32 segno;
+
+ for (segno = 0; segno < super->s_no_segs; segno++) {
+ logfs_get_segment_entry(sb, segno, &se);
+ printk("%3x: %6x %8x", segno, be32_to_cpu(se.ec_level),
+ be32_to_cpu(se.valid));
+ if (++segno < super->s_no_segs) {
+ logfs_get_segment_entry(sb, segno, &se);
+ printk(" %6x %8x", be32_to_cpu(se.ec_level),
+ be32_to_cpu(se.valid));
+ }
+ if (++segno < super->s_no_segs) {
+ logfs_get_segment_entry(sb, segno, &se);
+ printk(" %6x %8x", be32_to_cpu(se.ec_level),
+ be32_to_cpu(se.valid));
+ }
+ if (++segno < super->s_no_segs) {
+ logfs_get_segment_entry(sb, segno, &se);
+ printk(" %6x %8x", be32_to_cpu(se.ec_level),
+ be32_to_cpu(se.valid));
+ }
+ printk("\n");
+ }
+}
+
+/*
+ * logfs_crash_dump - dump debug information to device
+ *
+ * The LogFS superblock only occupies part of a segment. This function will
+ * write as much debug information as it can gather into the spare space.
+ */
+void logfs_crash_dump(struct super_block *sb)
+{
+ dump_segfile(sb);
+}
+
+/*
+ * TODO: move to lib/string.c
+ */
+/**
+ * memchr_inv - Find a character in an area of memory.
+ * @s: The memory area
+ * @c: The byte to search for
+ * @n: The size of the area.
+ *
+ * returns the address of the first character other than @c, or %NULL
+ * if the whole buffer contains just @c.
+ */
+void *memchr_inv(const void *s, int c, size_t n)
+{
+ const unsigned char *p = s;
+ while (n-- != 0)
+ if ((unsigned char)c != *p++)
+ return (void *)(p - 1);
+
+ return NULL;
+}
+
+/*
+ * FIXME: There should be a reserve for root, similar to ext2.
+ */
+int logfs_statfs(struct dentry *dentry, struct kstatfs *stats)
+{
+ struct super_block *sb = dentry->d_sb;
+ struct logfs_super *super = logfs_super(sb);
+
+ stats->f_type = LOGFS_MAGIC_U32;
+ stats->f_bsize = sb->s_blocksize;
+ stats->f_blocks = super->s_size >> LOGFS_BLOCK_BITS >> 3;
+ stats->f_bfree = super->s_free_bytes >> sb->s_blocksize_bits;
+ stats->f_bavail = super->s_free_bytes >> sb->s_blocksize_bits;
+ stats->f_files = 0;
+ stats->f_ffree = 0;
+ stats->f_namelen = LOGFS_MAX_NAMELEN;
+ return 0;
+}
+
+static int logfs_sb_set(struct super_block *sb, void *_super)
+{
+ struct logfs_super *super = _super;
+
+ sb->s_fs_info = super;
+ sb->s_mtd = super->s_mtd;
+ sb->s_bdev = super->s_bdev;
+ return 0;
+}
+
+static int logfs_sb_test(struct super_block *sb, void *_super)
+{
+ struct logfs_super *super = _super;
+ struct mtd_info *mtd = super->s_mtd;
+
+ if (mtd && sb->s_mtd == mtd)
+ return 1;
+ if (super->s_bdev && sb->s_bdev == super->s_bdev)
+ return 1;
+ return 0;
+}
+
+static void set_segment_header(struct logfs_segment_header *sh, u8 type,
+ u8 level, u32 segno, u32 ec)
+{
+ sh->pad = 0;
+ sh->type = type;
+ sh->level = level;
+ sh->segno = cpu_to_be32(segno);
+ sh->ec = cpu_to_be32(ec);
+ sh->gec = cpu_to_be64(segno);
+ sh->crc = logfs_crc32(sh, LOGFS_SEGMENT_HEADERSIZE, 4);
+}
+
+static void logfs_write_ds(struct super_block *sb, struct logfs_disk_super *ds,
+ u32 segno, u32 ec)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_segment_header *sh = &ds->ds_sh;
+ int i;
+
+ memset(ds, 0, sizeof(*ds));
+ set_segment_header(sh, SEG_SUPER, 0, segno, ec);
+
+ ds->ds_ifile_levels = super->s_ifile_levels;
+ ds->ds_iblock_levels = super->s_iblock_levels;
+ ds->ds_data_levels = super->s_data_levels; /* XXX: Remove */
+ ds->ds_segment_shift = super->s_segshift;
+ ds->ds_block_shift = sb->s_blocksize_bits;
+ ds->ds_write_shift = super->s_writeshift;
+ ds->ds_filesystem_size = cpu_to_be64(super->s_size);
+ ds->ds_segment_size = cpu_to_be32(super->s_segsize);
+ ds->ds_bad_seg_reserve = cpu_to_be32(super->s_bad_seg_reserve);
+ ds->ds_feature_incompat = cpu_to_be64(super->s_feature_incompat);
+ ds->ds_feature_ro_compat= cpu_to_be64(super->s_feature_ro_compat);
+ ds->ds_feature_compat = cpu_to_be64(super->s_feature_compat);
+ ds->ds_feature_flags = cpu_to_be64(super->s_feature_flags);
+ ds->ds_root_reserve = cpu_to_be64(super->s_root_reserve);
+ ds->ds_speed_reserve = cpu_to_be64(super->s_speed_reserve);
+ journal_for_each(i)
+ ds->ds_journal_seg[i] = cpu_to_be32(super->s_journal_seg[i]);
+ ds->ds_magic = cpu_to_be64(LOGFS_MAGIC);
+ ds->ds_crc = logfs_crc32(ds, sizeof(*ds),
+ LOGFS_SEGMENT_HEADERSIZE + 12);
+}
+
+static int write_one_sb(struct super_block *sb,
+ struct page *(*find_sb)(struct super_block *sb, u64 *ofs))
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_disk_super *ds;
+ struct logfs_segment_entry se;
+ struct page *page;
+ u64 ofs;
+ u32 ec, segno;
+ int err;
+
+ page = find_sb(sb, &ofs);
+ if (!page)
+ return -EIO;
+ ds = page_address(page);
+ segno = seg_no(sb, ofs);
+ logfs_get_segment_entry(sb, segno, &se);
+ ec = be32_to_cpu(se.ec_level) >> 4;
+ ec++;
+ logfs_set_segment_erased(sb, segno, ec, 0);
+ logfs_write_ds(sb, ds, segno, ec);
+ err = super->s_devops->write_sb(sb, page);
+ page_cache_release(page);
+ return err;
+}
+
+int logfs_write_sb(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ int err;
+
+ /* First superblock */
+ err = write_one_sb(sb, super->s_devops->find_first_sb);
+ if (err)
+ return err;
+
+ /* Last superblock */
+ err = write_one_sb(sb, super->s_devops->find_last_sb);
+ if (err)
+ return err;
+ return 0;
+}
+
+static int ds_cmp(const void *ds0, const void *ds1)
+{
+ size_t len = sizeof(struct logfs_disk_super);
+
+ /* We know the segment headers differ, so ignore them */
+ len -= LOGFS_SEGMENT_HEADERSIZE;
+ ds0 += LOGFS_SEGMENT_HEADERSIZE;
+ ds1 += LOGFS_SEGMENT_HEADERSIZE;
+ return memcmp(ds0, ds1, len);
+}
+
+static int logfs_recover_sb(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct logfs_disk_super _ds0, *ds0 = &_ds0;
+ struct logfs_disk_super _ds1, *ds1 = &_ds1;
+ int err, valid0, valid1;
+
+ /* read first superblock */
+ err = wbuf_read(sb, super->s_sb_ofs[0], sizeof(*ds0), ds0);
+ if (err)
+ return err;
+ /* read last superblock */
+ err = wbuf_read(sb, super->s_sb_ofs[1], sizeof(*ds1), ds1);
+ if (err)
+ return err;
+ valid0 = logfs_check_ds(ds0) == 0;
+ valid1 = logfs_check_ds(ds1) == 0;
+
+ if (!valid0 && valid1) {
+ printk(KERN_INFO"First superblock is invalid - fixing.\n");
+ return write_one_sb(sb, super->s_devops->find_first_sb);
+ }
+ if (valid0 && !valid1) {
+ printk(KERN_INFO"Last superblock is invalid - fixing.\n");
+ return write_one_sb(sb, super->s_devops->find_last_sb);
+ }
+ if (valid0 && valid1 && ds_cmp(ds0, ds1)) {
+ printk(KERN_INFO"Superblocks don't match - fixing.\n");
+ return write_one_sb(sb, super->s_devops->find_last_sb);
+ }
+ /* If neither is valid now, something's wrong. Didn't we properly
+ * check them before?!? */
+ BUG_ON(!valid0 && !valid1);
+ return 0;
+}
+
+static int logfs_make_writeable(struct super_block *sb)
+{
+ int err;
+
+ /* Repair any broken superblock copies */
+ err = logfs_recover_sb(sb);
+ if (err)
+ return err;
+
+ /* Check areas for trailing unaccounted data */
+ err = logfs_check_areas(sb);
+ if (err)
+ return err;
+
+ err = logfs_open_segfile(sb);
+ if (err)
+ return err;
+
+ /* Do one GC pass before any data gets dirtied */
+ logfs_gc_pass(sb);
+
+ /* after all initializations are done, replay the journal
+ * for rw-mounts, if necessary */
+ err = logfs_replay_journal(sb);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static int logfs_get_sb_final(struct super_block *sb, struct vfsmount *mnt)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct inode *rootdir;
+ int err;
+
+ /* root dir */
+ rootdir = logfs_iget(sb, LOGFS_INO_ROOT);
+ if (IS_ERR(rootdir))
+ goto fail;
+
+ sb->s_root = d_alloc_root(rootdir);
+ if (!sb->s_root)
+ goto fail;
+
+ super->s_erase_page = alloc_pages(GFP_KERNEL, 0);
+ if (!super->s_erase_page)
+ goto fail2;
+ memset(page_address(super->s_erase_page), 0xFF, PAGE_SIZE);
+
+ /* FIXME: check for read-only mounts */
+ err = logfs_make_writeable(sb);
+ if (err)
+ goto fail3;
+
+ log_super("LogFS: Finished mounting\n");
+ simple_set_mnt(mnt, sb);
+ return 0;
+
+fail3:
+ __free_page(super->s_erase_page);
+fail2:
+ iput(rootdir);
+fail:
+ iput(logfs_super(sb)->s_master_inode);
+ return -EIO;
+}
+
+int logfs_check_ds(struct logfs_disk_super *ds)
+{
+ struct logfs_segment_header *sh = &ds->ds_sh;
+
+ if (ds->ds_magic != cpu_to_be64(LOGFS_MAGIC))
+ return -EINVAL;
+ if (sh->crc != logfs_crc32(sh, LOGFS_SEGMENT_HEADERSIZE, 4))
+ return -EINVAL;
+ if (ds->ds_crc != logfs_crc32(ds, sizeof(*ds),
+ LOGFS_SEGMENT_HEADERSIZE + 12))
+ return -EINVAL;
+ return 0;
+}
+
+static struct page *find_super_block(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct page *first, *last;
+
+ first = super->s_devops->find_first_sb(sb, &super->s_sb_ofs[0]);
+ if (!first || IS_ERR(first))
+ return NULL;
+ last = super->s_devops->find_last_sb(sb, &super->s_sb_ofs[1]);
+ if (!last || IS_ERR(first)) {
+ page_cache_release(first);
+ return NULL;
+ }
+
+ if (!logfs_check_ds(page_address(first))) {
+ page_cache_release(last);
+ return first;
+ }
+
+ /* First one didn't work, try the second superblock */
+ if (!logfs_check_ds(page_address(last))) {
+ page_cache_release(first);
+ return last;
+ }
+
+ /* Neither worked, sorry folks */
+ page_cache_release(first);
+ page_cache_release(last);
+ return NULL;
+}
+
+static int __logfs_read_sb(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+ struct page *page;
+ struct logfs_disk_super *ds;
+ int i;
+
+ page = find_super_block(sb);
+ if (!page)
+ return -EIO;
+
+ ds = page_address(page);
+ super->s_size = be64_to_cpu(ds->ds_filesystem_size);
+ super->s_root_reserve = be64_to_cpu(ds->ds_root_reserve);
+ super->s_speed_reserve = be64_to_cpu(ds->ds_speed_reserve);
+ super->s_bad_seg_reserve = be32_to_cpu(ds->ds_bad_seg_reserve);
+ super->s_segsize = 1 << ds->ds_segment_shift;
+ super->s_segmask = (1 << ds->ds_segment_shift) - 1;
+ super->s_segshift = ds->ds_segment_shift;
+ sb->s_blocksize = 1 << ds->ds_block_shift;
+ sb->s_blocksize_bits = ds->ds_block_shift;
+ super->s_writesize = 1 << ds->ds_write_shift;
+ super->s_writeshift = ds->ds_write_shift;
+ super->s_no_segs = super->s_size >> super->s_segshift;
+ super->s_no_blocks = super->s_segsize >> sb->s_blocksize_bits;
+ super->s_feature_incompat = be64_to_cpu(ds->ds_feature_incompat);
+ super->s_feature_ro_compat = be64_to_cpu(ds->ds_feature_ro_compat);
+ super->s_feature_compat = be64_to_cpu(ds->ds_feature_compat);
+ super->s_feature_flags = be64_to_cpu(ds->ds_feature_flags);
+
+ journal_for_each(i)
+ super->s_journal_seg[i] = be32_to_cpu(ds->ds_journal_seg[i]);
+
+ super->s_ifile_levels = ds->ds_ifile_levels;
+ super->s_iblock_levels = ds->ds_iblock_levels;
+ super->s_data_levels = ds->ds_data_levels;
+ super->s_total_levels = super->s_ifile_levels + super->s_iblock_levels
+ + super->s_data_levels;
+ page_cache_release(page);
+ return 0;
+}
+
+static int logfs_read_sb(struct super_block *sb, int read_only)
+{
+ struct logfs_super *super = logfs_super(sb);
+ int ret;
+
+ super->s_btree_pool = mempool_create(32, btree_alloc, btree_free, NULL);
+ if (!super->s_btree_pool)
+ return -ENOMEM;
+
+ btree_init_mempool64(&super->s_shadow_tree.new, super->s_btree_pool);
+ btree_init_mempool64(&super->s_shadow_tree.old, super->s_btree_pool);
+
+ ret = logfs_init_mapping(sb);
+ if (ret)
+ return ret;
+
+ ret = __logfs_read_sb(sb);
+ if (ret)
+ return ret;
+
+ if (super->s_feature_incompat & ~LOGFS_FEATURES_INCOMPAT)
+ return -EIO;
+ if ((super->s_feature_ro_compat & ~LOGFS_FEATURES_RO_COMPAT) &&
+ !read_only)
+ return -EIO;
+
+ mutex_init(&super->s_dirop_mutex);
+ mutex_init(&super->s_object_alias_mutex);
+ INIT_LIST_HEAD(&super->s_freeing_list);
+
+ ret = logfs_init_rw(sb);
+ if (ret)
+ return ret;
+
+ ret = logfs_init_areas(sb);
+ if (ret)
+ return ret;
+
+ ret = logfs_init_gc(sb);
+ if (ret)
+ return ret;
+
+ ret = logfs_init_journal(sb);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void logfs_kill_sb(struct super_block *sb)
+{
+ struct logfs_super *super = logfs_super(sb);
+
+ log_super("LogFS: Start unmounting\n");
+ /* Alias entries slow down mount, so evict as many as possible */
+ sync_filesystem(sb);
+ logfs_write_anchor(sb);
+
+ /*
+ * From this point on alias entries are simply dropped - and any
+ * writes to the object store are considered bugs.
+ */
+ super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN;
+ log_super("LogFS: Now in shutdown\n");
+ generic_shutdown_super(sb);
+
+ BUG_ON(super->s_dirty_used_bytes || super->s_dirty_free_bytes);
+
+ logfs_cleanup_gc(sb);
+ logfs_cleanup_journal(sb);
+ logfs_cleanup_areas(sb);
+ logfs_cleanup_rw(sb);
+ if (super->s_erase_page)
+ __free_page(super->s_erase_page);
+ super->s_devops->put_device(sb);
+ mempool_destroy(super->s_btree_pool);
+ mempool_destroy(super->s_alias_pool);
+ kfree(super);
+ log_super("LogFS: Finished unmounting\n");
+}
+
+int logfs_get_sb_device(struct file_system_type *type, int flags,
+ struct mtd_info *mtd, struct block_device *bdev,
+ const struct logfs_device_ops *devops, struct vfsmount *mnt)
+{
+ struct logfs_super *super;
+ struct super_block *sb;
+ int err = -ENOMEM;
+ static int mount_count;
+
+ log_super("LogFS: Start mount %x\n", mount_count++);
+ super = kzalloc(sizeof(*super), GFP_KERNEL);
+ if (!super)
+ goto err0;
+
+ super->s_mtd = mtd;
+ super->s_bdev = bdev;
+ err = -EINVAL;
+ sb = sget(type, logfs_sb_test, logfs_sb_set, super);
+ if (IS_ERR(sb))
+ goto err0;
+
+ if (sb->s_root) {
+ /* Device is already in use */
+ err = 0;
+ simple_set_mnt(mnt, sb);
+ goto err0;
+ }
+
+ super->s_devops = devops;
+
+ /*
+ * sb->s_maxbytes is limited to 8TB. On 32bit systems, the page cache
+ * only covers 16TB and the upper 8TB are used for indirect blocks.
+ * On 64bit system we could bump up the limit, but that would make
+ * the filesystem incompatible with 32bit systems.
+ */
+ sb->s_maxbytes = (1ull << 43) - 1;
+ sb->s_op = &logfs_super_operations;
+ sb->s_flags = flags | MS_NOATIME;
+
+ err = logfs_read_sb(sb, sb->s_flags & MS_RDONLY);
+ if (err)
+ goto err1;
+
+ sb->s_flags |= MS_ACTIVE;
+ err = logfs_get_sb_final(sb, mnt);
+ if (err)
+ goto err1;
+ return 0;
+
+err1:
+ up_write(&sb->s_umount);
+ deactivate_super(sb);
+ return err;
+err0:
+ kfree(super);
+ //devops->put_device(sb);
+ return err;
+}
+
+static int logfs_get_sb(struct file_system_type *type, int flags,
+ const char *devname, void *data, struct vfsmount *mnt)
+{
+ ulong mtdnr;
+
+ if (!devname)
+ return logfs_get_sb_bdev(type, flags, devname, mnt);
+ if (strncmp(devname, "mtd", 3))
+ return logfs_get_sb_bdev(type, flags, devname, mnt);
+
+ {
+ char *garbage;
+ mtdnr = simple_strtoul(devname+3, &garbage, 0);
+ if (*garbage)
+ return -EINVAL;
+ }
+
+ return logfs_get_sb_mtd(type, flags, mtdnr, mnt);
+}
+
+static struct file_system_type logfs_fs_type = {
+ .owner = THIS_MODULE,
+ .name = "logfs",
+ .get_sb = logfs_get_sb,
+ .kill_sb = logfs_kill_sb,
+ .fs_flags = FS_REQUIRES_DEV,
+
+};
+
+static int __init logfs_init(void)
+{
+ int ret;
+
+ emergency_page = alloc_pages(GFP_KERNEL, 0);
+ if (!emergency_page)
+ return -ENOMEM;
+
+ ret = logfs_compr_init();
+ if (ret)
+ goto out1;
+
+ ret = logfs_init_inode_cache();
+ if (ret)
+ goto out2;
+
+ return register_filesystem(&logfs_fs_type);
+out2:
+ logfs_compr_exit();
+out1:
+ __free_pages(emergency_page, 0);
+ return ret;
+}
+
+static void __exit logfs_exit(void)
+{
+ unregister_filesystem(&logfs_fs_type);
+ logfs_destroy_inode_cache();
+ logfs_compr_exit();
+ __free_pages(emergency_page, 0);
+}
+
+module_init(logfs_init);
+module_exit(logfs_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Joern Engel <joern@logfs.org>");
+MODULE_DESCRIPTION("scalable flash filesystem");
diff --git a/fs/namei.c b/fs/namei.c
index 3d9d2f965f8..48e60a18732 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1656,7 +1656,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
if (path->dentry->d_inode->i_op->follow_link)
return NULL;
error = -ENOTDIR;
- if (*want_dir & !path->dentry->d_inode->i_op->lookup)
+ if (*want_dir && !path->dentry->d_inode->i_op->lookup)
goto exit_dput;
path_to_nameidata(path, nd);
audit_inode(pathname, nd->path.dentry);
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 73ab220354d..36dfdae9512 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -118,7 +118,6 @@ nfs4_callback_up(struct svc_serv *serv)
dprintk("NFS: Callback listener port = %u (af %u)\n",
nfs_callback_tcpport, PF_INET);
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
ret = svc_create_xprt(serv, "tcp", PF_INET6,
nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
if (ret > 0) {
@@ -129,7 +128,6 @@ nfs4_callback_up(struct svc_serv *serv)
ret = 0;
else
goto out_err;
-#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
return svc_prepare_thread(serv, &serv->sv_pools[0]);
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index c6eed2a3b09..4bc22c763de 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -525,6 +525,8 @@ static struct rpc_cred *callback_cred;
int set_callback_cred(void)
{
+ if (callback_cred)
+ return 0;
callback_cred = rpc_lookup_machine_cred();
if (!callback_cred)
return -ENOMEM;
@@ -542,7 +544,8 @@ void do_probe_callback(struct nfs4_client *clp)
};
int status;
- status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_SOFT,
+ status = rpc_call_async(cb->cb_client, &msg,
+ RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
&nfsd4_cb_probe_ops, (void *)clp);
if (status) {
warn_no_callback_path(clp, status);
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 5a754f7b71e..98fb98e330b 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -119,9 +119,7 @@ out_no_tfm:
static void
nfsd4_sync_rec_dir(void)
{
- mutex_lock(&rec_dir.dentry->d_inode->i_mutex);
- nfsd_sync_dir(rec_dir.dentry);
- mutex_unlock(&rec_dir.dentry->d_inode->i_mutex);
+ vfs_fsync(NULL, rec_dir.dentry, 0);
}
int
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index f19ed866c95..c97fddbd17d 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1998,7 +1998,9 @@ nfs4_file_downgrade(struct file *filp, unsigned int share_access)
{
if (share_access & NFS4_SHARE_ACCESS_WRITE) {
drop_file_write_access(filp);
+ spin_lock(&filp->f_lock);
filp->f_mode = (filp->f_mode | FMODE_READ) & ~FMODE_WRITE;
+ spin_unlock(&filp->f_lock);
}
}
@@ -2480,8 +2482,10 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
}
memcpy(&open->op_stateid, &stp->st_stateid, sizeof(stateid_t));
- if (nfsd4_has_session(&resp->cstate))
+ if (nfsd4_has_session(&resp->cstate)) {
open->op_stateowner->so_confirmed = 1;
+ nfsd4_create_clid_dir(open->op_stateowner->so_client);
+ }
/*
* Attempt to hand out a delegation. No error return, because the
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index bbf72d8f9fc..78c7e24e512 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1434,7 +1434,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
}
op->opnum = ntohl(*argp->p++);
- if (op->opnum >= OP_ACCESS && op->opnum < ops->nops)
+ if (op->opnum >= FIRST_NFS4_OP && op->opnum <= LAST_NFS4_OP)
op->status = ops->decoders[op->opnum](argp, &op->u);
else {
op->opnum = OP_ILLEGAL;
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 2604c3e70ea..0f0e77f2012 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -988,6 +988,7 @@ static ssize_t __write_ports_delfd(char *buf)
static ssize_t __write_ports_addxprt(char *buf)
{
char transport[16];
+ struct svc_xprt *xprt;
int port, err;
if (sscanf(buf, "%15s %4u", transport, &port) != 2)
@@ -1002,13 +1003,24 @@ static ssize_t __write_ports_addxprt(char *buf)
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;
- }
+ if (err < 0)
+ goto out_err;
+
+ err = svc_create_xprt(nfsd_serv, transport,
+ PF_INET6, port, SVC_SOCK_ANONYMOUS);
+ if (err < 0 && err != -EAFNOSUPPORT)
+ goto out_close;
return 0;
+out_close:
+ xprt = svc_find_xprt(nfsd_serv, transport, PF_INET, port);
+ if (xprt != NULL) {
+ svc_close_xprt(xprt);
+ svc_xprt_put(xprt);
+ }
+out_err:
+ /* Decrease the count, but don't shut down the service */
+ nfsd_serv->sv_nrthreads--;
+ return err;
}
/*
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 8eca17df4f6..a11b0e8678e 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -26,6 +26,8 @@
#include <linux/jhash.h>
#include <linux/ima.h>
#include <asm/uaccess.h>
+#include <linux/exportfs.h>
+#include <linux/writeback.h>
#ifdef CONFIG_NFSD_V3
#include "xdr3.h"
@@ -270,6 +272,32 @@ out:
return err;
}
+/*
+ * Commit metadata changes to stable storage.
+ */
+static int
+commit_metadata(struct svc_fh *fhp)
+{
+ struct inode *inode = fhp->fh_dentry->d_inode;
+ const struct export_operations *export_ops = inode->i_sb->s_export_op;
+ int error = 0;
+
+ if (!EX_ISSYNC(fhp->fh_export))
+ return 0;
+
+ if (export_ops->commit_metadata) {
+ error = export_ops->commit_metadata(inode);
+ } else {
+ struct writeback_control wbc = {
+ .sync_mode = WB_SYNC_ALL,
+ .nr_to_write = 0, /* metadata only */
+ };
+
+ error = sync_inode(inode, &wbc);
+ }
+
+ return error;
+}
/*
* Set various file attributes.
@@ -767,43 +795,6 @@ nfsd_close(struct file *filp)
}
/*
- * Sync a file
- * As this calls fsync (not fdatasync) there is no need for a write_inode
- * after it.
- */
-static inline int nfsd_dosync(struct file *filp, struct dentry *dp,
- const struct file_operations *fop)
-{
- struct inode *inode = dp->d_inode;
- int (*fsync) (struct file *, struct dentry *, int);
- int err;
-
- err = filemap_write_and_wait(inode->i_mapping);
- if (err == 0 && fop && (fsync = fop->fsync))
- err = fsync(filp, dp, 0);
- return err;
-}
-
-static int
-nfsd_sync(struct file *filp)
-{
- int err;
- struct inode *inode = filp->f_path.dentry->d_inode;
- dprintk("nfsd: sync file %s\n", filp->f_path.dentry->d_name.name);
- mutex_lock(&inode->i_mutex);
- err=nfsd_dosync(filp, filp->f_path.dentry, filp->f_op);
- mutex_unlock(&inode->i_mutex);
-
- return err;
-}
-
-int
-nfsd_sync_dir(struct dentry *dp)
-{
- return nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
-}
-
-/*
* Obtain the readahead parameters for the file
* specified by (dev, ino).
*/
@@ -1006,7 +997,7 @@ static int wait_for_concurrent_writes(struct file *file)
if (inode->i_state & I_DIRTY) {
dprintk("nfsd: write sync %d\n", task_pid_nr(current));
- err = nfsd_sync(file);
+ err = vfs_fsync(file, file->f_path.dentry, 0);
}
last_ino = inode->i_ino;
last_dev = inode->i_sb->s_dev;
@@ -1154,8 +1145,9 @@ out:
#ifdef CONFIG_NFSD_V3
/*
* Commit all pending writes to stable storage.
- * Strictly speaking, we could sync just the indicated file region here,
- * but there's currently no way we can ask the VFS to do so.
+ *
+ * Note: we only guarantee that data that lies within the range specified
+ * by the 'offset' and 'count' parameters will be synced.
*
* Unfortunately we cannot lock the file to make sure we return full WCC
* data to the client, as locking happens lower down in the filesystem.
@@ -1165,23 +1157,32 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
loff_t offset, unsigned long count)
{
struct file *file;
- __be32 err;
+ loff_t end = LLONG_MAX;
+ __be32 err = nfserr_inval;
- if ((u64)count > ~(u64)offset)
- return nfserr_inval;
+ if (offset < 0)
+ goto out;
+ if (count != 0) {
+ end = offset + (loff_t)count - 1;
+ if (end < offset)
+ goto out;
+ }
err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_WRITE, &file);
if (err)
- return err;
+ goto out;
if (EX_ISSYNC(fhp->fh_export)) {
- if (file->f_op && file->f_op->fsync) {
- err = nfserrno(nfsd_sync(file));
- } else {
+ int err2 = vfs_fsync_range(file, file->f_path.dentry,
+ offset, end, 0);
+
+ if (err2 != -EINVAL)
+ err = nfserrno(err2);
+ else
err = nfserr_notsupp;
- }
}
nfsd_close(file);
+out:
return err;
}
#endif /* CONFIG_NFSD_V3 */
@@ -1334,12 +1335,14 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
goto out_nfserr;
}
- if (EX_ISSYNC(fhp->fh_export)) {
- err = nfserrno(nfsd_sync_dir(dentry));
- write_inode_now(dchild->d_inode, 1);
- }
+ err = nfsd_create_setattr(rqstp, resfhp, iap);
- err2 = nfsd_create_setattr(rqstp, resfhp, iap);
+ /*
+ * nfsd_setattr already committed the child. Transactional filesystems
+ * had a chance to commit changes for both parent and child
+ * simultaneously making the following commit_metadata a noop.
+ */
+ err2 = nfserrno(commit_metadata(fhp));
if (err2)
err = err2;
mnt_drop_write(fhp->fh_export->ex_path.mnt);
@@ -1371,7 +1374,6 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
struct dentry *dentry, *dchild = NULL;
struct inode *dirp;
__be32 err;
- __be32 err2;
int host_err;
__u32 v_mtime=0, v_atime=0;
@@ -1466,11 +1468,6 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
if (created)
*created = 1;
- if (EX_ISSYNC(fhp->fh_export)) {
- err = nfserrno(nfsd_sync_dir(dentry));
- /* setattr will sync the child (or not) */
- }
-
nfsd_check_ignore_resizing(iap);
if (createmode == NFS3_CREATE_EXCLUSIVE) {
@@ -1485,9 +1482,13 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
}
set_attr:
- err2 = nfsd_create_setattr(rqstp, resfhp, iap);
- if (err2)
- err = err2;
+ err = nfsd_create_setattr(rqstp, resfhp, iap);
+
+ /*
+ * nfsd_setattr already committed the child (and possibly also the parent).
+ */
+ if (!err)
+ err = nfserrno(commit_metadata(fhp));
mnt_drop_write(fhp->fh_export->ex_path.mnt);
/*
@@ -1602,12 +1603,9 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
}
} else
host_err = vfs_symlink(dentry->d_inode, dnew, path);
-
- if (!host_err) {
- if (EX_ISSYNC(fhp->fh_export))
- host_err = nfsd_sync_dir(dentry);
- }
err = nfserrno(host_err);
+ if (!err)
+ err = nfserrno(commit_metadata(fhp));
fh_unlock(fhp);
mnt_drop_write(fhp->fh_export->ex_path.mnt);
@@ -1669,11 +1667,9 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
}
host_err = vfs_link(dold, dirp, dnew);
if (!host_err) {
- if (EX_ISSYNC(ffhp->fh_export)) {
- err = nfserrno(nfsd_sync_dir(ddir));
- write_inode_now(dest, 1);
- }
- err = 0;
+ err = nfserrno(commit_metadata(ffhp));
+ if (!err)
+ err = nfserrno(commit_metadata(tfhp));
} else {
if (host_err == -EXDEV && rqstp->rq_vers == 2)
err = nfserr_acces;
@@ -1769,10 +1765,10 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen,
goto out_dput_new;
host_err = vfs_rename(fdir, odentry, tdir, ndentry);
- if (!host_err && EX_ISSYNC(tfhp->fh_export)) {
- host_err = nfsd_sync_dir(tdentry);
+ if (!host_err) {
+ host_err = commit_metadata(tfhp);
if (!host_err)
- host_err = nfsd_sync_dir(fdentry);
+ host_err = commit_metadata(ffhp);
}
mnt_drop_write(ffhp->fh_export->ex_path.mnt);
@@ -1853,12 +1849,9 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
dput(rdentry);
- if (host_err)
- goto out_drop;
- if (EX_ISSYNC(fhp->fh_export))
- host_err = nfsd_sync_dir(dentry);
+ if (!host_err)
+ host_err = commit_metadata(fhp);
-out_drop:
mnt_drop_write(fhp->fh_export->ex_path.mnt);
out_nfserr:
err = nfserrno(host_err);
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c
index b39da877b12..3bb928a2bf7 100644
--- a/fs/ocfs2/cluster/masklog.c
+++ b/fs/ocfs2/cluster/masklog.c
@@ -136,7 +136,7 @@ static ssize_t mlog_store(struct kobject *obj, struct attribute *attr,
return mlog_mask_store(mlog_attr->mask, buf, count);
}
-static struct sysfs_ops mlog_attr_ops = {
+static const struct sysfs_ops mlog_attr_ops = {
.show = mlog_show,
.store = mlog_store,
};
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c
index 21f9e71223c..a6467f3d262 100644
--- a/fs/ocfs2/quota_local.c
+++ b/fs/ocfs2/quota_local.c
@@ -457,7 +457,7 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
break;
}
dchunk = (struct ocfs2_local_disk_chunk *)hbh->b_data;
- for_each_bit(bit, rchunk->rc_bitmap, ol_chunk_entries(sb)) {
+ for_each_set_bit(bit, rchunk->rc_bitmap, ol_chunk_entries(sb)) {
qbh = NULL;
status = ocfs2_read_quota_block(lqinode,
ol_dqblk_block(sb, chunk, bit),
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 18e20feee25..aa8637b8102 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -273,7 +273,7 @@ static inline void task_sig(struct seq_file *m, struct task_struct *p)
rcu_read_lock(); /* FIXME: is this correct? */
qsize = atomic_read(&__task_cred(p)->user->sigpending);
rcu_read_unlock();
- qlim = p->signal->rlim[RLIMIT_SIGPENDING].rlim_cur;
+ qlim = task_rlimit(p, RLIMIT_SIGPENDING);
unlock_task_sighand(p, &flags);
}
@@ -420,7 +420,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
cutime = sig->cutime;
cstime = sig->cstime;
cgtime = sig->cgtime;
- rsslim = sig->rlim[RLIMIT_RSS].rlim_cur;
+ rsslim = ACCESS_ONCE(sig->rlim[RLIMIT_RSS].rlim_cur);
/* add up live thread stats at the group level */
if (whole) {
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 9580abeadeb..08f4d71dacd 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -291,19 +291,17 @@ static const struct inode_operations proc_file_inode_operations = {
* returns the struct proc_dir_entry for "/proc/tty/driver", and
* returns "serial" in residual.
*/
-static int xlate_proc_name(const char *name,
- struct proc_dir_entry **ret, const char **residual)
+static int __xlate_proc_name(const char *name, struct proc_dir_entry **ret,
+ const char **residual)
{
const char *cp = name, *next;
struct proc_dir_entry *de;
int len;
- int rtn = 0;
de = *ret;
if (!de)
de = &proc_root;
- spin_lock(&proc_subdir_lock);
while (1) {
next = strchr(cp, '/');
if (!next)
@@ -315,16 +313,25 @@ static int xlate_proc_name(const char *name,
break;
}
if (!de) {
- rtn = -ENOENT;
- goto out;
+ WARN(1, "name '%s'\n", name);
+ return -ENOENT;
}
cp += len + 1;
}
*residual = cp;
*ret = de;
-out:
+ return 0;
+}
+
+static int xlate_proc_name(const char *name, struct proc_dir_entry **ret,
+ const char **residual)
+{
+ int rv;
+
+ spin_lock(&proc_subdir_lock);
+ rv = __xlate_proc_name(name, ret, residual);
spin_unlock(&proc_subdir_lock);
- return rtn;
+ return rv;
}
static DEFINE_IDA(proc_inum_ida);
@@ -797,11 +804,13 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
const char *fn = name;
int len;
- if (xlate_proc_name(name, &parent, &fn) != 0)
+ spin_lock(&proc_subdir_lock);
+ if (__xlate_proc_name(name, &parent, &fn) != 0) {
+ spin_unlock(&proc_subdir_lock);
return;
+ }
len = strlen(fn);
- spin_lock(&proc_subdir_lock);
for (p = &parent->subdir; *p; p=&(*p)->next ) {
if (proc_match(len, fn, *p)) {
de = *p;
@@ -811,8 +820,10 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)
}
}
spin_unlock(&proc_subdir_lock);
- if (!de)
+ if (!de) {
+ WARN(1, "name '%s'\n", name);
return;
+ }
spin_lock(&de->pde_unload_lock);
/*
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index f277c4a111c..183f8ff5f40 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -16,7 +16,7 @@
void task_mem(struct seq_file *m, struct mm_struct *mm)
{
- unsigned long data, text, lib;
+ unsigned long data, text, lib, swap;
unsigned long hiwater_vm, total_vm, hiwater_rss, total_rss;
/*
@@ -36,6 +36,7 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
data = mm->total_vm - mm->shared_vm - mm->stack_vm;
text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) >> 10;
lib = (mm->exec_vm << (PAGE_SHIFT-10)) - text;
+ swap = get_mm_counter(mm, MM_SWAPENTS);
seq_printf(m,
"VmPeak:\t%8lu kB\n"
"VmSize:\t%8lu kB\n"
@@ -46,7 +47,8 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
"VmStk:\t%8lu kB\n"
"VmExe:\t%8lu kB\n"
"VmLib:\t%8lu kB\n"
- "VmPTE:\t%8lu kB\n",
+ "VmPTE:\t%8lu kB\n"
+ "VmSwap:\t%8lu kB\n",
hiwater_vm << (PAGE_SHIFT-10),
(total_vm - mm->reserved_vm) << (PAGE_SHIFT-10),
mm->locked_vm << (PAGE_SHIFT-10),
@@ -54,7 +56,8 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)
total_rss << (PAGE_SHIFT-10),
data << (PAGE_SHIFT-10),
mm->stack_vm << (PAGE_SHIFT-10), text, lib,
- (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10);
+ (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10,
+ swap << (PAGE_SHIFT-10));
}
unsigned long task_vsize(struct mm_struct *mm)
@@ -65,11 +68,11 @@ unsigned long task_vsize(struct mm_struct *mm)
int task_statm(struct mm_struct *mm, int *shared, int *text,
int *data, int *resident)
{
- *shared = get_mm_counter(mm, file_rss);
+ *shared = get_mm_counter(mm, MM_FILEPAGES);
*text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK))
>> PAGE_SHIFT;
*data = mm->total_vm - mm->shared_vm;
- *resident = *shared + get_mm_counter(mm, anon_rss);
+ *resident = *shared + get_mm_counter(mm, MM_ANONPAGES);
return mm->total_vm;
}
diff --git a/fs/select.c b/fs/select.c
index fd38ce2e32e..73715e90030 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -821,7 +821,7 @@ int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds,
struct poll_list *walk = head;
unsigned long todo = nfds;
- if (nfds > current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
+ if (nfds > rlimit(RLIMIT_NOFILE))
return -EINVAL;
len = min_t(unsigned int, nfds, N_STACK_PPS);
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 5afd554efad..e1f437be6c3 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -734,7 +734,7 @@ EXPORT_SYMBOL(seq_hlist_start_head);
* seq_hlist_next - move to the next position of the hlist
* @v: the current iterator
* @head: the head of the hlist
- * @pos: the current posision
+ * @ppos: the current position
*
* Called at seq_file->op->next().
*/
@@ -800,7 +800,7 @@ EXPORT_SYMBOL(seq_hlist_start_head_rcu);
* seq_hlist_next_rcu - move to the next position of the hlist protected by RCU
* @v: the current iterator
* @head: the head of the hlist
- * @pos: the current posision
+ * @ppos: the current position
*
* Called at seq_file->op->next().
*
diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c
index a0a500af24a..e9d293593e5 100644
--- a/fs/sysfs/bin.c
+++ b/fs/sysfs/bin.c
@@ -54,14 +54,14 @@ fill_read(struct dentry *dentry, char *buffer, loff_t off, size_t count)
int rc;
/* need attr_sd for attr, its parent for kobj */
- if (!sysfs_get_active_two(attr_sd))
+ if (!sysfs_get_active(attr_sd))
return -ENODEV;
rc = -EIO;
if (attr->read)
rc = attr->read(kobj, attr, buffer, off, count);
- sysfs_put_active_two(attr_sd);
+ sysfs_put_active(attr_sd);
return rc;
}
@@ -125,14 +125,14 @@ flush_write(struct dentry *dentry, char *buffer, loff_t offset, size_t count)
int rc;
/* need attr_sd for attr, its parent for kobj */
- if (!sysfs_get_active_two(attr_sd))
+ if (!sysfs_get_active(attr_sd))
return -ENODEV;
rc = -EIO;
if (attr->write)
rc = attr->write(kobj, attr, buffer, offset, count);
- sysfs_put_active_two(attr_sd);
+ sysfs_put_active(attr_sd);
return rc;
}
@@ -184,12 +184,12 @@ static void bin_vma_open(struct vm_area_struct *vma)
if (!bb->vm_ops || !bb->vm_ops->open)
return;
- if (!sysfs_get_active_two(attr_sd))
+ if (!sysfs_get_active(attr_sd))
return;
bb->vm_ops->open(vma);
- sysfs_put_active_two(attr_sd);
+ sysfs_put_active(attr_sd);
}
static void bin_vma_close(struct vm_area_struct *vma)
@@ -201,12 +201,12 @@ static void bin_vma_close(struct vm_area_struct *vma)
if (!bb->vm_ops || !bb->vm_ops->close)
return;
- if (!sysfs_get_active_two(attr_sd))
+ if (!sysfs_get_active(attr_sd))
return;
bb->vm_ops->close(vma);
- sysfs_put_active_two(attr_sd);
+ sysfs_put_active(attr_sd);
}
static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
@@ -219,12 +219,12 @@ static int bin_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
if (!bb->vm_ops || !bb->vm_ops->fault)
return VM_FAULT_SIGBUS;
- if (!sysfs_get_active_two(attr_sd))
+ if (!sysfs_get_active(attr_sd))
return VM_FAULT_SIGBUS;
ret = bb->vm_ops->fault(vma, vmf);
- sysfs_put_active_two(attr_sd);
+ sysfs_put_active(attr_sd);
return ret;
}
@@ -241,12 +241,12 @@ static int bin_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
if (!bb->vm_ops->page_mkwrite)
return 0;
- if (!sysfs_get_active_two(attr_sd))
+ if (!sysfs_get_active(attr_sd))
return VM_FAULT_SIGBUS;
ret = bb->vm_ops->page_mkwrite(vma, vmf);
- sysfs_put_active_two(attr_sd);
+ sysfs_put_active(attr_sd);
return ret;
}
@@ -261,12 +261,12 @@ static int bin_access(struct vm_area_struct *vma, unsigned long addr,
if (!bb->vm_ops || !bb->vm_ops->access)
return -EINVAL;
- if (!sysfs_get_active_two(attr_sd))
+ if (!sysfs_get_active(attr_sd))
return -EINVAL;
ret = bb->vm_ops->access(vma, addr, buf, len, write);
- sysfs_put_active_two(attr_sd);
+ sysfs_put_active(attr_sd);
return ret;
}
@@ -281,12 +281,12 @@ static int bin_set_policy(struct vm_area_struct *vma, struct mempolicy *new)
if (!bb->vm_ops || !bb->vm_ops->set_policy)
return 0;
- if (!sysfs_get_active_two(attr_sd))
+ if (!sysfs_get_active(attr_sd))
return -EINVAL;
ret = bb->vm_ops->set_policy(vma, new);
- sysfs_put_active_two(attr_sd);
+ sysfs_put_active(attr_sd);
return ret;
}
@@ -301,12 +301,12 @@ static struct mempolicy *bin_get_policy(struct vm_area_struct *vma,
if (!bb->vm_ops || !bb->vm_ops->get_policy)
return vma->vm_policy;
- if (!sysfs_get_active_two(attr_sd))
+ if (!sysfs_get_active(attr_sd))
return vma->vm_policy;
pol = bb->vm_ops->get_policy(vma, addr);
- sysfs_put_active_two(attr_sd);
+ sysfs_put_active(attr_sd);
return pol;
}
@@ -321,12 +321,12 @@ static int bin_migrate(struct vm_area_struct *vma, const nodemask_t *from,
if (!bb->vm_ops || !bb->vm_ops->migrate)
return 0;
- if (!sysfs_get_active_two(attr_sd))
+ if (!sysfs_get_active(attr_sd))
return 0;
ret = bb->vm_ops->migrate(vma, from, to, flags);
- sysfs_put_active_two(attr_sd);
+ sysfs_put_active(attr_sd);
return ret;
}
#endif
@@ -356,7 +356,7 @@ static int mmap(struct file *file, struct vm_area_struct *vma)
/* need attr_sd for attr, its parent for kobj */
rc = -ENODEV;
- if (!sysfs_get_active_two(attr_sd))
+ if (!sysfs_get_active(attr_sd))
goto out_unlock;
rc = -EINVAL;
@@ -384,7 +384,7 @@ static int mmap(struct file *file, struct vm_area_struct *vma)
bb->vm_ops = vma->vm_ops;
vma->vm_ops = &bin_vm_ops;
out_put:
- sysfs_put_active_two(attr_sd);
+ sysfs_put_active(attr_sd);
out_unlock:
mutex_unlock(&bb->mutex);
@@ -399,7 +399,7 @@ static int open(struct inode * inode, struct file * file)
int error;
/* binary file operations requires both @sd and its parent */
- if (!sysfs_get_active_two(attr_sd))
+ if (!sysfs_get_active(attr_sd))
return -ENODEV;
error = -EACCES;
@@ -426,11 +426,11 @@ static int open(struct inode * inode, struct file * file)
mutex_unlock(&sysfs_bin_lock);
/* open succeeded, put active references */
- sysfs_put_active_two(attr_sd);
+ sysfs_put_active(attr_sd);
return 0;
err_out:
- sysfs_put_active_two(attr_sd);
+ sysfs_put_active(attr_sd);
kfree(bb);
return error;
}
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c
index 699f371b9f1..590717861c7 100644
--- a/fs/sysfs/dir.c
+++ b/fs/sysfs/dir.c
@@ -93,7 +93,7 @@ static void sysfs_unlink_sibling(struct sysfs_dirent *sd)
* RETURNS:
* Pointer to @sd on success, NULL on failure.
*/
-static struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
+struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
{
if (unlikely(!sd))
return NULL;
@@ -124,7 +124,7 @@ static struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd)
* Put an active reference to @sd. This function is noop if @sd
* is NULL.
*/
-static void sysfs_put_active(struct sysfs_dirent *sd)
+void sysfs_put_active(struct sysfs_dirent *sd)
{
struct completion *cmpl;
int v;
@@ -145,45 +145,6 @@ static void sysfs_put_active(struct sysfs_dirent *sd)
}
/**
- * sysfs_get_active_two - get active references to sysfs_dirent and parent
- * @sd: sysfs_dirent of interest
- *
- * Get active reference to @sd and its parent. Parent's active
- * reference is grabbed first. This function is noop if @sd is
- * NULL.
- *
- * RETURNS:
- * Pointer to @sd on success, NULL on failure.
- */
-struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd)
-{
- if (sd) {
- if (sd->s_parent && unlikely(!sysfs_get_active(sd->s_parent)))
- return NULL;
- if (unlikely(!sysfs_get_active(sd))) {
- sysfs_put_active(sd->s_parent);
- return NULL;
- }
- }
- return sd;
-}
-
-/**
- * sysfs_put_active_two - put active references to sysfs_dirent and parent
- * @sd: sysfs_dirent of interest
- *
- * Put active references to @sd and its parent. This function is
- * noop if @sd is NULL.
- */
-void sysfs_put_active_two(struct sysfs_dirent *sd)
-{
- if (sd) {
- sysfs_put_active(sd);
- sysfs_put_active(sd->s_parent);
- }
-}
-
-/**
* sysfs_deactivate - deactivate sysfs_dirent
* @sd: sysfs_dirent to deactivate
*
@@ -195,6 +156,10 @@ static void sysfs_deactivate(struct sysfs_dirent *sd)
int v;
BUG_ON(sd->s_sibling || !(sd->s_flags & SYSFS_FLAG_REMOVED));
+
+ if (!(sysfs_type(sd) & SYSFS_ACTIVE_REF))
+ return;
+
sd->s_sibling = (void *)&wait;
rwsem_acquire(&sd->dep_map, 0, 0, _RET_IP_);
@@ -354,7 +319,6 @@ struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
atomic_set(&sd->s_count, 1);
atomic_set(&sd->s_active, 0);
- sysfs_dirent_init_lockdep(sd);
sd->s_name = name;
sd->s_mode = mode;
@@ -681,7 +645,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
}
/* attach dentry and inode */
- inode = sysfs_get_inode(sd);
+ inode = sysfs_get_inode(dir->i_sb, sd);
if (!inode) {
ret = ERR_PTR(-ENOMEM);
goto out_unlock;
@@ -837,11 +801,46 @@ static inline unsigned char dt_type(struct sysfs_dirent *sd)
return (sd->s_mode >> 12) & 15;
}
+static int sysfs_dir_release(struct inode *inode, struct file *filp)
+{
+ sysfs_put(filp->private_data);
+ return 0;
+}
+
+static struct sysfs_dirent *sysfs_dir_pos(struct sysfs_dirent *parent_sd,
+ ino_t ino, struct sysfs_dirent *pos)
+{
+ if (pos) {
+ int valid = !(pos->s_flags & SYSFS_FLAG_REMOVED) &&
+ pos->s_parent == parent_sd &&
+ ino == pos->s_ino;
+ sysfs_put(pos);
+ if (valid)
+ return pos;
+ }
+ pos = NULL;
+ if ((ino > 1) && (ino < INT_MAX)) {
+ pos = parent_sd->s_dir.children;
+ while (pos && (ino > pos->s_ino))
+ pos = pos->s_sibling;
+ }
+ return pos;
+}
+
+static struct sysfs_dirent *sysfs_dir_next_pos(struct sysfs_dirent *parent_sd,
+ ino_t ino, struct sysfs_dirent *pos)
+{
+ pos = sysfs_dir_pos(parent_sd, ino, pos);
+ if (pos)
+ pos = pos->s_sibling;
+ return pos;
+}
+
static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
struct dentry *dentry = filp->f_path.dentry;
struct sysfs_dirent * parent_sd = dentry->d_fsdata;
- struct sysfs_dirent *pos;
+ struct sysfs_dirent *pos = filp->private_data;
ino_t ino;
if (filp->f_pos == 0) {
@@ -857,29 +856,31 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0)
filp->f_pos++;
}
- if ((filp->f_pos > 1) && (filp->f_pos < INT_MAX)) {
- mutex_lock(&sysfs_mutex);
-
- /* Skip the dentries we have already reported */
- pos = parent_sd->s_dir.children;
- while (pos && (filp->f_pos > pos->s_ino))
- pos = pos->s_sibling;
-
- for ( ; pos; pos = pos->s_sibling) {
- const char * name;
- int len;
-
- name = pos->s_name;
- len = strlen(name);
- filp->f_pos = ino = pos->s_ino;
+ mutex_lock(&sysfs_mutex);
+ for (pos = sysfs_dir_pos(parent_sd, filp->f_pos, pos);
+ pos;
+ pos = sysfs_dir_next_pos(parent_sd, filp->f_pos, pos)) {
+ const char * name;
+ unsigned int type;
+ int len, ret;
+
+ name = pos->s_name;
+ len = strlen(name);
+ ino = pos->s_ino;
+ type = dt_type(pos);
+ filp->f_pos = ino;
+ filp->private_data = sysfs_get(pos);
- if (filldir(dirent, name, len, filp->f_pos, ino,
- dt_type(pos)) < 0)
- break;
- }
- if (!pos)
- filp->f_pos = INT_MAX;
mutex_unlock(&sysfs_mutex);
+ ret = filldir(dirent, name, len, filp->f_pos, ino, type);
+ mutex_lock(&sysfs_mutex);
+ if (ret < 0)
+ break;
+ }
+ mutex_unlock(&sysfs_mutex);
+ if ((filp->f_pos > 1) && !pos) { /* EOF */
+ filp->f_pos = INT_MAX;
+ filp->private_data = NULL;
}
return 0;
}
@@ -888,5 +889,6 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
const struct file_operations sysfs_dir_operations = {
.read = generic_read_dir,
.readdir = sysfs_readdir,
+ .release = sysfs_dir_release,
.llseek = generic_file_llseek,
};
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index dc30d9e3168..e222b258274 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -53,7 +53,7 @@ struct sysfs_buffer {
size_t count;
loff_t pos;
char * page;
- struct sysfs_ops * ops;
+ const struct sysfs_ops * ops;
struct mutex mutex;
int needs_read_fill;
int event;
@@ -75,7 +75,7 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
{
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
- struct sysfs_ops * ops = buffer->ops;
+ const struct sysfs_ops * ops = buffer->ops;
int ret = 0;
ssize_t count;
@@ -85,13 +85,13 @@ static int fill_read_buffer(struct dentry * dentry, struct sysfs_buffer * buffer
return -ENOMEM;
/* need attr_sd for attr and ops, its parent for kobj */
- if (!sysfs_get_active_two(attr_sd))
+ if (!sysfs_get_active(attr_sd))
return -ENODEV;
buffer->event = atomic_read(&attr_sd->s_attr.open->event);
count = ops->show(kobj, attr_sd->s_attr.attr, buffer->page);
- sysfs_put_active_two(attr_sd);
+ sysfs_put_active(attr_sd);
/*
* The code works fine with PAGE_SIZE return but it's likely to
@@ -199,16 +199,16 @@ flush_write_buffer(struct dentry * dentry, struct sysfs_buffer * buffer, size_t
{
struct sysfs_dirent *attr_sd = dentry->d_fsdata;
struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
- struct sysfs_ops * ops = buffer->ops;
+ const struct sysfs_ops * ops = buffer->ops;
int rc;
/* need attr_sd for attr and ops, its parent for kobj */
- if (!sysfs_get_active_two(attr_sd))
+ if (!sysfs_get_active(attr_sd))
return -ENODEV;
rc = ops->store(kobj, attr_sd->s_attr.attr, buffer->page, count);
- sysfs_put_active_two(attr_sd);
+ sysfs_put_active(attr_sd);
return rc;
}
@@ -335,7 +335,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
struct sysfs_dirent *attr_sd = file->f_path.dentry->d_fsdata;
struct kobject *kobj = attr_sd->s_parent->s_dir.kobj;
struct sysfs_buffer *buffer;
- struct sysfs_ops *ops;
+ const struct sysfs_ops *ops;
int error = -EACCES;
char *p;
@@ -344,7 +344,7 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
memmove(last_sysfs_file, p, strlen(p) + 1);
/* need attr_sd for attr and ops, its parent for kobj */
- if (!sysfs_get_active_two(attr_sd))
+ if (!sysfs_get_active(attr_sd))
return -ENODEV;
/* every kobject with an attribute needs a ktype assigned */
@@ -393,13 +393,13 @@ static int sysfs_open_file(struct inode *inode, struct file *file)
goto err_free;
/* open succeeded, put active references */
- sysfs_put_active_two(attr_sd);
+ sysfs_put_active(attr_sd);
return 0;
err_free:
kfree(buffer);
err_out:
- sysfs_put_active_two(attr_sd);
+ sysfs_put_active(attr_sd);
return error;
}
@@ -437,12 +437,12 @@ static unsigned int sysfs_poll(struct file *filp, poll_table *wait)
struct sysfs_open_dirent *od = attr_sd->s_attr.open;
/* need parent for the kobj, grab both */
- if (!sysfs_get_active_two(attr_sd))
+ if (!sysfs_get_active(attr_sd))
goto trigger;
poll_wait(filp, &od->poll, wait);
- sysfs_put_active_two(attr_sd);
+ sysfs_put_active(attr_sd);
if (buffer->event != atomic_read(&od->event))
goto trigger;
@@ -509,6 +509,7 @@ int sysfs_add_file_mode(struct sysfs_dirent *dir_sd,
if (!sd)
return -ENOMEM;
sd->s_attr.attr = (void *)attr;
+ sysfs_dirent_init_lockdep(sd);
sysfs_addrm_start(&acxt, dir_sd);
rc = sysfs_add_one(&acxt, sd);
@@ -542,6 +543,18 @@ int sysfs_create_file(struct kobject * kobj, const struct attribute * attr)
}
+int sysfs_create_files(struct kobject *kobj, const struct attribute **ptr)
+{
+ int err = 0;
+ int i;
+
+ for (i = 0; ptr[i] && !err; i++)
+ err = sysfs_create_file(kobj, ptr[i]);
+ if (err)
+ while (--i >= 0)
+ sysfs_remove_file(kobj, ptr[i]);
+ return err;
+}
/**
* sysfs_add_file_to_group - add an attribute file to a pre-existing group.
@@ -614,6 +627,12 @@ void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr)
sysfs_hash_and_remove(kobj->sd, attr->name);
}
+void sysfs_remove_files(struct kobject * kobj, const struct attribute **ptr)
+{
+ int i;
+ for (i = 0; ptr[i]; i++)
+ sysfs_remove_file(kobj, ptr[i]);
+}
/**
* sysfs_remove_file_from_group - remove an attribute file from a group.
@@ -732,3 +751,5 @@ EXPORT_SYMBOL_GPL(sysfs_schedule_callback);
EXPORT_SYMBOL_GPL(sysfs_create_file);
EXPORT_SYMBOL_GPL(sysfs_remove_file);
+EXPORT_SYMBOL_GPL(sysfs_remove_files);
+EXPORT_SYMBOL_GPL(sysfs_create_files);
diff --git a/fs/sysfs/inode.c b/fs/sysfs/inode.c
index 6a06a1d1ea7..082daaecac1 100644
--- a/fs/sysfs/inode.c
+++ b/fs/sysfs/inode.c
@@ -111,20 +111,20 @@ int sysfs_setattr(struct dentry *dentry, struct iattr *iattr)
if (!sd)
return -EINVAL;
+ mutex_lock(&sysfs_mutex);
error = inode_change_ok(inode, iattr);
if (error)
- return error;
+ goto out;
iattr->ia_valid &= ~ATTR_SIZE; /* ignore size changes */
error = inode_setattr(inode, iattr);
if (error)
- return error;
+ goto out;
- mutex_lock(&sysfs_mutex);
error = sysfs_sd_setattr(sd, iattr);
+out:
mutex_unlock(&sysfs_mutex);
-
return error;
}
@@ -283,6 +283,7 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
/**
* sysfs_get_inode - get inode for sysfs_dirent
+ * @sb: super block
* @sd: sysfs_dirent to allocate inode for
*
* Get inode for @sd. If such inode doesn't exist, a new inode
@@ -295,11 +296,11 @@ static void sysfs_init_inode(struct sysfs_dirent *sd, struct inode *inode)
* RETURNS:
* Pointer to allocated inode on success, NULL on failure.
*/
-struct inode * sysfs_get_inode(struct sysfs_dirent *sd)
+struct inode * sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd)
{
struct inode *inode;
- inode = iget_locked(sysfs_sb, sd->s_ino);
+ inode = iget_locked(sb, sd->s_ino);
if (inode && (inode->i_state & I_NEW))
sysfs_init_inode(sd, inode);
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c
index 49749955cca..0cb10884a2f 100644
--- a/fs/sysfs/mount.c
+++ b/fs/sysfs/mount.c
@@ -23,7 +23,6 @@
static struct vfsmount *sysfs_mount;
-struct super_block * sysfs_sb = NULL;
struct kmem_cache *sysfs_dir_cachep;
static const struct super_operations sysfs_ops = {
@@ -50,11 +49,10 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_magic = SYSFS_MAGIC;
sb->s_op = &sysfs_ops;
sb->s_time_gran = 1;
- sysfs_sb = sb;
/* get root inode, initialize and unlock it */
mutex_lock(&sysfs_mutex);
- inode = sysfs_get_inode(&sysfs_root);
+ inode = sysfs_get_inode(sb, &sysfs_root);
mutex_unlock(&sysfs_mutex);
if (!inode) {
pr_debug("sysfs: could not get root inode\n");
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index c5eff49fa41..1b9a3a1e8a1 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -123,6 +123,44 @@ void sysfs_remove_link(struct kobject * kobj, const char * name)
sysfs_hash_and_remove(parent_sd, name);
}
+/**
+ * sysfs_rename_link - rename symlink in object's directory.
+ * @kobj: object we're acting for.
+ * @targ: object we're pointing to.
+ * @old: previous name of the symlink.
+ * @new: new name of the symlink.
+ *
+ * A helper function for the common rename symlink idiom.
+ */
+int sysfs_rename_link(struct kobject *kobj, struct kobject *targ,
+ const char *old, const char *new)
+{
+ struct sysfs_dirent *parent_sd, *sd = NULL;
+ int result;
+
+ if (!kobj)
+ parent_sd = &sysfs_root;
+ else
+ parent_sd = kobj->sd;
+
+ result = -ENOENT;
+ sd = sysfs_get_dirent(parent_sd, old);
+ if (!sd)
+ goto out;
+
+ result = -EINVAL;
+ if (sysfs_type(sd) != SYSFS_KOBJ_LINK)
+ goto out;
+ if (sd->s_symlink.target_sd->s_dir.kobj != targ)
+ goto out;
+
+ result = sysfs_rename(sd, parent_sd, new);
+
+out:
+ sysfs_put(sd);
+ return result;
+}
+
static int sysfs_get_target_path(struct sysfs_dirent *parent_sd,
struct sysfs_dirent *target_sd, char *path)
{
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index cdd9377a6e0..30f5a44fb5d 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -66,8 +66,8 @@ struct sysfs_dirent {
};
unsigned int s_flags;
+ unsigned short s_mode;
ino_t s_ino;
- umode_t s_mode;
struct sysfs_inode_attrs *s_iattr;
};
@@ -79,6 +79,7 @@ struct sysfs_dirent {
#define SYSFS_KOBJ_BIN_ATTR 0x0004
#define SYSFS_KOBJ_LINK 0x0008
#define SYSFS_COPY_NAME (SYSFS_DIR | SYSFS_KOBJ_LINK)
+#define SYSFS_ACTIVE_REF (SYSFS_KOBJ_ATTR | SYSFS_KOBJ_BIN_ATTR)
#define SYSFS_FLAG_MASK ~SYSFS_TYPE_MASK
#define SYSFS_FLAG_REMOVED 0x0200
@@ -91,9 +92,12 @@ static inline unsigned int sysfs_type(struct sysfs_dirent *sd)
#ifdef CONFIG_DEBUG_LOCK_ALLOC
#define sysfs_dirent_init_lockdep(sd) \
do { \
- static struct lock_class_key __key; \
+ struct attribute *attr = sd->s_attr.attr; \
+ struct lock_class_key *key = attr->key; \
+ if (!key) \
+ key = &attr->skey; \
\
- lockdep_init_map(&sd->dep_map, "s_active", &__key, 0); \
+ lockdep_init_map(&sd->dep_map, "s_active", key, 0); \
} while(0)
#else
#define sysfs_dirent_init_lockdep(sd) do {} while(0)
@@ -111,7 +115,6 @@ struct sysfs_addrm_cxt {
* mount.c
*/
extern struct sysfs_dirent sysfs_root;
-extern struct super_block *sysfs_sb;
extern struct kmem_cache *sysfs_dir_cachep;
/*
@@ -124,8 +127,8 @@ extern const struct file_operations sysfs_dir_operations;
extern const struct inode_operations sysfs_dir_inode_operations;
struct dentry *sysfs_get_dentry(struct sysfs_dirent *sd);
-struct sysfs_dirent *sysfs_get_active_two(struct sysfs_dirent *sd);
-void sysfs_put_active_two(struct sysfs_dirent *sd);
+struct sysfs_dirent *sysfs_get_active(struct sysfs_dirent *sd);
+void sysfs_put_active(struct sysfs_dirent *sd);
void sysfs_addrm_start(struct sysfs_addrm_cxt *acxt,
struct sysfs_dirent *parent_sd);
int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd);
@@ -168,7 +171,7 @@ static inline void __sysfs_put(struct sysfs_dirent *sd)
/*
* inode.c
*/
-struct inode *sysfs_get_inode(struct sysfs_dirent *sd);
+struct inode *sysfs_get_inode(struct super_block *sb, struct sysfs_dirent *sd);
void sysfs_delete_inode(struct inode *inode);
int sysfs_sd_setattr(struct sysfs_dirent *sd, struct iattr *iattr);
int sysfs_permission(struct inode *inode, int mask);
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index 5c5a366aa33..b4769e40e8b 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -105,7 +105,6 @@ xfs-y += $(addprefix $(XFS_LINUX)/, \
xfs_globals.o \
xfs_ioctl.o \
xfs_iops.o \
- xfs_lrw.o \
xfs_super.o \
xfs_sync.o \
xfs_xattr.o)
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 66abe36c121..9083357f9e4 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -39,6 +39,7 @@
#include "xfs_iomap.h"
#include "xfs_vnodeops.h"
#include "xfs_trace.h"
+#include "xfs_bmap.h"
#include <linux/mpage.h>
#include <linux/pagevec.h>
#include <linux/writeback.h>
@@ -163,14 +164,17 @@ xfs_ioend_new_eof(
}
/*
- * Update on-disk file size now that data has been written to disk.
- * The current in-memory file size is i_size. If a write is beyond
- * eof i_new_size will be the intended file size until i_size is
- * updated. If this write does not extend all the way to the valid
- * file size then restrict this update to the end of the write.
+ * Update on-disk file size now that data has been written to disk. The
+ * current in-memory file size is i_size. If a write is beyond eof i_new_size
+ * will be the intended file size until i_size is updated. If this write does
+ * not extend all the way to the valid file size then restrict this update to
+ * the end of the write.
+ *
+ * This function does not block as blocking on the inode lock in IO completion
+ * can lead to IO completion order dependency deadlocks.. If it can't get the
+ * inode ilock it will return EAGAIN. Callers must handle this.
*/
-
-STATIC void
+STATIC int
xfs_setfilesize(
xfs_ioend_t *ioend)
{
@@ -181,16 +185,40 @@ xfs_setfilesize(
ASSERT(ioend->io_type != IOMAP_READ);
if (unlikely(ioend->io_error))
- return;
+ return 0;
+
+ if (!xfs_ilock_nowait(ip, XFS_ILOCK_EXCL))
+ return EAGAIN;
- xfs_ilock(ip, XFS_ILOCK_EXCL);
isize = xfs_ioend_new_eof(ioend);
if (isize) {
ip->i_d.di_size = isize;
- xfs_mark_inode_dirty_sync(ip);
+ xfs_mark_inode_dirty(ip);
}
xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ return 0;
+}
+
+/*
+ * 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;
+
+ wq = (ioend->io_type == IOMAP_UNWRITTEN) ?
+ xfsconvertd_workqueue : xfsdatad_workqueue;
+ queue_work(wq, &ioend->io_work);
+ if (wait)
+ flush_workqueue(wq);
+ }
}
/*
@@ -198,11 +226,11 @@ xfs_setfilesize(
*/
STATIC void
xfs_end_io(
- struct work_struct *work)
+ struct work_struct *work)
{
- xfs_ioend_t *ioend =
- container_of(work, xfs_ioend_t, io_work);
- struct xfs_inode *ip = XFS_I(ioend->io_inode);
+ xfs_ioend_t *ioend = container_of(work, xfs_ioend_t, io_work);
+ struct xfs_inode *ip = XFS_I(ioend->io_inode);
+ int error = 0;
/*
* For unwritten extents we need to issue transactions to convert a
@@ -210,7 +238,6 @@ xfs_end_io(
*/
if (ioend->io_type == IOMAP_UNWRITTEN &&
likely(!ioend->io_error && !XFS_FORCED_SHUTDOWN(ip->i_mount))) {
- int error;
error = xfs_iomap_write_unwritten(ip, ioend->io_offset,
ioend->io_size);
@@ -222,30 +249,23 @@ xfs_end_io(
* We might have to update the on-disk file size after extending
* writes.
*/
- if (ioend->io_type != IOMAP_READ)
- xfs_setfilesize(ioend);
- xfs_destroy_ioend(ioend);
-}
-
-/*
- * 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;
-
- wq = (ioend->io_type == IOMAP_UNWRITTEN) ?
- xfsconvertd_workqueue : xfsdatad_workqueue;
- queue_work(wq, &ioend->io_work);
- if (wait)
- flush_workqueue(wq);
+ if (ioend->io_type != IOMAP_READ) {
+ error = xfs_setfilesize(ioend);
+ ASSERT(!error || error == EAGAIN);
}
+
+ /*
+ * If we didn't complete processing of the ioend, requeue it to the
+ * tail of the workqueue for another attempt later. Otherwise destroy
+ * it.
+ */
+ if (error == EAGAIN) {
+ atomic_inc(&ioend->io_remaining);
+ xfs_finish_ioend(ioend, 0);
+ /* ensure we don't spin on blocked ioends */
+ delay(1);
+ } else
+ xfs_destroy_ioend(ioend);
}
/*
@@ -341,7 +361,7 @@ xfs_submit_ioend_bio(
* but don't update the inode size until I/O completion.
*/
if (xfs_ioend_new_eof(ioend))
- xfs_mark_inode_dirty_sync(XFS_I(ioend->io_inode));
+ xfs_mark_inode_dirty(XFS_I(ioend->io_inode));
submit_bio(wbc->sync_mode == WB_SYNC_ALL ?
WRITE_SYNC_PLUG : WRITE, bio);
@@ -874,6 +894,118 @@ xfs_cluster_write(
}
}
+STATIC void
+xfs_vm_invalidatepage(
+ struct page *page,
+ unsigned long offset)
+{
+ trace_xfs_invalidatepage(page->mapping->host, page, offset);
+ block_invalidatepage(page, offset);
+}
+
+/*
+ * If the page has delalloc buffers on it, we need to punch them out before we
+ * invalidate the page. If we don't, we leave a stale delalloc mapping on the
+ * inode that can trip a BUG() in xfs_get_blocks() later on if a direct IO read
+ * is done on that same region - the delalloc extent is returned when none is
+ * supposed to be there.
+ *
+ * We prevent this by truncating away the delalloc regions on the page before
+ * invalidating it. Because they are delalloc, we can do this without needing a
+ * transaction. Indeed - if we get ENOSPC errors, we have to be able to do this
+ * truncation without a transaction as there is no space left for block
+ * reservation (typically why we see a ENOSPC in writeback).
+ *
+ * This is not a performance critical path, so for now just do the punching a
+ * buffer head at a time.
+ */
+STATIC void
+xfs_aops_discard_page(
+ struct page *page)
+{
+ struct inode *inode = page->mapping->host;
+ struct xfs_inode *ip = XFS_I(inode);
+ struct buffer_head *bh, *head;
+ loff_t offset = page_offset(page);
+ ssize_t len = 1 << inode->i_blkbits;
+
+ if (!xfs_is_delayed_page(page, IOMAP_DELAY))
+ goto out_invalidate;
+
+ xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
+ "page discard on page %p, inode 0x%llx, offset %llu.",
+ page, ip->i_ino, offset);
+
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ bh = head = page_buffers(page);
+ do {
+ int done;
+ xfs_fileoff_t offset_fsb;
+ xfs_bmbt_irec_t imap;
+ int nimaps = 1;
+ int error;
+ xfs_fsblock_t firstblock;
+ xfs_bmap_free_t flist;
+
+ if (!buffer_delay(bh))
+ goto next_buffer;
+
+ offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset);
+
+ /*
+ * Map the range first and check that it is a delalloc extent
+ * before trying to unmap the range. Otherwise we will be
+ * trying to remove a real extent (which requires a
+ * transaction) or a hole, which is probably a bad idea...
+ */
+ error = xfs_bmapi(NULL, ip, offset_fsb, 1,
+ XFS_BMAPI_ENTIRE, NULL, 0, &imap,
+ &nimaps, NULL, NULL);
+
+ if (error) {
+ /* something screwed, just bail */
+ xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
+ "page discard failed delalloc mapping lookup.");
+ break;
+ }
+ if (!nimaps) {
+ /* nothing there */
+ goto next_buffer;
+ }
+ if (imap.br_startblock != DELAYSTARTBLOCK) {
+ /* been converted, ignore */
+ goto next_buffer;
+ }
+ WARN_ON(imap.br_blockcount == 0);
+
+ /*
+ * Note: while we initialise the firstblock/flist pair, they
+ * should never be used because blocks should never be
+ * allocated or freed for a delalloc extent and hence we need
+ * don't cancel or finish them after the xfs_bunmapi() call.
+ */
+ xfs_bmap_init(&flist, &firstblock);
+ error = xfs_bunmapi(NULL, ip, offset_fsb, 1, 0, 1, &firstblock,
+ &flist, NULL, &done);
+
+ ASSERT(!flist.xbf_count && !flist.xbf_first);
+ if (error) {
+ /* something screwed, just bail */
+ xfs_fs_cmn_err(CE_ALERT, ip->i_mount,
+ "page discard unable to remove delalloc mapping.");
+ break;
+ }
+next_buffer:
+ offset += len;
+
+ } while ((bh = bh->b_this_page) != head);
+
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+out_invalidate:
+ xfs_vm_invalidatepage(page, 0);
+ return;
+}
+
/*
* Calling this without startio set means we are being asked to make a dirty
* page ready for freeing it's buffers. When called with startio set then
@@ -1125,7 +1257,7 @@ error:
*/
if (err != -EAGAIN) {
if (!unmapped)
- block_invalidatepage(page, 0);
+ xfs_aops_discard_page(page);
ClearPageUptodate(page);
}
return err;
@@ -1535,15 +1667,6 @@ xfs_vm_readpages(
return mpage_readpages(mapping, pages, nr_pages, xfs_get_blocks);
}
-STATIC void
-xfs_vm_invalidatepage(
- struct page *page,
- unsigned long offset)
-{
- trace_xfs_invalidatepage(page->mapping->host, page, offset);
- block_invalidatepage(page, offset);
-}
-
const struct address_space_operations xfs_address_space_operations = {
.readpage = xfs_vm_readpage,
.readpages = xfs_vm_readpages,
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c
index 87b8cbd23d4..846b75aeb2a 100644
--- a/fs/xfs/linux-2.6/xfs_export.c
+++ b/fs/xfs/linux-2.6/xfs_export.c
@@ -29,6 +29,7 @@
#include "xfs_vnodeops.h"
#include "xfs_bmap_btree.h"
#include "xfs_inode.h"
+#include "xfs_inode_item.h"
/*
* Note that we only accept fileids which are long enough rather than allow
@@ -215,9 +216,28 @@ xfs_fs_get_parent(
return d_obtain_alias(VFS_I(cip));
}
+STATIC int
+xfs_fs_nfs_commit_metadata(
+ struct inode *inode)
+{
+ struct xfs_inode *ip = XFS_I(inode);
+ struct xfs_mount *mp = ip->i_mount;
+ int error = 0;
+
+ xfs_ilock(ip, XFS_ILOCK_SHARED);
+ if (xfs_ipincount(ip)) {
+ error = _xfs_log_force_lsn(mp, ip->i_itemp->ili_last_lsn,
+ XFS_LOG_SYNC, NULL);
+ }
+ xfs_iunlock(ip, XFS_ILOCK_SHARED);
+
+ return error;
+}
+
const struct export_operations xfs_export_operations = {
.encode_fh = xfs_fs_encode_fh,
.fh_to_dentry = xfs_fs_fh_to_dentry,
.fh_to_parent = xfs_fs_fh_to_parent,
.get_parent = xfs_fs_get_parent,
+ .commit_metadata = xfs_fs_nfs_commit_metadata,
};
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index e4caeb28ce2..42dd3bcfba6 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -16,6 +16,7 @@
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
+#include "xfs_fs.h"
#include "xfs_bit.h"
#include "xfs_log.h"
#include "xfs_inum.h"
@@ -34,52 +35,279 @@
#include "xfs_dir2_sf.h"
#include "xfs_dinode.h"
#include "xfs_inode.h"
+#include "xfs_inode_item.h"
+#include "xfs_bmap.h"
#include "xfs_error.h"
#include "xfs_rw.h"
#include "xfs_vnodeops.h"
#include "xfs_da_btree.h"
#include "xfs_ioctl.h"
+#include "xfs_trace.h"
#include <linux/dcache.h>
static const struct vm_operations_struct xfs_file_vm_ops;
-STATIC ssize_t
-xfs_file_aio_read(
- struct kiocb *iocb,
- const struct iovec *iov,
- unsigned long nr_segs,
- loff_t pos)
+/*
+ * xfs_iozero
+ *
+ * xfs_iozero clears the specified range of buffer supplied,
+ * and marks all the affected blocks as valid and modified. If
+ * an affected block is not allocated, it will be allocated. If
+ * an affected block is not completely overwritten, and is not
+ * valid before the operation, it will be read from disk before
+ * being partially zeroed.
+ */
+STATIC int
+xfs_iozero(
+ struct xfs_inode *ip, /* inode */
+ loff_t pos, /* offset in file */
+ size_t count) /* size of data to zero */
{
- struct file *file = iocb->ki_filp;
- int ioflags = 0;
+ struct page *page;
+ struct address_space *mapping;
+ int status;
- BUG_ON(iocb->ki_pos != pos);
- if (unlikely(file->f_flags & O_DIRECT))
- ioflags |= IO_ISDIRECT;
- if (file->f_mode & FMODE_NOCMTIME)
- ioflags |= IO_INVIS;
- return xfs_read(XFS_I(file->f_path.dentry->d_inode), iocb, iov,
- nr_segs, &iocb->ki_pos, ioflags);
+ mapping = VFS_I(ip)->i_mapping;
+ do {
+ unsigned offset, bytes;
+ void *fsdata;
+
+ offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
+ bytes = PAGE_CACHE_SIZE - offset;
+ if (bytes > count)
+ bytes = count;
+
+ status = pagecache_write_begin(NULL, mapping, pos, bytes,
+ AOP_FLAG_UNINTERRUPTIBLE,
+ &page, &fsdata);
+ if (status)
+ break;
+
+ zero_user(page, offset, bytes);
+
+ status = pagecache_write_end(NULL, mapping, pos, bytes, bytes,
+ page, fsdata);
+ WARN_ON(status <= 0); /* can't return less than zero! */
+ pos += bytes;
+ count -= bytes;
+ status = 0;
+ } while (count);
+
+ return (-status);
+}
+
+STATIC int
+xfs_file_fsync(
+ struct file *file,
+ struct dentry *dentry,
+ int datasync)
+{
+ struct xfs_inode *ip = XFS_I(dentry->d_inode);
+ struct xfs_trans *tp;
+ int error = 0;
+ int log_flushed = 0;
+
+ xfs_itrace_entry(ip);
+
+ if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+ return -XFS_ERROR(EIO);
+
+ xfs_iflags_clear(ip, XFS_ITRUNCATED);
+
+ /*
+ * We always need to make sure that the required inode state is safe on
+ * disk. The inode might be clean but we still might need to force the
+ * log because of committed transactions that haven't hit the disk yet.
+ * Likewise, there could be unflushed non-transactional changes to the
+ * inode core that have to go to disk and this requires us to issue
+ * a synchronous transaction to capture these changes correctly.
+ *
+ * This code relies on the assumption that if the i_update_core field
+ * of the inode is clear and the inode is unpinned then it is clean
+ * and no action is required.
+ */
+ xfs_ilock(ip, XFS_ILOCK_SHARED);
+
+ /*
+ * First check if the VFS inode is marked dirty. All the dirtying
+ * of non-transactional updates no goes through mark_inode_dirty*,
+ * which allows us to distinguish beteeen pure timestamp updates
+ * and i_size updates which need to be caught for fdatasync.
+ * After that also theck for the dirty state in the XFS inode, which
+ * might gets cleared when the inode gets written out via the AIL
+ * or xfs_iflush_cluster.
+ */
+ if (((dentry->d_inode->i_state & I_DIRTY_DATASYNC) ||
+ ((dentry->d_inode->i_state & I_DIRTY_SYNC) && !datasync)) &&
+ ip->i_update_core) {
+ /*
+ * Kick off a transaction to log the inode core to get the
+ * updates. The sync transaction will also force the log.
+ */
+ xfs_iunlock(ip, XFS_ILOCK_SHARED);
+ tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_FSYNC_TS);
+ error = xfs_trans_reserve(tp, 0,
+ XFS_FSYNC_TS_LOG_RES(ip->i_mount), 0, 0, 0);
+ if (error) {
+ xfs_trans_cancel(tp, 0);
+ return -error;
+ }
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+
+ /*
+ * Note - it's possible that we might have pushed ourselves out
+ * of the way during trans_reserve which would flush the inode.
+ * But there's no guarantee that the inode buffer has actually
+ * gone out yet (it's delwri). Plus the buffer could be pinned
+ * anyway if it's part of an inode in another recent
+ * transaction. So we play it safe and fire off the
+ * transaction anyway.
+ */
+ xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
+ xfs_trans_ihold(tp, ip);
+ xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+ xfs_trans_set_sync(tp);
+ error = _xfs_trans_commit(tp, 0, &log_flushed);
+
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ } else {
+ /*
+ * Timestamps/size haven't changed since last inode flush or
+ * inode transaction commit. That means either nothing got
+ * written or a transaction committed which caught the updates.
+ * If the latter happened and the transaction hasn't hit the
+ * disk yet, the inode will be still be pinned. If it is,
+ * force the log.
+ */
+ if (xfs_ipincount(ip)) {
+ error = _xfs_log_force_lsn(ip->i_mount,
+ ip->i_itemp->ili_last_lsn,
+ XFS_LOG_SYNC, &log_flushed);
+ }
+ xfs_iunlock(ip, XFS_ILOCK_SHARED);
+ }
+
+ if (ip->i_mount->m_flags & XFS_MOUNT_BARRIER) {
+ /*
+ * If the log write didn't issue an ordered tag we need
+ * to flush the disk cache for the data device now.
+ */
+ if (!log_flushed)
+ xfs_blkdev_issue_flush(ip->i_mount->m_ddev_targp);
+
+ /*
+ * If this inode is on the RT dev we need to flush that
+ * cache as well.
+ */
+ if (XFS_IS_REALTIME_INODE(ip))
+ xfs_blkdev_issue_flush(ip->i_mount->m_rtdev_targp);
+ }
+
+ return -error;
}
STATIC ssize_t
-xfs_file_aio_write(
+xfs_file_aio_read(
struct kiocb *iocb,
- const struct iovec *iov,
+ const struct iovec *iovp,
unsigned long nr_segs,
loff_t pos)
{
struct file *file = iocb->ki_filp;
+ struct inode *inode = file->f_mapping->host;
+ struct xfs_inode *ip = XFS_I(inode);
+ struct xfs_mount *mp = ip->i_mount;
+ size_t size = 0;
+ ssize_t ret = 0;
int ioflags = 0;
+ xfs_fsize_t n;
+ unsigned long seg;
+
+ XFS_STATS_INC(xs_read_calls);
BUG_ON(iocb->ki_pos != pos);
+
if (unlikely(file->f_flags & O_DIRECT))
ioflags |= IO_ISDIRECT;
if (file->f_mode & FMODE_NOCMTIME)
ioflags |= IO_INVIS;
- return xfs_write(XFS_I(file->f_mapping->host), iocb, iov, nr_segs,
- &iocb->ki_pos, ioflags);
+
+ /* START copy & waste from filemap.c */
+ for (seg = 0; seg < nr_segs; seg++) {
+ const struct iovec *iv = &iovp[seg];
+
+ /*
+ * If any segment has a negative length, or the cumulative
+ * length ever wraps negative then return -EINVAL.
+ */
+ size += iv->iov_len;
+ if (unlikely((ssize_t)(size|iv->iov_len) < 0))
+ return XFS_ERROR(-EINVAL);
+ }
+ /* END copy & waste from filemap.c */
+
+ if (unlikely(ioflags & IO_ISDIRECT)) {
+ xfs_buftarg_t *target =
+ XFS_IS_REALTIME_INODE(ip) ?
+ mp->m_rtdev_targp : mp->m_ddev_targp;
+ if ((iocb->ki_pos & target->bt_smask) ||
+ (size & target->bt_smask)) {
+ if (iocb->ki_pos == ip->i_size)
+ return 0;
+ return -XFS_ERROR(EINVAL);
+ }
+ }
+
+ n = XFS_MAXIOFFSET(mp) - iocb->ki_pos;
+ if (n <= 0 || size == 0)
+ return 0;
+
+ if (n < size)
+ size = n;
+
+ if (XFS_FORCED_SHUTDOWN(mp))
+ return -EIO;
+
+ if (unlikely(ioflags & IO_ISDIRECT))
+ mutex_lock(&inode->i_mutex);
+ xfs_ilock(ip, XFS_IOLOCK_SHARED);
+
+ if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
+ int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
+ int iolock = XFS_IOLOCK_SHARED;
+
+ ret = -XFS_SEND_DATA(mp, DM_EVENT_READ, ip, iocb->ki_pos, size,
+ dmflags, &iolock);
+ if (ret) {
+ xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+ if (unlikely(ioflags & IO_ISDIRECT))
+ mutex_unlock(&inode->i_mutex);
+ return ret;
+ }
+ }
+
+ if (unlikely(ioflags & IO_ISDIRECT)) {
+ if (inode->i_mapping->nrpages) {
+ ret = -xfs_flushinval_pages(ip,
+ (iocb->ki_pos & PAGE_CACHE_MASK),
+ -1, FI_REMAPF_LOCKED);
+ }
+ mutex_unlock(&inode->i_mutex);
+ if (ret) {
+ xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+ return ret;
+ }
+ }
+
+ trace_xfs_file_read(ip, size, iocb->ki_pos, ioflags);
+
+ ret = generic_file_aio_read(iocb, iovp, nr_segs, iocb->ki_pos);
+ if (ret > 0)
+ XFS_STATS_ADD(xs_read_bytes, ret);
+
+ xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+ return ret;
}
STATIC ssize_t
@@ -87,16 +315,44 @@ xfs_file_splice_read(
struct file *infilp,
loff_t *ppos,
struct pipe_inode_info *pipe,
- size_t len,
+ size_t count,
unsigned int flags)
{
+ struct xfs_inode *ip = XFS_I(infilp->f_mapping->host);
+ struct xfs_mount *mp = ip->i_mount;
int ioflags = 0;
+ ssize_t ret;
+
+ XFS_STATS_INC(xs_read_calls);
if (infilp->f_mode & FMODE_NOCMTIME)
ioflags |= IO_INVIS;
- return xfs_splice_read(XFS_I(infilp->f_path.dentry->d_inode),
- infilp, ppos, pipe, len, flags, ioflags);
+ if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+ return -EIO;
+
+ xfs_ilock(ip, XFS_IOLOCK_SHARED);
+
+ if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
+ int iolock = XFS_IOLOCK_SHARED;
+ int error;
+
+ error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip, *ppos, count,
+ FILP_DELAY_FLAG(infilp), &iolock);
+ if (error) {
+ xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+ return -error;
+ }
+ }
+
+ trace_xfs_file_splice_read(ip, count, *ppos, ioflags);
+
+ ret = generic_file_splice_read(infilp, ppos, pipe, count, flags);
+ if (ret > 0)
+ XFS_STATS_ADD(xs_read_bytes, ret);
+
+ xfs_iunlock(ip, XFS_IOLOCK_SHARED);
+ return ret;
}
STATIC ssize_t
@@ -104,16 +360,538 @@ xfs_file_splice_write(
struct pipe_inode_info *pipe,
struct file *outfilp,
loff_t *ppos,
- size_t len,
+ size_t count,
unsigned int flags)
{
+ struct inode *inode = outfilp->f_mapping->host;
+ struct xfs_inode *ip = XFS_I(inode);
+ struct xfs_mount *mp = ip->i_mount;
+ xfs_fsize_t isize, new_size;
int ioflags = 0;
+ ssize_t ret;
+
+ XFS_STATS_INC(xs_write_calls);
if (outfilp->f_mode & FMODE_NOCMTIME)
ioflags |= IO_INVIS;
- return xfs_splice_write(XFS_I(outfilp->f_path.dentry->d_inode),
- pipe, outfilp, ppos, len, flags, ioflags);
+ if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+ return -EIO;
+
+ xfs_ilock(ip, XFS_IOLOCK_EXCL);
+
+ if (DM_EVENT_ENABLED(ip, DM_EVENT_WRITE) && !(ioflags & IO_INVIS)) {
+ int iolock = XFS_IOLOCK_EXCL;
+ int error;
+
+ error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, ip, *ppos, count,
+ FILP_DELAY_FLAG(outfilp), &iolock);
+ if (error) {
+ xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+ return -error;
+ }
+ }
+
+ new_size = *ppos + count;
+
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ if (new_size > ip->i_size)
+ ip->i_new_size = new_size;
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+
+ trace_xfs_file_splice_write(ip, count, *ppos, ioflags);
+
+ ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags);
+ if (ret > 0)
+ XFS_STATS_ADD(xs_write_bytes, ret);
+
+ isize = i_size_read(inode);
+ if (unlikely(ret < 0 && ret != -EFAULT && *ppos > isize))
+ *ppos = isize;
+
+ if (*ppos > ip->i_size) {
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ if (*ppos > ip->i_size)
+ ip->i_size = *ppos;
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ }
+
+ if (ip->i_new_size) {
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ ip->i_new_size = 0;
+ if (ip->i_d.di_size > ip->i_size)
+ ip->i_d.di_size = ip->i_size;
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ }
+ xfs_iunlock(ip, XFS_IOLOCK_EXCL);
+ return ret;
+}
+
+/*
+ * This routine is called to handle zeroing any space in the last
+ * block of the file that is beyond the EOF. We do this since the
+ * size is being increased without writing anything to that block
+ * and we don't want anyone to read the garbage on the disk.
+ */
+STATIC int /* error (positive) */
+xfs_zero_last_block(
+ xfs_inode_t *ip,
+ xfs_fsize_t offset,
+ xfs_fsize_t isize)
+{
+ xfs_fileoff_t last_fsb;
+ xfs_mount_t *mp = ip->i_mount;
+ int nimaps;
+ int zero_offset;
+ int zero_len;
+ int error = 0;
+ xfs_bmbt_irec_t imap;
+
+ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+
+ zero_offset = XFS_B_FSB_OFFSET(mp, isize);
+ if (zero_offset == 0) {
+ /*
+ * There are no extra bytes in the last block on disk to
+ * zero, so return.
+ */
+ return 0;
+ }
+
+ last_fsb = XFS_B_TO_FSBT(mp, isize);
+ nimaps = 1;
+ error = xfs_bmapi(NULL, ip, last_fsb, 1, 0, NULL, 0, &imap,
+ &nimaps, NULL, NULL);
+ if (error) {
+ return error;
+ }
+ ASSERT(nimaps > 0);
+ /*
+ * If the block underlying isize is just a hole, then there
+ * is nothing to zero.
+ */
+ if (imap.br_startblock == HOLESTARTBLOCK) {
+ return 0;
+ }
+ /*
+ * Zero the part of the last block beyond the EOF, and write it
+ * out sync. We need to drop the ilock while we do this so we
+ * don't deadlock when the buffer cache calls back to us.
+ */
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+
+ zero_len = mp->m_sb.sb_blocksize - zero_offset;
+ if (isize + zero_len > offset)
+ zero_len = offset - isize;
+ error = xfs_iozero(ip, isize, zero_len);
+
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ ASSERT(error >= 0);
+ return error;
+}
+
+/*
+ * Zero any on disk space between the current EOF and the new,
+ * larger EOF. This handles the normal case of zeroing the remainder
+ * of the last block in the file and the unusual case of zeroing blocks
+ * out beyond the size of the file. This second case only happens
+ * with fixed size extents and when the system crashes before the inode
+ * size was updated but after blocks were allocated. If fill is set,
+ * then any holes in the range are filled and zeroed. If not, the holes
+ * are left alone as holes.
+ */
+
+int /* error (positive) */
+xfs_zero_eof(
+ xfs_inode_t *ip,
+ xfs_off_t offset, /* starting I/O offset */
+ xfs_fsize_t isize) /* current inode size */
+{
+ xfs_mount_t *mp = ip->i_mount;
+ xfs_fileoff_t start_zero_fsb;
+ xfs_fileoff_t end_zero_fsb;
+ xfs_fileoff_t zero_count_fsb;
+ xfs_fileoff_t last_fsb;
+ xfs_fileoff_t zero_off;
+ xfs_fsize_t zero_len;
+ int nimaps;
+ int error = 0;
+ xfs_bmbt_irec_t imap;
+
+ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
+ ASSERT(offset > isize);
+
+ /*
+ * First handle zeroing the block on which isize resides.
+ * We only zero a part of that block so it is handled specially.
+ */
+ error = xfs_zero_last_block(ip, offset, isize);
+ if (error) {
+ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
+ return error;
+ }
+
+ /*
+ * Calculate the range between the new size and the old
+ * where blocks needing to be zeroed may exist. To get the
+ * block where the last byte in the file currently resides,
+ * we need to subtract one from the size and truncate back
+ * to a block boundary. We subtract 1 in case the size is
+ * exactly on a block boundary.
+ */
+ last_fsb = isize ? XFS_B_TO_FSBT(mp, isize - 1) : (xfs_fileoff_t)-1;
+ start_zero_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)isize);
+ end_zero_fsb = XFS_B_TO_FSBT(mp, offset - 1);
+ ASSERT((xfs_sfiloff_t)last_fsb < (xfs_sfiloff_t)start_zero_fsb);
+ if (last_fsb == end_zero_fsb) {
+ /*
+ * The size was only incremented on its last block.
+ * We took care of that above, so just return.
+ */
+ return 0;
+ }
+
+ ASSERT(start_zero_fsb <= end_zero_fsb);
+ while (start_zero_fsb <= end_zero_fsb) {
+ nimaps = 1;
+ zero_count_fsb = end_zero_fsb - start_zero_fsb + 1;
+ error = xfs_bmapi(NULL, ip, start_zero_fsb, zero_count_fsb,
+ 0, NULL, 0, &imap, &nimaps, NULL, NULL);
+ if (error) {
+ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
+ return error;
+ }
+ ASSERT(nimaps > 0);
+
+ if (imap.br_state == XFS_EXT_UNWRITTEN ||
+ imap.br_startblock == HOLESTARTBLOCK) {
+ /*
+ * This loop handles initializing pages that were
+ * partially initialized by the code below this
+ * loop. It basically zeroes the part of the page
+ * that sits on a hole and sets the page as P_HOLE
+ * and calls remapf if it is a mapped file.
+ */
+ start_zero_fsb = imap.br_startoff + imap.br_blockcount;
+ ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
+ continue;
+ }
+
+ /*
+ * There are blocks we need to zero.
+ * Drop the inode lock while we're doing the I/O.
+ * We'll still have the iolock to protect us.
+ */
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+
+ zero_off = XFS_FSB_TO_B(mp, start_zero_fsb);
+ zero_len = XFS_FSB_TO_B(mp, imap.br_blockcount);
+
+ if ((zero_off + zero_len) > offset)
+ zero_len = offset - zero_off;
+
+ error = xfs_iozero(ip, zero_off, zero_len);
+ if (error) {
+ goto out_lock;
+ }
+
+ start_zero_fsb = imap.br_startoff + imap.br_blockcount;
+ ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
+
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ }
+
+ return 0;
+
+out_lock:
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ ASSERT(error >= 0);
+ return error;
+}
+
+STATIC ssize_t
+xfs_file_aio_write(
+ struct kiocb *iocb,
+ const struct iovec *iovp,
+ unsigned long nr_segs,
+ loff_t pos)
+{
+ struct file *file = iocb->ki_filp;
+ struct address_space *mapping = file->f_mapping;
+ struct inode *inode = mapping->host;
+ struct xfs_inode *ip = XFS_I(inode);
+ struct xfs_mount *mp = ip->i_mount;
+ ssize_t ret = 0, error = 0;
+ int ioflags = 0;
+ xfs_fsize_t isize, new_size;
+ int iolock;
+ int eventsent = 0;
+ size_t ocount = 0, count;
+ int need_i_mutex;
+
+ XFS_STATS_INC(xs_write_calls);
+
+ BUG_ON(iocb->ki_pos != pos);
+
+ if (unlikely(file->f_flags & O_DIRECT))
+ ioflags |= IO_ISDIRECT;
+ if (file->f_mode & FMODE_NOCMTIME)
+ ioflags |= IO_INVIS;
+
+ error = generic_segment_checks(iovp, &nr_segs, &ocount, VERIFY_READ);
+ if (error)
+ return error;
+
+ count = ocount;
+ if (count == 0)
+ return 0;
+
+ xfs_wait_for_freeze(mp, SB_FREEZE_WRITE);
+
+ if (XFS_FORCED_SHUTDOWN(mp))
+ return -EIO;
+
+relock:
+ if (ioflags & IO_ISDIRECT) {
+ iolock = XFS_IOLOCK_SHARED;
+ need_i_mutex = 0;
+ } else {
+ iolock = XFS_IOLOCK_EXCL;
+ need_i_mutex = 1;
+ mutex_lock(&inode->i_mutex);
+ }
+
+ xfs_ilock(ip, XFS_ILOCK_EXCL|iolock);
+
+start:
+ error = -generic_write_checks(file, &pos, &count,
+ S_ISBLK(inode->i_mode));
+ if (error) {
+ xfs_iunlock(ip, XFS_ILOCK_EXCL|iolock);
+ goto out_unlock_mutex;
+ }
+
+ if ((DM_EVENT_ENABLED(ip, DM_EVENT_WRITE) &&
+ !(ioflags & IO_INVIS) && !eventsent)) {
+ int dmflags = FILP_DELAY_FLAG(file);
+
+ if (need_i_mutex)
+ dmflags |= DM_FLAGS_IMUX;
+
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ error = XFS_SEND_DATA(ip->i_mount, DM_EVENT_WRITE, ip,
+ pos, count, dmflags, &iolock);
+ if (error) {
+ goto out_unlock_internal;
+ }
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ eventsent = 1;
+
+ /*
+ * The iolock was dropped and reacquired in XFS_SEND_DATA
+ * so we have to recheck the size when appending.
+ * We will only "goto start;" once, since having sent the
+ * event prevents another call to XFS_SEND_DATA, which is
+ * what allows the size to change in the first place.
+ */
+ if ((file->f_flags & O_APPEND) && pos != ip->i_size)
+ goto start;
+ }
+
+ if (ioflags & IO_ISDIRECT) {
+ xfs_buftarg_t *target =
+ XFS_IS_REALTIME_INODE(ip) ?
+ mp->m_rtdev_targp : mp->m_ddev_targp;
+
+ if ((pos & target->bt_smask) || (count & target->bt_smask)) {
+ xfs_iunlock(ip, XFS_ILOCK_EXCL|iolock);
+ return XFS_ERROR(-EINVAL);
+ }
+
+ if (!need_i_mutex && (mapping->nrpages || pos > ip->i_size)) {
+ xfs_iunlock(ip, XFS_ILOCK_EXCL|iolock);
+ iolock = XFS_IOLOCK_EXCL;
+ need_i_mutex = 1;
+ mutex_lock(&inode->i_mutex);
+ xfs_ilock(ip, XFS_ILOCK_EXCL|iolock);
+ goto start;
+ }
+ }
+
+ new_size = pos + count;
+ if (new_size > ip->i_size)
+ ip->i_new_size = new_size;
+
+ if (likely(!(ioflags & IO_INVIS)))
+ file_update_time(file);
+
+ /*
+ * If the offset is beyond the size of the file, we have a couple
+ * of things to do. First, if there is already space allocated
+ * we need to either create holes or zero the disk or ...
+ *
+ * If there is a page where the previous size lands, we need
+ * to zero it out up to the new size.
+ */
+
+ if (pos > ip->i_size) {
+ error = xfs_zero_eof(ip, pos, ip->i_size);
+ if (error) {
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ goto out_unlock_internal;
+ }
+ }
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+
+ /*
+ * If we're writing the file then make sure to clear the
+ * setuid and setgid bits if the process is not being run
+ * by root. This keeps people from modifying setuid and
+ * setgid binaries.
+ */
+ error = -file_remove_suid(file);
+ if (unlikely(error))
+ goto out_unlock_internal;
+
+ /* We can write back this queue in page reclaim */
+ current->backing_dev_info = mapping->backing_dev_info;
+
+ if ((ioflags & IO_ISDIRECT)) {
+ if (mapping->nrpages) {
+ WARN_ON(need_i_mutex == 0);
+ error = xfs_flushinval_pages(ip,
+ (pos & PAGE_CACHE_MASK),
+ -1, FI_REMAPF_LOCKED);
+ if (error)
+ goto out_unlock_internal;
+ }
+
+ if (need_i_mutex) {
+ /* demote the lock now the cached pages are gone */
+ xfs_ilock_demote(ip, XFS_IOLOCK_EXCL);
+ mutex_unlock(&inode->i_mutex);
+
+ iolock = XFS_IOLOCK_SHARED;
+ need_i_mutex = 0;
+ }
+
+ trace_xfs_file_direct_write(ip, count, iocb->ki_pos, ioflags);
+ ret = generic_file_direct_write(iocb, iovp,
+ &nr_segs, pos, &iocb->ki_pos, count, ocount);
+
+ /*
+ * direct-io write to a hole: fall through to buffered I/O
+ * for completing the rest of the request.
+ */
+ if (ret >= 0 && ret != count) {
+ XFS_STATS_ADD(xs_write_bytes, ret);
+
+ pos += ret;
+ count -= ret;
+
+ ioflags &= ~IO_ISDIRECT;
+ xfs_iunlock(ip, iolock);
+ goto relock;
+ }
+ } else {
+ int enospc = 0;
+ ssize_t ret2 = 0;
+
+write_retry:
+ trace_xfs_file_buffered_write(ip, count, iocb->ki_pos, ioflags);
+ ret2 = generic_file_buffered_write(iocb, iovp, nr_segs,
+ pos, &iocb->ki_pos, 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(ip, 0, -1, 0, FI_NONE);
+ if (error)
+ goto out_unlock_internal;
+ enospc = 1;
+ goto write_retry;
+ }
+ ret = ret2;
+ }
+
+ current->backing_dev_info = NULL;
+
+ isize = i_size_read(inode);
+ if (unlikely(ret < 0 && ret != -EFAULT && iocb->ki_pos > isize))
+ iocb->ki_pos = isize;
+
+ if (iocb->ki_pos > ip->i_size) {
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ if (iocb->ki_pos > ip->i_size)
+ ip->i_size = iocb->ki_pos;
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ }
+
+ if (ret == -ENOSPC &&
+ DM_EVENT_ENABLED(ip, DM_EVENT_NOSPACE) && !(ioflags & IO_INVIS)) {
+ xfs_iunlock(ip, iolock);
+ if (need_i_mutex)
+ mutex_unlock(&inode->i_mutex);
+ error = XFS_SEND_NAMESP(ip->i_mount, DM_EVENT_NOSPACE, ip,
+ DM_RIGHT_NULL, ip, DM_RIGHT_NULL, NULL, NULL,
+ 0, 0, 0); /* Delay flag intentionally unused */
+ if (need_i_mutex)
+ mutex_lock(&inode->i_mutex);
+ xfs_ilock(ip, iolock);
+ if (error)
+ goto out_unlock_internal;
+ goto start;
+ }
+
+ error = -ret;
+ if (ret <= 0)
+ goto out_unlock_internal;
+
+ XFS_STATS_ADD(xs_write_bytes, ret);
+
+ /* Handle various SYNC-type writes */
+ if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) {
+ loff_t end = pos + ret - 1;
+ int error2;
+
+ xfs_iunlock(ip, iolock);
+ if (need_i_mutex)
+ mutex_unlock(&inode->i_mutex);
+
+ error2 = filemap_write_and_wait_range(mapping, pos, end);
+ if (!error)
+ error = error2;
+ if (need_i_mutex)
+ mutex_lock(&inode->i_mutex);
+ xfs_ilock(ip, iolock);
+
+ error2 = -xfs_file_fsync(file, file->f_path.dentry,
+ (file->f_flags & __O_SYNC) ? 0 : 1);
+ if (!error)
+ error = error2;
+ }
+
+ out_unlock_internal:
+ if (ip->i_new_size) {
+ xfs_ilock(ip, XFS_ILOCK_EXCL);
+ ip->i_new_size = 0;
+ /*
+ * If this was a direct or synchronous I/O that failed (such
+ * as ENOSPC) then part of the I/O may have been written to
+ * disk before the error occured. In this case the on-disk
+ * file size may have been adjusted beyond the in-memory file
+ * size and now needs to be truncated back.
+ */
+ if (ip->i_d.di_size > ip->i_size)
+ ip->i_d.di_size = ip->i_size;
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
+ }
+ xfs_iunlock(ip, iolock);
+ out_unlock_mutex:
+ if (need_i_mutex)
+ mutex_unlock(&inode->i_mutex);
+ return -error;
}
STATIC int
@@ -160,28 +938,6 @@ xfs_file_release(
return -xfs_release(XFS_I(inode));
}
-/*
- * We ignore the datasync flag here because a datasync is effectively
- * identical to an fsync. That is, datasync implies that we need to write
- * only the metadata needed to be able to access the data that is written
- * if we crash after the call completes. Hence if we are writing beyond
- * EOF we have to log the inode size change as well, which makes it a
- * full fsync. If we don't write beyond EOF, the inode core will be
- * clean in memory and so we don't need to log the inode, just like
- * fsync.
- */
-STATIC int
-xfs_file_fsync(
- struct file *file,
- struct dentry *dentry,
- int datasync)
-{
- struct xfs_inode *ip = XFS_I(dentry->d_inode);
-
- xfs_iflags_clear(ip, XFS_ITRUNCATED);
- return -xfs_fsync(ip);
-}
-
STATIC int
xfs_file_readdir(
struct file *filp,
@@ -203,9 +959,9 @@ xfs_file_readdir(
*
* Try to give it an estimate that's good enough, maybe at some
* point we can change the ->readdir prototype to include the
- * buffer size.
+ * buffer size. For now we use the current glibc buffer size.
*/
- bufsize = (size_t)min_t(loff_t, PAGE_SIZE, ip->i_d.di_size);
+ bufsize = (size_t)min_t(loff_t, 32768, ip->i_d.di_size);
error = xfs_readdir(ip, dirent, bufsize,
(xfs_off_t *)&filp->f_pos, filldir);
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index e8566bbf0f0..61a99608731 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -91,6 +91,16 @@ xfs_mark_inode_dirty_sync(
mark_inode_dirty_sync(inode);
}
+void
+xfs_mark_inode_dirty(
+ xfs_inode_t *ip)
+{
+ struct inode *inode = VFS_I(ip);
+
+ if (!(inode->i_state & (I_WILL_FREE|I_FREEING|I_CLEAR)))
+ mark_inode_dirty(inode);
+}
+
/*
* Change the requested timestamp in the given inode.
* We don't lock across timestamp updates, and we don't log them but
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
index 5af0c81ca1a..facfb323a70 100644
--- a/fs/xfs/linux-2.6/xfs_linux.h
+++ b/fs/xfs/linux-2.6/xfs_linux.h
@@ -88,7 +88,6 @@
#include <xfs_super.h>
#include <xfs_globals.h>
#include <xfs_fs_subr.h>
-#include <xfs_lrw.h>
#include <xfs_buf.h>
/*
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c
deleted file mode 100644
index eac6f80d786..00000000000
--- a/fs/xfs/linux-2.6/xfs_lrw.c
+++ /dev/null
@@ -1,796 +0,0 @@
-/*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-#include "xfs.h"
-#include "xfs_fs.h"
-#include "xfs_bit.h"
-#include "xfs_log.h"
-#include "xfs_inum.h"
-#include "xfs_trans.h"
-#include "xfs_sb.h"
-#include "xfs_ag.h"
-#include "xfs_dir2.h"
-#include "xfs_alloc.h"
-#include "xfs_dmapi.h"
-#include "xfs_quota.h"
-#include "xfs_mount.h"
-#include "xfs_bmap_btree.h"
-#include "xfs_alloc_btree.h"
-#include "xfs_ialloc_btree.h"
-#include "xfs_dir2_sf.h"
-#include "xfs_attr_sf.h"
-#include "xfs_dinode.h"
-#include "xfs_inode.h"
-#include "xfs_bmap.h"
-#include "xfs_btree.h"
-#include "xfs_ialloc.h"
-#include "xfs_rtalloc.h"
-#include "xfs_error.h"
-#include "xfs_itable.h"
-#include "xfs_rw.h"
-#include "xfs_attr.h"
-#include "xfs_inode_item.h"
-#include "xfs_buf_item.h"
-#include "xfs_utils.h"
-#include "xfs_iomap.h"
-#include "xfs_vnodeops.h"
-#include "xfs_trace.h"
-
-#include <linux/capability.h>
-#include <linux/writeback.h>
-
-
-/*
- * xfs_iozero
- *
- * xfs_iozero clears the specified range of buffer supplied,
- * and marks all the affected blocks as valid and modified. If
- * an affected block is not allocated, it will be allocated. If
- * an affected block is not completely overwritten, and is not
- * valid before the operation, it will be read from disk before
- * being partially zeroed.
- */
-STATIC int
-xfs_iozero(
- struct xfs_inode *ip, /* inode */
- loff_t pos, /* offset in file */
- size_t count) /* size of data to zero */
-{
- struct page *page;
- struct address_space *mapping;
- int status;
-
- mapping = VFS_I(ip)->i_mapping;
- do {
- unsigned offset, bytes;
- void *fsdata;
-
- offset = (pos & (PAGE_CACHE_SIZE -1)); /* Within page */
- bytes = PAGE_CACHE_SIZE - offset;
- if (bytes > count)
- bytes = count;
-
- status = pagecache_write_begin(NULL, mapping, pos, bytes,
- AOP_FLAG_UNINTERRUPTIBLE,
- &page, &fsdata);
- if (status)
- break;
-
- zero_user(page, offset, bytes);
-
- status = pagecache_write_end(NULL, mapping, pos, bytes, bytes,
- page, fsdata);
- WARN_ON(status <= 0); /* can't return less than zero! */
- pos += bytes;
- count -= bytes;
- status = 0;
- } while (count);
-
- return (-status);
-}
-
-ssize_t /* bytes read, or (-) error */
-xfs_read(
- xfs_inode_t *ip,
- struct kiocb *iocb,
- const struct iovec *iovp,
- unsigned int segs,
- loff_t *offset,
- int ioflags)
-{
- struct file *file = iocb->ki_filp;
- struct inode *inode = file->f_mapping->host;
- xfs_mount_t *mp = ip->i_mount;
- size_t size = 0;
- ssize_t ret = 0;
- xfs_fsize_t n;
- unsigned long seg;
-
-
- XFS_STATS_INC(xs_read_calls);
-
- /* START copy & waste from filemap.c */
- for (seg = 0; seg < segs; seg++) {
- const struct iovec *iv = &iovp[seg];
-
- /*
- * If any segment has a negative length, or the cumulative
- * length ever wraps negative then return -EINVAL.
- */
- size += iv->iov_len;
- if (unlikely((ssize_t)(size|iv->iov_len) < 0))
- return XFS_ERROR(-EINVAL);
- }
- /* END copy & waste from filemap.c */
-
- if (unlikely(ioflags & IO_ISDIRECT)) {
- xfs_buftarg_t *target =
- XFS_IS_REALTIME_INODE(ip) ?
- mp->m_rtdev_targp : mp->m_ddev_targp;
- if ((*offset & target->bt_smask) ||
- (size & target->bt_smask)) {
- if (*offset == ip->i_size) {
- return (0);
- }
- return -XFS_ERROR(EINVAL);
- }
- }
-
- n = XFS_MAXIOFFSET(mp) - *offset;
- if ((n <= 0) || (size == 0))
- return 0;
-
- if (n < size)
- size = n;
-
- if (XFS_FORCED_SHUTDOWN(mp))
- return -EIO;
-
- if (unlikely(ioflags & IO_ISDIRECT))
- mutex_lock(&inode->i_mutex);
- xfs_ilock(ip, XFS_IOLOCK_SHARED);
-
- if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
- int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags);
- int iolock = XFS_IOLOCK_SHARED;
-
- ret = -XFS_SEND_DATA(mp, DM_EVENT_READ, ip, *offset, size,
- dmflags, &iolock);
- if (ret) {
- xfs_iunlock(ip, XFS_IOLOCK_SHARED);
- if (unlikely(ioflags & IO_ISDIRECT))
- mutex_unlock(&inode->i_mutex);
- return ret;
- }
- }
-
- if (unlikely(ioflags & IO_ISDIRECT)) {
- if (inode->i_mapping->nrpages)
- ret = -xfs_flushinval_pages(ip, (*offset & PAGE_CACHE_MASK),
- -1, FI_REMAPF_LOCKED);
- mutex_unlock(&inode->i_mutex);
- if (ret) {
- xfs_iunlock(ip, XFS_IOLOCK_SHARED);
- return ret;
- }
- }
-
- trace_xfs_file_read(ip, size, *offset, ioflags);
-
- iocb->ki_pos = *offset;
- ret = generic_file_aio_read(iocb, iovp, segs, *offset);
- if (ret > 0)
- XFS_STATS_ADD(xs_read_bytes, ret);
-
- xfs_iunlock(ip, XFS_IOLOCK_SHARED);
- return ret;
-}
-
-ssize_t
-xfs_splice_read(
- xfs_inode_t *ip,
- struct file *infilp,
- loff_t *ppos,
- struct pipe_inode_info *pipe,
- size_t count,
- int flags,
- int ioflags)
-{
- xfs_mount_t *mp = ip->i_mount;
- ssize_t ret;
-
- XFS_STATS_INC(xs_read_calls);
- if (XFS_FORCED_SHUTDOWN(ip->i_mount))
- return -EIO;
-
- xfs_ilock(ip, XFS_IOLOCK_SHARED);
-
- if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) && !(ioflags & IO_INVIS)) {
- int iolock = XFS_IOLOCK_SHARED;
- int error;
-
- error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip, *ppos, count,
- FILP_DELAY_FLAG(infilp), &iolock);
- if (error) {
- xfs_iunlock(ip, XFS_IOLOCK_SHARED);
- return -error;
- }
- }
-
- trace_xfs_file_splice_read(ip, count, *ppos, ioflags);
-
- ret = generic_file_splice_read(infilp, ppos, pipe, count, flags);
- if (ret > 0)
- XFS_STATS_ADD(xs_read_bytes, ret);
-
- xfs_iunlock(ip, XFS_IOLOCK_SHARED);
- return ret;
-}
-
-ssize_t
-xfs_splice_write(
- xfs_inode_t *ip,
- struct pipe_inode_info *pipe,
- struct file *outfilp,
- loff_t *ppos,
- size_t count,
- int flags,
- int ioflags)
-{
- xfs_mount_t *mp = ip->i_mount;
- ssize_t ret;
- struct inode *inode = outfilp->f_mapping->host;
- xfs_fsize_t isize, new_size;
-
- XFS_STATS_INC(xs_write_calls);
- if (XFS_FORCED_SHUTDOWN(ip->i_mount))
- return -EIO;
-
- xfs_ilock(ip, XFS_IOLOCK_EXCL);
-
- if (DM_EVENT_ENABLED(ip, DM_EVENT_WRITE) && !(ioflags & IO_INVIS)) {
- int iolock = XFS_IOLOCK_EXCL;
- int error;
-
- error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, ip, *ppos, count,
- FILP_DELAY_FLAG(outfilp), &iolock);
- if (error) {
- xfs_iunlock(ip, XFS_IOLOCK_EXCL);
- return -error;
- }
- }
-
- new_size = *ppos + count;
-
- xfs_ilock(ip, XFS_ILOCK_EXCL);
- if (new_size > ip->i_size)
- ip->i_new_size = new_size;
- xfs_iunlock(ip, XFS_ILOCK_EXCL);
-
- trace_xfs_file_splice_write(ip, count, *ppos, ioflags);
-
- ret = generic_file_splice_write(pipe, outfilp, ppos, count, flags);
- if (ret > 0)
- XFS_STATS_ADD(xs_write_bytes, ret);
-
- isize = i_size_read(inode);
- if (unlikely(ret < 0 && ret != -EFAULT && *ppos > isize))
- *ppos = isize;
-
- if (*ppos > ip->i_size) {
- xfs_ilock(ip, XFS_ILOCK_EXCL);
- if (*ppos > ip->i_size)
- ip->i_size = *ppos;
- xfs_iunlock(ip, XFS_ILOCK_EXCL);
- }
-
- if (ip->i_new_size) {
- xfs_ilock(ip, XFS_ILOCK_EXCL);
- ip->i_new_size = 0;
- if (ip->i_d.di_size > ip->i_size)
- ip->i_d.di_size = ip->i_size;
- xfs_iunlock(ip, XFS_ILOCK_EXCL);
- }
- xfs_iunlock(ip, XFS_IOLOCK_EXCL);
- return ret;
-}
-
-/*
- * This routine is called to handle zeroing any space in the last
- * block of the file that is beyond the EOF. We do this since the
- * size is being increased without writing anything to that block
- * and we don't want anyone to read the garbage on the disk.
- */
-STATIC int /* error (positive) */
-xfs_zero_last_block(
- xfs_inode_t *ip,
- xfs_fsize_t offset,
- xfs_fsize_t isize)
-{
- xfs_fileoff_t last_fsb;
- xfs_mount_t *mp = ip->i_mount;
- int nimaps;
- int zero_offset;
- int zero_len;
- int error = 0;
- xfs_bmbt_irec_t imap;
-
- ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
-
- zero_offset = XFS_B_FSB_OFFSET(mp, isize);
- if (zero_offset == 0) {
- /*
- * There are no extra bytes in the last block on disk to
- * zero, so return.
- */
- return 0;
- }
-
- last_fsb = XFS_B_TO_FSBT(mp, isize);
- nimaps = 1;
- error = xfs_bmapi(NULL, ip, last_fsb, 1, 0, NULL, 0, &imap,
- &nimaps, NULL, NULL);
- if (error) {
- return error;
- }
- ASSERT(nimaps > 0);
- /*
- * If the block underlying isize is just a hole, then there
- * is nothing to zero.
- */
- if (imap.br_startblock == HOLESTARTBLOCK) {
- return 0;
- }
- /*
- * Zero the part of the last block beyond the EOF, and write it
- * out sync. We need to drop the ilock while we do this so we
- * don't deadlock when the buffer cache calls back to us.
- */
- xfs_iunlock(ip, XFS_ILOCK_EXCL);
-
- zero_len = mp->m_sb.sb_blocksize - zero_offset;
- if (isize + zero_len > offset)
- zero_len = offset - isize;
- error = xfs_iozero(ip, isize, zero_len);
-
- xfs_ilock(ip, XFS_ILOCK_EXCL);
- ASSERT(error >= 0);
- return error;
-}
-
-/*
- * Zero any on disk space between the current EOF and the new,
- * larger EOF. This handles the normal case of zeroing the remainder
- * of the last block in the file and the unusual case of zeroing blocks
- * out beyond the size of the file. This second case only happens
- * with fixed size extents and when the system crashes before the inode
- * size was updated but after blocks were allocated. If fill is set,
- * then any holes in the range are filled and zeroed. If not, the holes
- * are left alone as holes.
- */
-
-int /* error (positive) */
-xfs_zero_eof(
- xfs_inode_t *ip,
- xfs_off_t offset, /* starting I/O offset */
- xfs_fsize_t isize) /* current inode size */
-{
- xfs_mount_t *mp = ip->i_mount;
- xfs_fileoff_t start_zero_fsb;
- xfs_fileoff_t end_zero_fsb;
- xfs_fileoff_t zero_count_fsb;
- xfs_fileoff_t last_fsb;
- xfs_fileoff_t zero_off;
- xfs_fsize_t zero_len;
- int nimaps;
- int error = 0;
- xfs_bmbt_irec_t imap;
-
- ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
- ASSERT(offset > isize);
-
- /*
- * First handle zeroing the block on which isize resides.
- * We only zero a part of that block so it is handled specially.
- */
- error = xfs_zero_last_block(ip, offset, isize);
- if (error) {
- ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
- return error;
- }
-
- /*
- * Calculate the range between the new size and the old
- * where blocks needing to be zeroed may exist. To get the
- * block where the last byte in the file currently resides,
- * we need to subtract one from the size and truncate back
- * to a block boundary. We subtract 1 in case the size is
- * exactly on a block boundary.
- */
- last_fsb = isize ? XFS_B_TO_FSBT(mp, isize - 1) : (xfs_fileoff_t)-1;
- start_zero_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)isize);
- end_zero_fsb = XFS_B_TO_FSBT(mp, offset - 1);
- ASSERT((xfs_sfiloff_t)last_fsb < (xfs_sfiloff_t)start_zero_fsb);
- if (last_fsb == end_zero_fsb) {
- /*
- * The size was only incremented on its last block.
- * We took care of that above, so just return.
- */
- return 0;
- }
-
- ASSERT(start_zero_fsb <= end_zero_fsb);
- while (start_zero_fsb <= end_zero_fsb) {
- nimaps = 1;
- zero_count_fsb = end_zero_fsb - start_zero_fsb + 1;
- error = xfs_bmapi(NULL, ip, start_zero_fsb, zero_count_fsb,
- 0, NULL, 0, &imap, &nimaps, NULL, NULL);
- if (error) {
- ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_IOLOCK_EXCL));
- return error;
- }
- ASSERT(nimaps > 0);
-
- if (imap.br_state == XFS_EXT_UNWRITTEN ||
- imap.br_startblock == HOLESTARTBLOCK) {
- /*
- * This loop handles initializing pages that were
- * partially initialized by the code below this
- * loop. It basically zeroes the part of the page
- * that sits on a hole and sets the page as P_HOLE
- * and calls remapf if it is a mapped file.
- */
- start_zero_fsb = imap.br_startoff + imap.br_blockcount;
- ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
- continue;
- }
-
- /*
- * There are blocks we need to zero.
- * Drop the inode lock while we're doing the I/O.
- * We'll still have the iolock to protect us.
- */
- xfs_iunlock(ip, XFS_ILOCK_EXCL);
-
- zero_off = XFS_FSB_TO_B(mp, start_zero_fsb);
- zero_len = XFS_FSB_TO_B(mp, imap.br_blockcount);
-
- if ((zero_off + zero_len) > offset)
- zero_len = offset - zero_off;
-
- error = xfs_iozero(ip, zero_off, zero_len);
- if (error) {
- goto out_lock;
- }
-
- start_zero_fsb = imap.br_startoff + imap.br_blockcount;
- ASSERT(start_zero_fsb <= (end_zero_fsb + 1));
-
- xfs_ilock(ip, XFS_ILOCK_EXCL);
- }
-
- return 0;
-
-out_lock:
- xfs_ilock(ip, XFS_ILOCK_EXCL);
- ASSERT(error >= 0);
- return error;
-}
-
-ssize_t /* bytes written, or (-) error */
-xfs_write(
- struct xfs_inode *xip,
- struct kiocb *iocb,
- const struct iovec *iovp,
- unsigned int nsegs,
- loff_t *offset,
- int ioflags)
-{
- struct file *file = iocb->ki_filp;
- struct address_space *mapping = file->f_mapping;
- struct inode *inode = mapping->host;
- unsigned long segs = nsegs;
- xfs_mount_t *mp;
- ssize_t ret = 0, error = 0;
- xfs_fsize_t isize, new_size;
- int iolock;
- int eventsent = 0;
- size_t ocount = 0, count;
- loff_t pos;
- int need_i_mutex;
-
- XFS_STATS_INC(xs_write_calls);
-
- error = generic_segment_checks(iovp, &segs, &ocount, VERIFY_READ);
- if (error)
- return error;
-
- count = ocount;
- pos = *offset;
-
- if (count == 0)
- return 0;
-
- mp = xip->i_mount;
-
- xfs_wait_for_freeze(mp, SB_FREEZE_WRITE);
-
- if (XFS_FORCED_SHUTDOWN(mp))
- return -EIO;
-
-relock:
- if (ioflags & IO_ISDIRECT) {
- iolock = XFS_IOLOCK_SHARED;
- need_i_mutex = 0;
- } else {
- iolock = XFS_IOLOCK_EXCL;
- need_i_mutex = 1;
- mutex_lock(&inode->i_mutex);
- }
-
- xfs_ilock(xip, XFS_ILOCK_EXCL|iolock);
-
-start:
- error = -generic_write_checks(file, &pos, &count,
- S_ISBLK(inode->i_mode));
- if (error) {
- xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
- goto out_unlock_mutex;
- }
-
- if ((DM_EVENT_ENABLED(xip, DM_EVENT_WRITE) &&
- !(ioflags & IO_INVIS) && !eventsent)) {
- int dmflags = FILP_DELAY_FLAG(file);
-
- if (need_i_mutex)
- dmflags |= DM_FLAGS_IMUX;
-
- xfs_iunlock(xip, XFS_ILOCK_EXCL);
- error = XFS_SEND_DATA(xip->i_mount, DM_EVENT_WRITE, xip,
- pos, count, dmflags, &iolock);
- if (error) {
- goto out_unlock_internal;
- }
- xfs_ilock(xip, XFS_ILOCK_EXCL);
- eventsent = 1;
-
- /*
- * The iolock was dropped and reacquired in XFS_SEND_DATA
- * so we have to recheck the size when appending.
- * We will only "goto start;" once, since having sent the
- * event prevents another call to XFS_SEND_DATA, which is
- * what allows the size to change in the first place.
- */
- if ((file->f_flags & O_APPEND) && pos != xip->i_size)
- goto start;
- }
-
- if (ioflags & IO_ISDIRECT) {
- xfs_buftarg_t *target =
- XFS_IS_REALTIME_INODE(xip) ?
- mp->m_rtdev_targp : mp->m_ddev_targp;
-
- if ((pos & target->bt_smask) || (count & target->bt_smask)) {
- xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
- return XFS_ERROR(-EINVAL);
- }
-
- if (!need_i_mutex && (mapping->nrpages || pos > xip->i_size)) {
- xfs_iunlock(xip, XFS_ILOCK_EXCL|iolock);
- iolock = XFS_IOLOCK_EXCL;
- need_i_mutex = 1;
- mutex_lock(&inode->i_mutex);
- xfs_ilock(xip, XFS_ILOCK_EXCL|iolock);
- goto start;
- }
- }
-
- new_size = pos + count;
- if (new_size > xip->i_size)
- xip->i_new_size = new_size;
-
- if (likely(!(ioflags & IO_INVIS)))
- file_update_time(file);
-
- /*
- * If the offset is beyond the size of the file, we have a couple
- * of things to do. First, if there is already space allocated
- * we need to either create holes or zero the disk or ...
- *
- * If there is a page where the previous size lands, we need
- * to zero it out up to the new size.
- */
-
- if (pos > xip->i_size) {
- error = xfs_zero_eof(xip, pos, xip->i_size);
- if (error) {
- xfs_iunlock(xip, XFS_ILOCK_EXCL);
- goto out_unlock_internal;
- }
- }
- xfs_iunlock(xip, XFS_ILOCK_EXCL);
-
- /*
- * If we're writing the file then make sure to clear the
- * setuid and setgid bits if the process is not being run
- * by root. This keeps people from modifying setuid and
- * setgid binaries.
- */
- error = -file_remove_suid(file);
- if (unlikely(error))
- goto out_unlock_internal;
-
- /* We can write back this queue in page reclaim */
- current->backing_dev_info = mapping->backing_dev_info;
-
- if ((ioflags & IO_ISDIRECT)) {
- if (mapping->nrpages) {
- WARN_ON(need_i_mutex == 0);
- error = xfs_flushinval_pages(xip,
- (pos & PAGE_CACHE_MASK),
- -1, FI_REMAPF_LOCKED);
- if (error)
- goto out_unlock_internal;
- }
-
- if (need_i_mutex) {
- /* demote the lock now the cached pages are gone */
- xfs_ilock_demote(xip, XFS_IOLOCK_EXCL);
- mutex_unlock(&inode->i_mutex);
-
- iolock = XFS_IOLOCK_SHARED;
- need_i_mutex = 0;
- }
-
- trace_xfs_file_direct_write(xip, count, *offset, ioflags);
- ret = generic_file_direct_write(iocb, iovp,
- &segs, pos, offset, count, ocount);
-
- /*
- * direct-io write to a hole: fall through to buffered I/O
- * for completing the rest of the request.
- */
- if (ret >= 0 && ret != count) {
- XFS_STATS_ADD(xs_write_bytes, ret);
-
- pos += ret;
- count -= ret;
-
- ioflags &= ~IO_ISDIRECT;
- xfs_iunlock(xip, iolock);
- goto relock;
- }
- } else {
- int enospc = 0;
- ssize_t ret2 = 0;
-
-write_retry:
- trace_xfs_file_buffered_write(xip, count, *offset, ioflags);
- 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;
-
- isize = i_size_read(inode);
- if (unlikely(ret < 0 && ret != -EFAULT && *offset > isize))
- *offset = isize;
-
- if (*offset > xip->i_size) {
- xfs_ilock(xip, XFS_ILOCK_EXCL);
- if (*offset > xip->i_size)
- xip->i_size = *offset;
- xfs_iunlock(xip, XFS_ILOCK_EXCL);
- }
-
- if (ret == -ENOSPC &&
- DM_EVENT_ENABLED(xip, DM_EVENT_NOSPACE) && !(ioflags & IO_INVIS)) {
- xfs_iunlock(xip, iolock);
- if (need_i_mutex)
- mutex_unlock(&inode->i_mutex);
- error = XFS_SEND_NAMESP(xip->i_mount, DM_EVENT_NOSPACE, xip,
- DM_RIGHT_NULL, xip, DM_RIGHT_NULL, NULL, NULL,
- 0, 0, 0); /* Delay flag intentionally unused */
- if (need_i_mutex)
- mutex_lock(&inode->i_mutex);
- xfs_ilock(xip, iolock);
- if (error)
- goto out_unlock_internal;
- goto start;
- }
-
- error = -ret;
- if (ret <= 0)
- goto out_unlock_internal;
-
- XFS_STATS_ADD(xs_write_bytes, ret);
-
- /* Handle various SYNC-type writes */
- if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) {
- loff_t end = pos + ret - 1;
- int error2;
-
- xfs_iunlock(xip, iolock);
- if (need_i_mutex)
- mutex_unlock(&inode->i_mutex);
-
- error2 = filemap_write_and_wait_range(mapping, pos, end);
- if (!error)
- error = error2;
- if (need_i_mutex)
- mutex_lock(&inode->i_mutex);
- xfs_ilock(xip, iolock);
-
- error2 = xfs_fsync(xip);
- if (!error)
- error = error2;
- }
-
- out_unlock_internal:
- if (xip->i_new_size) {
- xfs_ilock(xip, XFS_ILOCK_EXCL);
- xip->i_new_size = 0;
- /*
- * If this was a direct or synchronous I/O that failed (such
- * as ENOSPC) then part of the I/O may have been written to
- * disk before the error occured. In this case the on-disk
- * file size may have been adjusted beyond the in-memory file
- * size and now needs to be truncated back.
- */
- if (xip->i_d.di_size > xip->i_size)
- xip->i_d.di_size = xip->i_size;
- xfs_iunlock(xip, XFS_ILOCK_EXCL);
- }
- xfs_iunlock(xip, iolock);
- out_unlock_mutex:
- if (need_i_mutex)
- mutex_unlock(&inode->i_mutex);
- return -error;
-}
-
-/*
- * If the underlying (data/log/rt) device is readonly, there are some
- * operations that cannot proceed.
- */
-int
-xfs_dev_is_read_only(
- xfs_mount_t *mp,
- char *message)
-{
- if (xfs_readonly_buftarg(mp->m_ddev_targp) ||
- xfs_readonly_buftarg(mp->m_logdev_targp) ||
- (mp->m_rtdev_targp && xfs_readonly_buftarg(mp->m_rtdev_targp))) {
- cmn_err(CE_NOTE,
- "XFS: %s required on read-only device.", message);
- cmn_err(CE_NOTE,
- "XFS: write access unavailable, cannot proceed.");
- return EROFS;
- }
- return 0;
-}
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h
deleted file mode 100644
index 342ae8c0d01..00000000000
--- a/fs/xfs/linux-2.6/xfs_lrw.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-#ifndef __XFS_LRW_H__
-#define __XFS_LRW_H__
-
-struct xfs_mount;
-struct xfs_inode;
-struct xfs_buf;
-
-extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
-
-extern int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t);
-
-#endif /* __XFS_LRW_H__ */
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index a9f6d20aff4..05cd85317f6 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -607,7 +607,8 @@ xfssyncd(
set_freezable();
timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10);
for (;;) {
- timeleft = schedule_timeout_interruptible(timeleft);
+ if (list_empty(&mp->m_sync_list))
+ timeleft = schedule_timeout_interruptible(timeleft);
/* swsusp */
try_to_freeze();
if (kthread_should_stop() && list_empty(&mp->m_sync_list))
@@ -627,8 +628,7 @@ xfssyncd(
list_add_tail(&mp->m_sync_work.w_list,
&mp->m_sync_list);
}
- list_for_each_entry_safe(work, n, &mp->m_sync_list, w_list)
- list_move(&work->w_list, &tmp);
+ list_splice_init(&mp->m_sync_list, &tmp);
spin_unlock(&mp->m_sync_lock);
list_for_each_entry_safe(work, n, &tmp, w_list) {
@@ -688,12 +688,12 @@ xfs_inode_set_reclaim_tag(
struct xfs_perag *pag;
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
- read_lock(&pag->pag_ici_lock);
+ write_lock(&pag->pag_ici_lock);
spin_lock(&ip->i_flags_lock);
__xfs_inode_set_reclaim_tag(pag, ip);
__xfs_iflags_set(ip, XFS_IRECLAIMABLE);
spin_unlock(&ip->i_flags_lock);
- read_unlock(&pag->pag_ici_lock);
+ write_unlock(&pag->pag_ici_lock);
xfs_perag_put(pag);
}
diff --git a/fs/xfs/linux-2.6/xfs_trace.c b/fs/xfs/linux-2.6/xfs_trace.c
index 856eb3c8d60..5a107601e96 100644
--- a/fs/xfs/linux-2.6/xfs_trace.c
+++ b/fs/xfs/linux-2.6/xfs_trace.c
@@ -52,22 +52,6 @@
#include "quota/xfs_dquot.h"
/*
- * Format fsblock number into a static buffer & return it.
- */
-STATIC char *xfs_fmtfsblock(xfs_fsblock_t bno)
-{
- static char rval[50];
-
- if (bno == NULLFSBLOCK)
- sprintf(rval, "NULLFSBLOCK");
- else if (isnullstartblock(bno))
- sprintf(rval, "NULLSTARTBLOCK(%lld)", startblockval(bno));
- else
- sprintf(rval, "%lld", (xfs_dfsbno_t)bno);
- return rval;
-}
-
-/*
* We include this last to have the helpers above available for the trace
* event implementations.
*/
diff --git a/fs/xfs/linux-2.6/xfs_trace.h b/fs/xfs/linux-2.6/xfs_trace.h
index a4574dcf506..fcaa62f0799 100644
--- a/fs/xfs/linux-2.6/xfs_trace.h
+++ b/fs/xfs/linux-2.6/xfs_trace.h
@@ -197,13 +197,13 @@ TRACE_EVENT(xfs_iext_insert,
__entry->caller_ip = caller_ip;
),
TP_printk("dev %d:%d ino 0x%llx state %s idx %ld "
- "offset %lld block %s count %lld flag %d caller %pf",
+ "offset %lld block %lld count %lld flag %d caller %pf",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
__print_flags(__entry->bmap_state, "|", XFS_BMAP_EXT_FLAGS),
(long)__entry->idx,
__entry->startoff,
- xfs_fmtfsblock(__entry->startblock),
+ (__int64_t)__entry->startblock,
__entry->blockcount,
__entry->state,
(char *)__entry->caller_ip)
@@ -241,13 +241,13 @@ DECLARE_EVENT_CLASS(xfs_bmap_class,
__entry->caller_ip = caller_ip;
),
TP_printk("dev %d:%d ino 0x%llx state %s idx %ld "
- "offset %lld block %s count %lld flag %d caller %pf",
+ "offset %lld block %lld count %lld flag %d caller %pf",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->ino,
__print_flags(__entry->bmap_state, "|", XFS_BMAP_EXT_FLAGS),
(long)__entry->idx,
__entry->startoff,
- xfs_fmtfsblock(__entry->startblock),
+ (__int64_t)__entry->startblock,
__entry->blockcount,
__entry->state,
(char *)__entry->caller_ip)
@@ -593,7 +593,7 @@ DECLARE_EVENT_CLASS(xfs_dquot_class,
TP_ARGS(dqp),
TP_STRUCT__entry(
__field(dev_t, dev)
- __field(__be32, id)
+ __field(u32, id)
__field(unsigned, flags)
__field(unsigned, nrefs)
__field(unsigned long long, res_bcount)
@@ -606,7 +606,7 @@ DECLARE_EVENT_CLASS(xfs_dquot_class,
), \
TP_fast_assign(
__entry->dev = dqp->q_mount->m_super->s_dev;
- __entry->id = dqp->q_core.d_id;
+ __entry->id = be32_to_cpu(dqp->q_core.d_id);
__entry->flags = dqp->dq_flags;
__entry->nrefs = dqp->q_nrefs;
__entry->res_bcount = dqp->q_res_bcount;
@@ -622,10 +622,10 @@ DECLARE_EVENT_CLASS(xfs_dquot_class,
be64_to_cpu(dqp->q_core.d_ino_softlimit);
),
TP_printk("dev %d:%d id 0x%x flags %s nrefs %u res_bc 0x%llx "
- "bcnt 0x%llx [hard 0x%llx | soft 0x%llx] "
- "icnt 0x%llx [hard 0x%llx | soft 0x%llx]",
+ "bcnt 0x%llx bhardlimit 0x%llx bsoftlimit 0x%llx "
+ "icnt 0x%llx ihardlimit 0x%llx isoftlimit 0x%llx]",
MAJOR(__entry->dev), MINOR(__entry->dev),
- be32_to_cpu(__entry->id),
+ __entry->id,
__print_flags(__entry->flags, "|", XFS_DQ_FLAGS),
__entry->nrefs,
__entry->res_bcount,
@@ -881,7 +881,7 @@ TRACE_EVENT(name, \
), \
TP_printk("dev %d:%d ino 0x%llx size 0x%llx new_size 0x%llx " \
"offset 0x%llx count %zd flags %s " \
- "startoff 0x%llx startblock %s blockcount 0x%llx", \
+ "startoff 0x%llx startblock %lld blockcount 0x%llx", \
MAJOR(__entry->dev), MINOR(__entry->dev), \
__entry->ino, \
__entry->size, \
@@ -890,7 +890,7 @@ TRACE_EVENT(name, \
__entry->count, \
__print_flags(__entry->flags, "|", BMAPI_FLAGS), \
__entry->startoff, \
- xfs_fmtfsblock(__entry->startblock), \
+ (__int64_t)__entry->startblock, \
__entry->blockcount) \
)
DEFINE_IOMAP_EVENT(xfs_iomap_enter);
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 1869fb97381..5c11e4d1701 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -2550,22 +2550,134 @@ xfs_bmap_rtalloc(
}
STATIC int
+xfs_bmap_btalloc_nullfb(
+ struct xfs_bmalloca *ap,
+ struct xfs_alloc_arg *args,
+ xfs_extlen_t *blen)
+{
+ struct xfs_mount *mp = ap->ip->i_mount;
+ struct xfs_perag *pag;
+ xfs_agnumber_t ag, startag;
+ int notinit = 0;
+ int error;
+
+ if (ap->userdata && xfs_inode_is_filestream(ap->ip))
+ args->type = XFS_ALLOCTYPE_NEAR_BNO;
+ else
+ args->type = XFS_ALLOCTYPE_START_BNO;
+ args->total = ap->total;
+
+ /*
+ * Search for an allocation group with a single extent large enough
+ * for the request. If one isn't found, then adjust the minimum
+ * allocation size to the largest space found.
+ */
+ startag = ag = XFS_FSB_TO_AGNO(mp, args->fsbno);
+ if (startag == NULLAGNUMBER)
+ startag = ag = 0;
+
+ pag = xfs_perag_get(mp, ag);
+ while (*blen < ap->alen) {
+ if (!pag->pagf_init) {
+ error = xfs_alloc_pagf_init(mp, args->tp, ag,
+ XFS_ALLOC_FLAG_TRYLOCK);
+ if (error) {
+ xfs_perag_put(pag);
+ return error;
+ }
+ }
+
+ /*
+ * See xfs_alloc_fix_freelist...
+ */
+ if (pag->pagf_init) {
+ xfs_extlen_t longest;
+ longest = xfs_alloc_longest_free_extent(mp, pag);
+ if (*blen < longest)
+ *blen = longest;
+ } else
+ notinit = 1;
+
+ if (xfs_inode_is_filestream(ap->ip)) {
+ if (*blen >= ap->alen)
+ break;
+
+ if (ap->userdata) {
+ /*
+ * If startag is an invalid AG, we've
+ * come here once before and
+ * xfs_filestream_new_ag picked the
+ * best currently available.
+ *
+ * Don't continue looping, since we
+ * could loop forever.
+ */
+ if (startag == NULLAGNUMBER)
+ break;
+
+ error = xfs_filestream_new_ag(ap, &ag);
+ xfs_perag_put(pag);
+ if (error)
+ return error;
+
+ /* loop again to set 'blen'*/
+ startag = NULLAGNUMBER;
+ pag = xfs_perag_get(mp, ag);
+ continue;
+ }
+ }
+ if (++ag == mp->m_sb.sb_agcount)
+ ag = 0;
+ if (ag == startag)
+ break;
+ xfs_perag_put(pag);
+ pag = xfs_perag_get(mp, ag);
+ }
+ xfs_perag_put(pag);
+
+ /*
+ * Since the above loop did a BUF_TRYLOCK, it is
+ * possible that there is space for this request.
+ */
+ if (notinit || *blen < ap->minlen)
+ args->minlen = ap->minlen;
+ /*
+ * If the best seen length is less than the request
+ * length, use the best as the minimum.
+ */
+ else if (*blen < ap->alen)
+ args->minlen = *blen;
+ /*
+ * Otherwise we've seen an extent as big as alen,
+ * use that as the minimum.
+ */
+ else
+ args->minlen = ap->alen;
+
+ /*
+ * set the failure fallback case to look in the selected
+ * AG as the stream may have moved.
+ */
+ if (xfs_inode_is_filestream(ap->ip))
+ ap->rval = args->fsbno = XFS_AGB_TO_FSB(mp, ag, 0);
+
+ return 0;
+}
+
+STATIC int
xfs_bmap_btalloc(
xfs_bmalloca_t *ap) /* bmap alloc argument struct */
{
xfs_mount_t *mp; /* mount point structure */
xfs_alloctype_t atype = 0; /* type for allocation routines */
xfs_extlen_t align; /* minimum allocation alignment */
- xfs_agnumber_t ag;
xfs_agnumber_t fb_agno; /* ag number of ap->firstblock */
- xfs_agnumber_t startag;
+ xfs_agnumber_t ag;
xfs_alloc_arg_t args;
xfs_extlen_t blen;
xfs_extlen_t nextminlen = 0;
- xfs_perag_t *pag;
int nullfb; /* true if ap->firstblock isn't set */
int isaligned;
- int notinit;
int tryagain;
int error;
@@ -2612,103 +2724,9 @@ xfs_bmap_btalloc(
args.firstblock = ap->firstblock;
blen = 0;
if (nullfb) {
- if (ap->userdata && xfs_inode_is_filestream(ap->ip))
- args.type = XFS_ALLOCTYPE_NEAR_BNO;
- else
- args.type = XFS_ALLOCTYPE_START_BNO;
- args.total = ap->total;
-
- /*
- * Search for an allocation group with a single extent
- * large enough for the request.
- *
- * If one isn't found, then adjust the minimum allocation
- * size to the largest space found.
- */
- startag = ag = XFS_FSB_TO_AGNO(mp, args.fsbno);
- if (startag == NULLAGNUMBER)
- startag = ag = 0;
- notinit = 0;
- pag = xfs_perag_get(mp, ag);
- while (blen < ap->alen) {
- if (!pag->pagf_init &&
- (error = xfs_alloc_pagf_init(mp, args.tp,
- ag, XFS_ALLOC_FLAG_TRYLOCK))) {
- xfs_perag_put(pag);
- return error;
- }
- /*
- * See xfs_alloc_fix_freelist...
- */
- if (pag->pagf_init) {
- xfs_extlen_t longest;
- longest = xfs_alloc_longest_free_extent(mp, pag);
- if (blen < longest)
- blen = longest;
- } else
- notinit = 1;
-
- if (xfs_inode_is_filestream(ap->ip)) {
- if (blen >= ap->alen)
- break;
-
- if (ap->userdata) {
- /*
- * If startag is an invalid AG, we've
- * come here once before and
- * xfs_filestream_new_ag picked the
- * best currently available.
- *
- * Don't continue looping, since we
- * could loop forever.
- */
- if (startag == NULLAGNUMBER)
- break;
-
- error = xfs_filestream_new_ag(ap, &ag);
- xfs_perag_put(pag);
- if (error)
- return error;
-
- /* loop again to set 'blen'*/
- startag = NULLAGNUMBER;
- pag = xfs_perag_get(mp, ag);
- continue;
- }
- }
- if (++ag == mp->m_sb.sb_agcount)
- ag = 0;
- if (ag == startag)
- break;
- xfs_perag_put(pag);
- pag = xfs_perag_get(mp, ag);
- }
- xfs_perag_put(pag);
- /*
- * Since the above loop did a BUF_TRYLOCK, it is
- * possible that there is space for this request.
- */
- if (notinit || blen < ap->minlen)
- args.minlen = ap->minlen;
- /*
- * If the best seen length is less than the request
- * length, use the best as the minimum.
- */
- else if (blen < ap->alen)
- args.minlen = blen;
- /*
- * Otherwise we've seen an extent as big as alen,
- * use that as the minimum.
- */
- else
- args.minlen = ap->alen;
-
- /*
- * set the failure fallback case to look in the selected
- * AG as the stream may have moved.
- */
- if (xfs_inode_is_filestream(ap->ip))
- ap->rval = args.fsbno = XFS_AGB_TO_FSB(mp, ag, 0);
+ error = xfs_bmap_btalloc_nullfb(ap, &args, &blen);
+ if (error)
+ return error;
} else if (ap->low) {
if (xfs_inode_is_filestream(ap->ip))
args.type = XFS_ALLOCTYPE_FIRST_AG;
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h
index f52ac276277..7cf7220e7d5 100644
--- a/fs/xfs/xfs_fs.h
+++ b/fs/xfs/xfs_fs.h
@@ -292,7 +292,8 @@ typedef struct xfs_bstat {
__s32 bs_extents; /* number of extents */
__u32 bs_gen; /* generation count */
__u16 bs_projid; /* project id */
- unsigned char bs_pad[14]; /* pad space, unused */
+ __u16 bs_forkoff; /* inode fork offset in bytes */
+ unsigned char bs_pad[12]; /* pad space, unused */
__u32 bs_dmevmask; /* DMIG event mask */
__u16 bs_dmstate; /* DMIG state info */
__u16 bs_aextents; /* attribute number of extents */
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index e281eb4a1c4..6845db90818 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -190,13 +190,12 @@ xfs_iget_cache_hit(
trace_xfs_iget_reclaim(ip);
/*
- * We need to set XFS_INEW atomically with clearing the
- * reclaimable tag so that we do have an indicator of the
- * inode still being initialized.
+ * We need to set XFS_IRECLAIM to prevent xfs_reclaim_inode
+ * from stomping over us while we recycle the inode. We can't
+ * clear the radix tree reclaimable tag yet as it requires
+ * pag_ici_lock to be held exclusive.
*/
- ip->i_flags |= XFS_INEW;
- ip->i_flags &= ~XFS_IRECLAIMABLE;
- __xfs_inode_clear_reclaim_tag(mp, pag, ip);
+ ip->i_flags |= XFS_IRECLAIM;
spin_unlock(&ip->i_flags_lock);
read_unlock(&pag->pag_ici_lock);
@@ -216,7 +215,15 @@ xfs_iget_cache_hit(
trace_xfs_iget_reclaim(ip);
goto out_error;
}
+
+ write_lock(&pag->pag_ici_lock);
+ spin_lock(&ip->i_flags_lock);
+ ip->i_flags &= ~(XFS_IRECLAIMABLE | XFS_IRECLAIM);
+ ip->i_flags |= XFS_INEW;
+ __xfs_inode_clear_reclaim_tag(mp, pag, ip);
inode->i_state = I_NEW;
+ spin_unlock(&ip->i_flags_lock);
+ write_unlock(&pag->pag_ici_lock);
} else {
/* If the VFS inode is being torn down, pause and try again. */
if (!igrab(inode)) {
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index fa31360046d..0ffd5644704 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -2439,75 +2439,31 @@ xfs_idestroy_fork(
}
/*
- * Increment the pin count of the given buffer.
- * This value is protected by ipinlock spinlock in the mount structure.
+ * This is called to unpin an inode. The caller must have the inode locked
+ * in at least shared mode so that the buffer cannot be subsequently pinned
+ * once someone is waiting for it to be unpinned.
*/
-void
-xfs_ipin(
- xfs_inode_t *ip)
-{
- ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
-
- atomic_inc(&ip->i_pincount);
-}
-
-/*
- * Decrement the pin count of the given inode, and wake up
- * anyone in xfs_iwait_unpin() if the count goes to 0. The
- * inode must have been previously pinned with a call to xfs_ipin().
- */
-void
-xfs_iunpin(
- xfs_inode_t *ip)
-{
- ASSERT(atomic_read(&ip->i_pincount) > 0);
-
- if (atomic_dec_and_test(&ip->i_pincount))
- wake_up(&ip->i_ipin_wait);
-}
-
-/*
- * This is called to unpin an inode. It can be directed to wait or to return
- * immediately without waiting for the inode to be unpinned. The caller must
- * have the inode locked in at least shared mode so that the buffer cannot be
- * subsequently pinned once someone is waiting for it to be unpinned.
- */
-STATIC void
-__xfs_iunpin_wait(
- xfs_inode_t *ip,
- int wait)
+static void
+xfs_iunpin_nowait(
+ struct xfs_inode *ip)
{
- xfs_inode_log_item_t *iip = ip->i_itemp;
-
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
- if (atomic_read(&ip->i_pincount) == 0)
- return;
/* Give the log a push to start the unpinning I/O */
- if (iip && iip->ili_last_lsn)
- xfs_log_force_lsn(ip->i_mount, iip->ili_last_lsn, 0);
- else
- xfs_log_force(ip->i_mount, 0);
+ xfs_log_force_lsn(ip->i_mount, ip->i_itemp->ili_last_lsn, 0);
- if (wait)
- wait_event(ip->i_ipin_wait, (atomic_read(&ip->i_pincount) == 0));
}
void
xfs_iunpin_wait(
- xfs_inode_t *ip)
+ struct xfs_inode *ip)
{
- __xfs_iunpin_wait(ip, 1);
-}
-
-static inline void
-xfs_iunpin_nowait(
- xfs_inode_t *ip)
-{
- __xfs_iunpin_wait(ip, 0);
+ if (xfs_ipincount(ip)) {
+ xfs_iunpin_nowait(ip);
+ wait_event(ip->i_ipin_wait, (xfs_ipincount(ip) == 0));
+ }
}
-
/*
* xfs_iextents_copy()
*
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 6c912b02759..9965e40a461 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -471,8 +471,6 @@ int xfs_itruncate_finish(struct xfs_trans **, xfs_inode_t *,
int xfs_iunlink(struct xfs_trans *, xfs_inode_t *);
void xfs_iext_realloc(xfs_inode_t *, int, int);
-void xfs_ipin(xfs_inode_t *);
-void xfs_iunpin(xfs_inode_t *);
void xfs_iunpin_wait(xfs_inode_t *);
int xfs_iflush(xfs_inode_t *, uint);
void xfs_ichgtime(xfs_inode_t *, int);
@@ -480,6 +478,7 @@ void xfs_lock_inodes(xfs_inode_t **, int, uint);
void xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint);
void xfs_synchronize_times(xfs_inode_t *);
+void xfs_mark_inode_dirty(xfs_inode_t *);
void xfs_mark_inode_dirty_sync(xfs_inode_t *);
#define IHOLD(ip) \
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index d4dc063111f..7bfea854015 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -535,23 +535,23 @@ xfs_inode_item_format(
/*
* This is called to pin the inode associated with the inode log
- * item in memory so it cannot be written out. Do this by calling
- * xfs_ipin() to bump the pin count in the inode while holding the
- * inode pin lock.
+ * item in memory so it cannot be written out.
*/
STATIC void
xfs_inode_item_pin(
xfs_inode_log_item_t *iip)
{
ASSERT(xfs_isilocked(iip->ili_inode, XFS_ILOCK_EXCL));
- xfs_ipin(iip->ili_inode);
+
+ atomic_inc(&iip->ili_inode->i_pincount);
}
/*
* This is called to unpin the inode associated with the inode log
* item which was previously pinned with a call to xfs_inode_item_pin().
- * Just call xfs_iunpin() on the inode to do this.
+ *
+ * Also wake up anyone in xfs_iunpin_wait() if the count goes to 0.
*/
/* ARGSUSED */
STATIC void
@@ -559,7 +559,11 @@ xfs_inode_item_unpin(
xfs_inode_log_item_t *iip,
int stale)
{
- xfs_iunpin(iip->ili_inode);
+ struct xfs_inode *ip = iip->ili_inode;
+
+ ASSERT(atomic_read(&ip->i_pincount) > 0);
+ if (atomic_dec_and_test(&ip->i_pincount))
+ wake_up(&ip->i_ipin_wait);
}
/* ARGSUSED */
@@ -568,7 +572,7 @@ xfs_inode_item_unpin_remove(
xfs_inode_log_item_t *iip,
xfs_trans_t *tp)
{
- xfs_iunpin(iip->ili_inode);
+ xfs_inode_item_unpin(iip, 0);
}
/*
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 3af02314c60..b1b801e4a28 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -106,6 +106,7 @@ xfs_bulkstat_one_iget(
buf->bs_dmevmask = dic->di_dmevmask;
buf->bs_dmstate = dic->di_dmstate;
buf->bs_aextents = dic->di_anextents;
+ buf->bs_forkoff = XFS_IFORK_BOFF(ip);
switch (dic->di_format) {
case XFS_DINODE_FMT_DEV:
@@ -176,6 +177,7 @@ xfs_bulkstat_one_dinode(
buf->bs_dmevmask = be32_to_cpu(dic->di_dmevmask);
buf->bs_dmstate = be16_to_cpu(dic->di_dmstate);
buf->bs_aextents = be16_to_cpu(dic->di_anextents);
+ buf->bs_forkoff = XFS_DFORK_BOFF(dic);
switch (dic->di_format) {
case XFS_DINODE_FMT_DEV:
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 4f16be4b6ee..e8fba92d7cd 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -60,7 +60,7 @@ STATIC int xlog_space_left(xlog_t *log, int cycle, int bytes);
STATIC int xlog_sync(xlog_t *log, xlog_in_core_t *iclog);
STATIC void xlog_dealloc_log(xlog_t *log);
STATIC int xlog_write(xfs_mount_t *mp, xfs_log_iovec_t region[],
- int nentries, xfs_log_ticket_t tic,
+ int nentries, struct xlog_ticket *tic,
xfs_lsn_t *start_lsn,
xlog_in_core_t **commit_iclog,
uint flags);
@@ -243,14 +243,14 @@ xlog_tic_add_region(xlog_ticket_t *tic, uint len, uint type)
* out when the next write occurs.
*/
xfs_lsn_t
-xfs_log_done(xfs_mount_t *mp,
- xfs_log_ticket_t xtic,
- void **iclog,
- uint flags)
+xfs_log_done(
+ struct xfs_mount *mp,
+ struct xlog_ticket *ticket,
+ struct xlog_in_core **iclog,
+ uint flags)
{
- xlog_t *log = mp->m_log;
- xlog_ticket_t *ticket = (xfs_log_ticket_t) xtic;
- xfs_lsn_t lsn = 0;
+ struct log *log = mp->m_log;
+ xfs_lsn_t lsn = 0;
if (XLOG_FORCED_SHUTDOWN(log) ||
/*
@@ -258,8 +258,7 @@ xfs_log_done(xfs_mount_t *mp,
* If we get an error, just continue and give back the log ticket.
*/
(((ticket->t_flags & XLOG_TIC_INITED) == 0) &&
- (xlog_commit_record(mp, ticket,
- (xlog_in_core_t **)iclog, &lsn)))) {
+ (xlog_commit_record(mp, ticket, iclog, &lsn)))) {
lsn = (xfs_lsn_t) -1;
if (ticket->t_flags & XLOG_TIC_PERM_RESERV) {
flags |= XFS_LOG_REL_PERM_RESERV;
@@ -289,7 +288,7 @@ xfs_log_done(xfs_mount_t *mp,
}
return lsn;
-} /* xfs_log_done */
+}
/*
* Attaches a new iclog I/O completion callback routine during
@@ -298,11 +297,11 @@ xfs_log_done(xfs_mount_t *mp,
* executing the callback at an appropriate time.
*/
int
-xfs_log_notify(xfs_mount_t *mp, /* mount of partition */
- void *iclog_hndl, /* iclog to hang callback off */
- xfs_log_callback_t *cb)
+xfs_log_notify(
+ struct xfs_mount *mp,
+ struct xlog_in_core *iclog,
+ xfs_log_callback_t *cb)
{
- xlog_in_core_t *iclog = (xlog_in_core_t *)iclog_hndl;
int abortflg;
spin_lock(&iclog->ic_callback_lock);
@@ -316,16 +315,14 @@ xfs_log_notify(xfs_mount_t *mp, /* mount of partition */
}
spin_unlock(&iclog->ic_callback_lock);
return abortflg;
-} /* xfs_log_notify */
+}
int
-xfs_log_release_iclog(xfs_mount_t *mp,
- void *iclog_hndl)
+xfs_log_release_iclog(
+ struct xfs_mount *mp,
+ struct xlog_in_core *iclog)
{
- xlog_t *log = mp->m_log;
- xlog_in_core_t *iclog = (xlog_in_core_t *)iclog_hndl;
-
- if (xlog_state_release_iclog(log, iclog)) {
+ if (xlog_state_release_iclog(mp->m_log, iclog)) {
xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
return EIO;
}
@@ -344,17 +341,18 @@ xfs_log_release_iclog(xfs_mount_t *mp,
* reservation, we prevent over allocation problems.
*/
int
-xfs_log_reserve(xfs_mount_t *mp,
- int unit_bytes,
- int cnt,
- xfs_log_ticket_t *ticket,
- __uint8_t client,
- uint flags,
- uint t_type)
+xfs_log_reserve(
+ struct xfs_mount *mp,
+ int unit_bytes,
+ int cnt,
+ struct xlog_ticket **ticket,
+ __uint8_t client,
+ uint flags,
+ uint t_type)
{
- xlog_t *log = mp->m_log;
- xlog_ticket_t *internal_ticket;
- int retval = 0;
+ struct log *log = mp->m_log;
+ struct xlog_ticket *internal_ticket;
+ int retval = 0;
ASSERT(client == XFS_TRANSACTION || client == XFS_LOG);
ASSERT((flags & XFS_LOG_NOSLEEP) == 0);
@@ -367,7 +365,7 @@ xfs_log_reserve(xfs_mount_t *mp,
if (*ticket != NULL) {
ASSERT(flags & XFS_LOG_PERM_RESERV);
- internal_ticket = (xlog_ticket_t *)*ticket;
+ internal_ticket = *ticket;
trace_xfs_log_reserve(log, internal_ticket);
@@ -519,7 +517,7 @@ xfs_log_unmount_write(xfs_mount_t *mp)
xlog_in_core_t *first_iclog;
#endif
xfs_log_iovec_t reg[1];
- xfs_log_ticket_t tic = NULL;
+ xlog_ticket_t *tic = NULL;
xfs_lsn_t lsn;
int error;
@@ -656,24 +654,24 @@ xfs_log_unmount(xfs_mount_t *mp)
* transaction occur with one call to xfs_log_write().
*/
int
-xfs_log_write(xfs_mount_t * mp,
- xfs_log_iovec_t reg[],
- int nentries,
- xfs_log_ticket_t tic,
- xfs_lsn_t *start_lsn)
+xfs_log_write(
+ struct xfs_mount *mp,
+ struct xfs_log_iovec reg[],
+ int nentries,
+ struct xlog_ticket *tic,
+ xfs_lsn_t *start_lsn)
{
- int error;
- xlog_t *log = mp->m_log;
+ struct log *log = mp->m_log;
+ int error;
if (XLOG_FORCED_SHUTDOWN(log))
return XFS_ERROR(EIO);
- if ((error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0))) {
+ error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0);
+ if (error)
xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
- }
return error;
-} /* xfs_log_write */
-
+}
void
xfs_log_move_tail(xfs_mount_t *mp,
@@ -1642,16 +1640,16 @@ xlog_print_tic_res(xfs_mount_t *mp, xlog_ticket_t *ticket)
* bytes have been written out.
*/
STATIC int
-xlog_write(xfs_mount_t * mp,
- xfs_log_iovec_t reg[],
- int nentries,
- xfs_log_ticket_t tic,
- xfs_lsn_t *start_lsn,
- xlog_in_core_t **commit_iclog,
- uint flags)
+xlog_write(
+ struct xfs_mount *mp,
+ struct xfs_log_iovec reg[],
+ int nentries,
+ struct xlog_ticket *ticket,
+ xfs_lsn_t *start_lsn,
+ struct xlog_in_core **commit_iclog,
+ uint flags)
{
xlog_t *log = mp->m_log;
- xlog_ticket_t *ticket = (xlog_ticket_t *)tic;
xlog_in_core_t *iclog = NULL; /* ptr to current in-core log */
xlog_op_header_t *logop_head; /* ptr to log operation header */
__psint_t ptr; /* copy address into data region */
@@ -1765,7 +1763,7 @@ xlog_write(xfs_mount_t * mp,
default:
xfs_fs_cmn_err(CE_WARN, mp,
"Bad XFS transaction clientid 0x%x in ticket 0x%p",
- logop_head->oh_clientid, tic);
+ logop_head->oh_clientid, ticket);
return XFS_ERROR(EIO);
}
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index 7074be9d13e..97a24c7795a 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -110,8 +110,6 @@ typedef struct xfs_log_iovec {
uint i_type; /* type of region */
} xfs_log_iovec_t;
-typedef void* xfs_log_ticket_t;
-
/*
* Structure used to pass callback function and the function's argument
* to the log manager.
@@ -126,10 +124,12 @@ typedef struct xfs_log_callback {
#ifdef __KERNEL__
/* Log manager interfaces */
struct xfs_mount;
+struct xlog_in_core;
struct xlog_ticket;
+
xfs_lsn_t xfs_log_done(struct xfs_mount *mp,
- xfs_log_ticket_t ticket,
- void **iclog,
+ struct xlog_ticket *ticket,
+ struct xlog_in_core **iclog,
uint flags);
int _xfs_log_force(struct xfs_mount *mp,
uint flags,
@@ -151,21 +151,21 @@ int xfs_log_mount_finish(struct xfs_mount *mp);
void xfs_log_move_tail(struct xfs_mount *mp,
xfs_lsn_t tail_lsn);
int xfs_log_notify(struct xfs_mount *mp,
- void *iclog,
+ struct xlog_in_core *iclog,
xfs_log_callback_t *callback_entry);
int xfs_log_release_iclog(struct xfs_mount *mp,
- void *iclog_hndl);
+ struct xlog_in_core *iclog);
int xfs_log_reserve(struct xfs_mount *mp,
int length,
int count,
- xfs_log_ticket_t *ticket,
+ struct xlog_ticket **ticket,
__uint8_t clientid,
uint flags,
uint t_type);
int xfs_log_write(struct xfs_mount *mp,
xfs_log_iovec_t region[],
int nentries,
- xfs_log_ticket_t ticket,
+ struct xlog_ticket *ticket,
xfs_lsn_t *start_lsn);
int xfs_log_unmount_write(struct xfs_mount *mp);
void xfs_log_unmount(struct xfs_mount *mp);
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 6afaaeb2950..e79b56b4bca 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -1097,13 +1097,15 @@ xfs_default_resblks(xfs_mount_t *mp)
__uint64_t resblks;
/*
- * We default to 5% or 1024 fsbs of space reserved, whichever is smaller.
- * This may drive us straight to ENOSPC on mount, but that implies
- * we were already there on the last unmount. Warn if this occurs.
+ * We default to 5% or 8192 fsbs of space reserved, whichever is
+ * smaller. This is intended to cover concurrent allocation
+ * transactions when we initially hit enospc. These each require a 4
+ * block reservation. Hence by default we cover roughly 2000 concurrent
+ * allocation reservations.
*/
resblks = mp->m_sb.sb_dblocks;
do_div(resblks, 20);
- resblks = min_t(__uint64_t, resblks, 1024);
+ resblks = min_t(__uint64_t, resblks, 8192);
return resblks;
}
@@ -1417,6 +1419,9 @@ xfs_mountfs(
* when at ENOSPC. This is needed for operations like create with
* attr, unwritten extent conversion at ENOSPC, etc. Data allocations
* are not allowed to use this reserved space.
+ *
+ * This may drive us straight to ENOSPC on mount, but that implies
+ * we were already there on the last unmount. Warn if this occurs.
*/
if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
resblks = xfs_default_resblks(mp);
@@ -1725,26 +1730,30 @@ xfs_mod_incore_sb_unlocked(
lcounter += rem;
}
} else { /* Taking blocks away */
-
lcounter += delta;
+ if (lcounter >= 0) {
+ mp->m_sb.sb_fdblocks = lcounter +
+ XFS_ALLOC_SET_ASIDE(mp);
+ return 0;
+ }
- /*
- * If were out of blocks, use any available reserved blocks if
- * were allowed to.
- */
+ /*
+ * We are out of blocks, use any available reserved
+ * blocks if were allowed to.
+ */
+ if (!rsvd)
+ return XFS_ERROR(ENOSPC);
- if (lcounter < 0) {
- if (rsvd) {
- lcounter = (long long)mp->m_resblks_avail + delta;
- if (lcounter < 0) {
- return XFS_ERROR(ENOSPC);
- }
- mp->m_resblks_avail = lcounter;
- return 0;
- } else { /* not reserved */
- return XFS_ERROR(ENOSPC);
- }
+ lcounter = (long long)mp->m_resblks_avail + delta;
+ if (lcounter >= 0) {
+ mp->m_resblks_avail = lcounter;
+ return 0;
}
+ printk_once(KERN_WARNING
+ "Filesystem \"%s\": reserve blocks depleted! "
+ "Consider increasing reserve pool size.",
+ mp->m_fsname);
+ return XFS_ERROR(ENOSPC);
}
mp->m_sb.sb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp);
@@ -2052,6 +2061,26 @@ xfs_mount_log_sb(
return error;
}
+/*
+ * If the underlying (data/log/rt) device is readonly, there are some
+ * operations that cannot proceed.
+ */
+int
+xfs_dev_is_read_only(
+ struct xfs_mount *mp,
+ char *message)
+{
+ if (xfs_readonly_buftarg(mp->m_ddev_targp) ||
+ xfs_readonly_buftarg(mp->m_logdev_targp) ||
+ (mp->m_rtdev_targp && xfs_readonly_buftarg(mp->m_rtdev_targp))) {
+ cmn_err(CE_NOTE,
+ "XFS: %s required on read-only device.", message);
+ cmn_err(CE_NOTE,
+ "XFS: write access unavailable, cannot proceed.");
+ return EROFS;
+ }
+ return 0;
+}
#ifdef HAVE_PERCPU_SB
/*
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 14dafd60823..4fa0bc7b983 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -436,6 +436,8 @@ extern void xfs_freesb(xfs_mount_t *);
extern int xfs_fs_writable(xfs_mount_t *);
extern int xfs_sb_validate_fsb_count(struct xfs_sb *, __uint64_t);
+extern int xfs_dev_is_read_only(struct xfs_mount *, char *);
+
extern int xfs_dmops_get(struct xfs_mount *);
extern void xfs_dmops_put(struct xfs_mount *);
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index be942d4e332..f73e358bae8 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -796,7 +796,7 @@ _xfs_trans_commit(
int sync;
#define XFS_TRANS_LOGVEC_COUNT 16
xfs_log_iovec_t log_vector_fast[XFS_TRANS_LOGVEC_COUNT];
- void *commit_iclog;
+ struct xlog_in_core *commit_iclog;
int shutdown;
commit_lsn = -1;
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index c93e3a10285..79c8bab9dff 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -910,7 +910,7 @@ typedef struct xfs_trans {
unsigned int t_blk_res_used; /* # of resvd blocks used */
unsigned int t_rtx_res; /* # of rt extents resvd */
unsigned int t_rtx_res_used; /* # of resvd rt extents used */
- xfs_log_ticket_t t_ticket; /* log mgr ticket */
+ struct xlog_ticket *t_ticket; /* log mgr ticket */
xfs_lsn_t t_lsn; /* log seq num of start of
* transaction. */
xfs_lsn_t t_commit_lsn; /* log seq num of end of
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index 5ffd544434e..fb586360d1c 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -46,6 +46,65 @@ STATIC xfs_buf_t *xfs_trans_buf_item_match(xfs_trans_t *, xfs_buftarg_t *,
STATIC xfs_buf_t *xfs_trans_buf_item_match_all(xfs_trans_t *, xfs_buftarg_t *,
xfs_daddr_t, int);
+/*
+ * Add the locked buffer to the transaction.
+ *
+ * The buffer must be locked, and it cannot be associated with any
+ * transaction.
+ *
+ * If the buffer does not yet have a buf log item associated with it,
+ * then allocate one for it. Then add the buf item to the transaction.
+ */
+STATIC void
+_xfs_trans_bjoin(
+ struct xfs_trans *tp,
+ struct xfs_buf *bp,
+ int reset_recur)
+{
+ struct xfs_buf_log_item *bip;
+
+ ASSERT(XFS_BUF_ISBUSY(bp));
+ ASSERT(XFS_BUF_FSPRIVATE2(bp, void *) == NULL);
+
+ /*
+ * The xfs_buf_log_item pointer is stored in b_fsprivate. If
+ * it doesn't have one yet, then allocate one and initialize it.
+ * The checks to see if one is there are in xfs_buf_item_init().
+ */
+ xfs_buf_item_init(bp, tp->t_mountp);
+ bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
+ ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
+ ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL));
+ ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
+ if (reset_recur)
+ bip->bli_recur = 0;
+
+ /*
+ * Take a reference for this transaction on the buf item.
+ */
+ atomic_inc(&bip->bli_refcount);
+
+ /*
+ * Get a log_item_desc to point at the new item.
+ */
+ (void) xfs_trans_add_item(tp, (xfs_log_item_t *)bip);
+
+ /*
+ * Initialize b_fsprivate2 so we can find it with incore_match()
+ * in xfs_trans_get_buf() and friends above.
+ */
+ XFS_BUF_SET_FSPRIVATE2(bp, tp);
+
+}
+
+void
+xfs_trans_bjoin(
+ struct xfs_trans *tp,
+ struct xfs_buf *bp)
+{
+ _xfs_trans_bjoin(tp, bp, 0);
+ trace_xfs_trans_bjoin(bp->b_fspriv);
+}
/*
* Get and lock the buffer for the caller if it is not already
@@ -132,40 +191,8 @@ xfs_trans_get_buf(xfs_trans_t *tp,
ASSERT(!XFS_BUF_GETERROR(bp));
- /*
- * The xfs_buf_log_item pointer is stored in b_fsprivate. If
- * it doesn't have one yet, then allocate one and initialize it.
- * The checks to see if one is there are in xfs_buf_item_init().
- */
- xfs_buf_item_init(bp, tp->t_mountp);
-
- /*
- * Set the recursion count for the buffer within this transaction
- * to 0.
- */
- bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);
- ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
- ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL));
- ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
- bip->bli_recur = 0;
-
- /*
- * Take a reference for this transaction on the buf item.
- */
- atomic_inc(&bip->bli_refcount);
-
- /*
- * Get a log_item_desc to point at the new item.
- */
- (void) xfs_trans_add_item(tp, (xfs_log_item_t*)bip);
-
- /*
- * Initialize b_fsprivate2 so we can find it with incore_match()
- * above.
- */
- XFS_BUF_SET_FSPRIVATE2(bp, tp);
-
- trace_xfs_trans_get_buf(bip);
+ _xfs_trans_bjoin(tp, bp, 1);
+ trace_xfs_trans_get_buf(bp->b_fspriv);
return (bp);
}
@@ -210,44 +237,11 @@ xfs_trans_getsb(xfs_trans_t *tp,
}
bp = xfs_getsb(mp, flags);
- if (bp == NULL) {
+ if (bp == NULL)
return NULL;
- }
-
- /*
- * The xfs_buf_log_item pointer is stored in b_fsprivate. If
- * it doesn't have one yet, then allocate one and initialize it.
- * The checks to see if one is there are in xfs_buf_item_init().
- */
- xfs_buf_item_init(bp, mp);
-
- /*
- * Set the recursion count for the buffer within this transaction
- * to 0.
- */
- bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);
- ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
- ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL));
- ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
- bip->bli_recur = 0;
-
- /*
- * Take a reference for this transaction on the buf item.
- */
- atomic_inc(&bip->bli_refcount);
-
- /*
- * Get a log_item_desc to point at the new item.
- */
- (void) xfs_trans_add_item(tp, (xfs_log_item_t*)bip);
-
- /*
- * Initialize b_fsprivate2 so we can find it with incore_match()
- * above.
- */
- XFS_BUF_SET_FSPRIVATE2(bp, tp);
- trace_xfs_trans_getsb(bip);
+ _xfs_trans_bjoin(tp, bp, 1);
+ trace_xfs_trans_getsb(bp->b_fspriv);
return (bp);
}
@@ -425,40 +419,9 @@ xfs_trans_read_buf(
if (XFS_FORCED_SHUTDOWN(mp))
goto shutdown_abort;
- /*
- * The xfs_buf_log_item pointer is stored in b_fsprivate. If
- * it doesn't have one yet, then allocate one and initialize it.
- * The checks to see if one is there are in xfs_buf_item_init().
- */
- xfs_buf_item_init(bp, tp->t_mountp);
+ _xfs_trans_bjoin(tp, bp, 1);
+ trace_xfs_trans_read_buf(bp->b_fspriv);
- /*
- * Set the recursion count for the buffer within this transaction
- * to 0.
- */
- bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t*);
- ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
- ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL));
- ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
- bip->bli_recur = 0;
-
- /*
- * Take a reference for this transaction on the buf item.
- */
- atomic_inc(&bip->bli_refcount);
-
- /*
- * Get a log_item_desc to point at the new item.
- */
- (void) xfs_trans_add_item(tp, (xfs_log_item_t*)bip);
-
- /*
- * Initialize b_fsprivate2 so we can find it with incore_match()
- * above.
- */
- XFS_BUF_SET_FSPRIVATE2(bp, tp);
-
- trace_xfs_trans_read_buf(bip);
*bpp = bp;
return 0;
@@ -623,53 +586,6 @@ xfs_trans_brelse(xfs_trans_t *tp,
}
/*
- * Add the locked buffer to the transaction.
- * The buffer must be locked, and it cannot be associated with any
- * transaction.
- *
- * If the buffer does not yet have a buf log item associated with it,
- * then allocate one for it. Then add the buf item to the transaction.
- */
-void
-xfs_trans_bjoin(xfs_trans_t *tp,
- xfs_buf_t *bp)
-{
- xfs_buf_log_item_t *bip;
-
- ASSERT(XFS_BUF_ISBUSY(bp));
- ASSERT(XFS_BUF_FSPRIVATE2(bp, void *) == NULL);
-
- /*
- * The xfs_buf_log_item pointer is stored in b_fsprivate. If
- * it doesn't have one yet, then allocate one and initialize it.
- * The checks to see if one is there are in xfs_buf_item_init().
- */
- xfs_buf_item_init(bp, tp->t_mountp);
- bip = XFS_BUF_FSPRIVATE(bp, xfs_buf_log_item_t *);
- ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
- ASSERT(!(bip->bli_format.blf_flags & XFS_BLI_CANCEL));
- ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
-
- /*
- * Take a reference for this transaction on the buf item.
- */
- atomic_inc(&bip->bli_refcount);
-
- /*
- * Get a log_item_desc to point at the new item.
- */
- (void) xfs_trans_add_item(tp, (xfs_log_item_t *)bip);
-
- /*
- * Initialize b_fsprivate2 so we can find it with incore_match()
- * in xfs_trans_get_buf() and friends above.
- */
- XFS_BUF_SET_FSPRIVATE2(bp, tp);
-
- trace_xfs_trans_bjoin(bip);
-}
-
-/*
* Mark the buffer as not needing to be unlocked when the buf item's
* IOP_UNLOCK() routine is called. The buffer must already be locked
* and associated with the given transaction.
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index ddd2c5d1b85..9d376be0ea3 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -584,113 +584,6 @@ xfs_readlink(
}
/*
- * xfs_fsync
- *
- * This is called to sync the inode and its data out to disk. We need to hold
- * the I/O lock while flushing the data, and the inode lock while flushing the
- * inode. The inode lock CANNOT be held while flushing the data, so acquire
- * after we're done with that.
- */
-int
-xfs_fsync(
- xfs_inode_t *ip)
-{
- xfs_trans_t *tp;
- int error = 0;
- int log_flushed = 0;
-
- xfs_itrace_entry(ip);
-
- if (XFS_FORCED_SHUTDOWN(ip->i_mount))
- return XFS_ERROR(EIO);
-
- /*
- * We always need to make sure that the required inode state is safe on
- * disk. The inode might be clean but we still might need to force the
- * log because of committed transactions that haven't hit the disk yet.
- * Likewise, there could be unflushed non-transactional changes to the
- * inode core that have to go to disk and this requires us to issue
- * a synchronous transaction to capture these changes correctly.
- *
- * This code relies on the assumption that if the update_* fields
- * of the inode are clear and the inode is unpinned then it is clean
- * and no action is required.
- */
- xfs_ilock(ip, XFS_ILOCK_SHARED);
-
- if (!ip->i_update_core) {
- /*
- * Timestamps/size haven't changed since last inode flush or
- * inode transaction commit. That means either nothing got
- * written or a transaction committed which caught the updates.
- * If the latter happened and the transaction hasn't hit the
- * disk yet, the inode will be still be pinned. If it is,
- * force the log.
- */
- xfs_iunlock(ip, XFS_ILOCK_SHARED);
- if (xfs_ipincount(ip)) {
- if (ip->i_itemp->ili_last_lsn) {
- error = _xfs_log_force_lsn(ip->i_mount,
- ip->i_itemp->ili_last_lsn,
- XFS_LOG_SYNC, &log_flushed);
- } else {
- error = _xfs_log_force(ip->i_mount,
- XFS_LOG_SYNC, &log_flushed);
- }
- }
- } else {
- /*
- * Kick off a transaction to log the inode core to get the
- * updates. The sync transaction will also force the log.
- */
- xfs_iunlock(ip, XFS_ILOCK_SHARED);
- tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_FSYNC_TS);
- error = xfs_trans_reserve(tp, 0,
- XFS_FSYNC_TS_LOG_RES(ip->i_mount), 0, 0, 0);
- if (error) {
- xfs_trans_cancel(tp, 0);
- return error;
- }
- xfs_ilock(ip, XFS_ILOCK_EXCL);
-
- /*
- * Note - it's possible that we might have pushed ourselves out
- * of the way during trans_reserve which would flush the inode.
- * But there's no guarantee that the inode buffer has actually
- * gone out yet (it's delwri). Plus the buffer could be pinned
- * anyway if it's part of an inode in another recent
- * transaction. So we play it safe and fire off the
- * transaction anyway.
- */
- xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
- xfs_trans_ihold(tp, ip);
- xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
- xfs_trans_set_sync(tp);
- error = _xfs_trans_commit(tp, 0, &log_flushed);
-
- xfs_iunlock(ip, XFS_ILOCK_EXCL);
- }
-
- if (ip->i_mount->m_flags & XFS_MOUNT_BARRIER) {
- /*
- * If the log write didn't issue an ordered tag we need
- * to flush the disk cache for the data device now.
- */
- if (!log_flushed)
- xfs_blkdev_issue_flush(ip->i_mount->m_ddev_targp);
-
- /*
- * If this inode is on the RT dev we need to flush that
- * cache as well.
- */
- if (XFS_IS_REALTIME_INODE(ip))
- xfs_blkdev_issue_flush(ip->i_mount->m_rtdev_targp);
- }
-
- return error;
-}
-
-/*
* Flags for xfs_free_eofblocks
*/
#define XFS_FREE_EOF_TRYLOCK (1<<0)
diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h
index 774f40729ca..d8dfa8d0dad 100644
--- a/fs/xfs/xfs_vnodeops.h
+++ b/fs/xfs/xfs_vnodeops.h
@@ -21,7 +21,6 @@ int xfs_setattr(struct xfs_inode *ip, struct iattr *vap, int flags);
#define XFS_ATTR_NOACL 0x08 /* Don't call xfs_acl_chmod */
int xfs_readlink(struct xfs_inode *ip, char *link);
-int xfs_fsync(struct xfs_inode *ip);
int xfs_release(struct xfs_inode *ip);
int xfs_inactive(struct xfs_inode *ip);
int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name,
@@ -50,18 +49,6 @@ int xfs_attr_set(struct xfs_inode *dp, const unsigned char *name,
int xfs_attr_remove(struct xfs_inode *dp, const unsigned char *name, int flags);
int xfs_attr_list(struct xfs_inode *dp, char *buffer, int bufsize,
int flags, struct attrlist_cursor_kern *cursor);
-ssize_t xfs_read(struct xfs_inode *ip, struct kiocb *iocb,
- const struct iovec *iovp, unsigned int segs,
- loff_t *offset, int ioflags);
-ssize_t xfs_splice_read(struct xfs_inode *ip, struct file *infilp,
- loff_t *ppos, struct pipe_inode_info *pipe, size_t count,
- int flags, int ioflags);
-ssize_t xfs_splice_write(struct xfs_inode *ip,
- struct pipe_inode_info *pipe, struct file *outfilp,
- loff_t *ppos, size_t count, int flags, int ioflags);
-ssize_t xfs_write(struct xfs_inode *xip, struct kiocb *iocb,
- const struct iovec *iovp, unsigned int nsegs,
- loff_t *offset, int ioflags);
int xfs_bmap(struct xfs_inode *ip, xfs_off_t offset, ssize_t count,
int flags, struct xfs_iomap *iomapp, int *niomaps);
void xfs_tosspages(struct xfs_inode *inode, xfs_off_t first,
@@ -72,4 +59,6 @@ int xfs_flush_pages(struct xfs_inode *ip, xfs_off_t first,
xfs_off_t last, uint64_t flags, int fiopt);
int xfs_wait_on_pages(struct xfs_inode *ip, xfs_off_t first, xfs_off_t last);
+int xfs_zero_eof(struct xfs_inode *, xfs_off_t, xfs_fsize_t);
+
#endif /* _XFS_VNODEOPS_H */
diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
index 485eeb6c4ef..979c6a57f2f 100644
--- a/include/asm-generic/gpio.h
+++ b/include/asm-generic/gpio.h
@@ -136,6 +136,32 @@ extern int __gpio_cansleep(unsigned gpio);
extern int __gpio_to_irq(unsigned gpio);
+#define GPIOF_DIR_OUT (0 << 0)
+#define GPIOF_DIR_IN (1 << 0)
+
+#define GPIOF_INIT_LOW (0 << 1)
+#define GPIOF_INIT_HIGH (1 << 1)
+
+#define GPIOF_IN (GPIOF_DIR_IN)
+#define GPIOF_OUT_INIT_LOW (GPIOF_DIR_OUT | GPIOF_INIT_LOW)
+#define GPIOF_OUT_INIT_HIGH (GPIOF_DIR_OUT | GPIOF_INIT_HIGH)
+
+/**
+ * struct gpio - a structure describing a GPIO with configuration
+ * @gpio: the GPIO number
+ * @flags: GPIO configuration as specified by GPIOF_*
+ * @label: a literal description string of this GPIO
+ */
+struct gpio {
+ unsigned gpio;
+ unsigned long flags;
+ const char *label;
+};
+
+extern int gpio_request_one(unsigned gpio, unsigned long flags, const char *label);
+extern int gpio_request_array(struct gpio *array, size_t num);
+extern void gpio_free_array(struct gpio *array, size_t num);
+
#ifdef CONFIG_GPIO_SYSFS
/*
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 89c6249fc56..c809e286d21 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -74,6 +74,7 @@ struct coredump_params {
struct pt_regs *regs;
struct file *file;
unsigned long limit;
+ unsigned long mm_flags;
};
/*
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 25b8b2f33ae..b7938987923 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -16,11 +16,13 @@
*/
#include <asm/bitops.h>
-#define for_each_bit(bit, addr, size) \
+#define for_each_set_bit(bit, addr, size) \
for ((bit) = find_first_bit((addr), (size)); \
(bit) < (size); \
(bit) = find_next_bit((addr), (size), (bit) + 1))
+/* Temporary */
+#define for_each_bit(bit, addr, size) for_each_set_bit(bit, addr, size)
static __inline__ int get_bitmask_order(unsigned int count)
{
diff --git a/include/linux/btree-128.h b/include/linux/btree-128.h
new file mode 100644
index 00000000000..0b3414c4c92
--- /dev/null
+++ b/include/linux/btree-128.h
@@ -0,0 +1,109 @@
+extern struct btree_geo btree_geo128;
+
+struct btree_head128 { struct btree_head h; };
+
+static inline void btree_init_mempool128(struct btree_head128 *head,
+ mempool_t *mempool)
+{
+ btree_init_mempool(&head->h, mempool);
+}
+
+static inline int btree_init128(struct btree_head128 *head)
+{
+ return btree_init(&head->h);
+}
+
+static inline void btree_destroy128(struct btree_head128 *head)
+{
+ btree_destroy(&head->h);
+}
+
+static inline void *btree_lookup128(struct btree_head128 *head, u64 k1, u64 k2)
+{
+ u64 key[2] = {k1, k2};
+ return btree_lookup(&head->h, &btree_geo128, (unsigned long *)&key);
+}
+
+static inline void *btree_get_prev128(struct btree_head128 *head,
+ u64 *k1, u64 *k2)
+{
+ u64 key[2] = {*k1, *k2};
+ void *val;
+
+ val = btree_get_prev(&head->h, &btree_geo128,
+ (unsigned long *)&key);
+ *k1 = key[0];
+ *k2 = key[1];
+ return val;
+}
+
+static inline int btree_insert128(struct btree_head128 *head, u64 k1, u64 k2,
+ void *val, gfp_t gfp)
+{
+ u64 key[2] = {k1, k2};
+ return btree_insert(&head->h, &btree_geo128,
+ (unsigned long *)&key, val, gfp);
+}
+
+static inline int btree_update128(struct btree_head128 *head, u64 k1, u64 k2,
+ void *val)
+{
+ u64 key[2] = {k1, k2};
+ return btree_update(&head->h, &btree_geo128,
+ (unsigned long *)&key, val);
+}
+
+static inline void *btree_remove128(struct btree_head128 *head, u64 k1, u64 k2)
+{
+ u64 key[2] = {k1, k2};
+ return btree_remove(&head->h, &btree_geo128, (unsigned long *)&key);
+}
+
+static inline void *btree_last128(struct btree_head128 *head, u64 *k1, u64 *k2)
+{
+ u64 key[2];
+ void *val;
+
+ val = btree_last(&head->h, &btree_geo128, (unsigned long *)&key[0]);
+ if (val) {
+ *k1 = key[0];
+ *k2 = key[1];
+ }
+
+ return val;
+}
+
+static inline int btree_merge128(struct btree_head128 *target,
+ struct btree_head128 *victim,
+ gfp_t gfp)
+{
+ return btree_merge(&target->h, &victim->h, &btree_geo128, gfp);
+}
+
+void visitor128(void *elem, unsigned long opaque, unsigned long *__key,
+ size_t index, void *__func);
+
+typedef void (*visitor128_t)(void *elem, unsigned long opaque,
+ u64 key1, u64 key2, size_t index);
+
+static inline size_t btree_visitor128(struct btree_head128 *head,
+ unsigned long opaque,
+ visitor128_t func2)
+{
+ return btree_visitor(&head->h, &btree_geo128, opaque,
+ visitor128, func2);
+}
+
+static inline size_t btree_grim_visitor128(struct btree_head128 *head,
+ unsigned long opaque,
+ visitor128_t func2)
+{
+ return btree_grim_visitor(&head->h, &btree_geo128, opaque,
+ visitor128, func2);
+}
+
+#define btree_for_each_safe128(head, k1, k2, val) \
+ for (val = btree_last128(head, &k1, &k2); \
+ val; \
+ val = btree_get_prev128(head, &k1, &k2))
+
diff --git a/include/linux/btree-type.h b/include/linux/btree-type.h
new file mode 100644
index 00000000000..9a1147ef856
--- /dev/null
+++ b/include/linux/btree-type.h
@@ -0,0 +1,147 @@
+#define __BTREE_TP(pfx, type, sfx) pfx ## type ## sfx
+#define _BTREE_TP(pfx, type, sfx) __BTREE_TP(pfx, type, sfx)
+#define BTREE_TP(pfx) _BTREE_TP(pfx, BTREE_TYPE_SUFFIX,)
+#define BTREE_FN(name) BTREE_TP(btree_ ## name)
+#define BTREE_TYPE_HEAD BTREE_TP(struct btree_head)
+#define VISITOR_FN BTREE_TP(visitor)
+#define VISITOR_FN_T _BTREE_TP(visitor, BTREE_TYPE_SUFFIX, _t)
+
+BTREE_TYPE_HEAD {
+ struct btree_head h;
+};
+
+static inline void BTREE_FN(init_mempool)(BTREE_TYPE_HEAD *head,
+ mempool_t *mempool)
+{
+ btree_init_mempool(&head->h, mempool);
+}
+
+static inline int BTREE_FN(init)(BTREE_TYPE_HEAD *head)
+{
+ return btree_init(&head->h);
+}
+
+static inline void BTREE_FN(destroy)(BTREE_TYPE_HEAD *head)
+{
+ btree_destroy(&head->h);
+}
+
+static inline int BTREE_FN(merge)(BTREE_TYPE_HEAD *target,
+ BTREE_TYPE_HEAD *victim,
+ gfp_t gfp)
+{
+ return btree_merge(&target->h, &victim->h, BTREE_TYPE_GEO, gfp);
+}
+
+#if (BITS_PER_LONG > BTREE_TYPE_BITS)
+static inline void *BTREE_FN(lookup)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE key)
+{
+ unsigned long _key = key;
+ return btree_lookup(&head->h, BTREE_TYPE_GEO, &_key);
+}
+
+static inline int BTREE_FN(insert)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE key,
+ void *val, gfp_t gfp)
+{
+ unsigned long _key = key;
+ return btree_insert(&head->h, BTREE_TYPE_GEO, &_key, val, gfp);
+}
+
+static inline int BTREE_FN(update)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE key,
+ void *val)
+{
+ unsigned long _key = key;
+ return btree_update(&head->h, BTREE_TYPE_GEO, &_key, val);
+}
+
+static inline void *BTREE_FN(remove)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE key)
+{
+ unsigned long _key = key;
+ return btree_remove(&head->h, BTREE_TYPE_GEO, &_key);
+}
+
+static inline void *BTREE_FN(last)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE *key)
+{
+ unsigned long _key;
+ void *val = btree_last(&head->h, BTREE_TYPE_GEO, &_key);
+ if (val)
+ *key = _key;
+ return val;
+}
+
+static inline void *BTREE_FN(get_prev)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE *key)
+{
+ unsigned long _key = *key;
+ void *val = btree_get_prev(&head->h, BTREE_TYPE_GEO, &_key);
+ if (val)
+ *key = _key;
+ return val;
+}
+#else
+static inline void *BTREE_FN(lookup)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE key)
+{
+ return btree_lookup(&head->h, BTREE_TYPE_GEO, (unsigned long *)&key);
+}
+
+static inline int BTREE_FN(insert)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE key,
+ void *val, gfp_t gfp)
+{
+ return btree_insert(&head->h, BTREE_TYPE_GEO, (unsigned long *)&key,
+ val, gfp);
+}
+
+static inline int BTREE_FN(update)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE key,
+ void *val)
+{
+ return btree_update(&head->h, BTREE_TYPE_GEO, (unsigned long *)&key, val);
+}
+
+static inline void *BTREE_FN(remove)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE key)
+{
+ return btree_remove(&head->h, BTREE_TYPE_GEO, (unsigned long *)&key);
+}
+
+static inline void *BTREE_FN(last)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE *key)
+{
+ return btree_last(&head->h, BTREE_TYPE_GEO, (unsigned long *)key);
+}
+
+static inline void *BTREE_FN(get_prev)(BTREE_TYPE_HEAD *head, BTREE_KEYTYPE *key)
+{
+ return btree_get_prev(&head->h, BTREE_TYPE_GEO, (unsigned long *)key);
+}
+#endif
+
+void VISITOR_FN(void *elem, unsigned long opaque, unsigned long *key,
+ size_t index, void *__func);
+
+typedef void (*VISITOR_FN_T)(void *elem, unsigned long opaque,
+ BTREE_KEYTYPE key, size_t index);
+
+static inline size_t BTREE_FN(visitor)(BTREE_TYPE_HEAD *head,
+ unsigned long opaque,
+ VISITOR_FN_T func2)
+{
+ return btree_visitor(&head->h, BTREE_TYPE_GEO, opaque,
+ visitorl, func2);
+}
+
+static inline size_t BTREE_FN(grim_visitor)(BTREE_TYPE_HEAD *head,
+ unsigned long opaque,
+ VISITOR_FN_T func2)
+{
+ return btree_grim_visitor(&head->h, BTREE_TYPE_GEO, opaque,
+ visitorl, func2);
+}
+
+#undef VISITOR_FN
+#undef VISITOR_FN_T
+#undef __BTREE_TP
+#undef _BTREE_TP
+#undef BTREE_TP
+#undef BTREE_FN
+#undef BTREE_TYPE_HEAD
+#undef BTREE_TYPE_SUFFIX
+#undef BTREE_TYPE_GEO
+#undef BTREE_KEYTYPE
+#undef BTREE_TYPE_BITS
diff --git a/include/linux/btree.h b/include/linux/btree.h
new file mode 100644
index 00000000000..65b5bb05832
--- /dev/null
+++ b/include/linux/btree.h
@@ -0,0 +1,243 @@
+#ifndef BTREE_H
+#define BTREE_H
+
+#include <linux/kernel.h>
+#include <linux/mempool.h>
+
+/**
+ * DOC: B+Tree basics
+ *
+ * A B+Tree is a data structure for looking up arbitrary (currently allowing
+ * unsigned long, u32, u64 and 2 * u64) keys into pointers. The data structure
+ * is described at http://en.wikipedia.org/wiki/B-tree, we currently do not
+ * use binary search to find the key on lookups.
+ *
+ * Each B+Tree consists of a head, that contains bookkeeping information and
+ * a variable number (starting with zero) nodes. Each node contains the keys
+ * and pointers to sub-nodes, or, for leaf nodes, the keys and values for the
+ * tree entries.
+ *
+ * Each node in this implementation has the following layout:
+ * [key1, key2, ..., keyN] [val1, val2, ..., valN]
+ *
+ * Each key here is an array of unsigned longs, geo->no_longs in total. The
+ * number of keys and values (N) is geo->no_pairs.
+ */
+
+/**
+ * struct btree_head - btree head
+ *
+ * @node: the first node in the tree
+ * @mempool: mempool used for node allocations
+ * @height: current of the tree
+ */
+struct btree_head {
+ unsigned long *node;
+ mempool_t *mempool;
+ int height;
+};
+
+/* btree geometry */
+struct btree_geo;
+
+/**
+ * btree_alloc - allocate function for the mempool
+ * @gfp_mask: gfp mask for the allocation
+ * @pool_data: unused
+ */
+void *btree_alloc(gfp_t gfp_mask, void *pool_data);
+
+/**
+ * btree_free - free function for the mempool
+ * @element: the element to free
+ * @pool_data: unused
+ */
+void btree_free(void *element, void *pool_data);
+
+/**
+ * btree_init_mempool - initialise a btree with given mempool
+ *
+ * @head: the btree head to initialise
+ * @mempool: the mempool to use
+ *
+ * When this function is used, there is no need to destroy
+ * the mempool.
+ */
+void btree_init_mempool(struct btree_head *head, mempool_t *mempool);
+
+/**
+ * btree_init - initialise a btree
+ *
+ * @head: the btree head to initialise
+ *
+ * This function allocates the memory pool that the
+ * btree needs. Returns zero or a negative error code
+ * (-%ENOMEM) when memory allocation fails.
+ *
+ */
+int __must_check btree_init(struct btree_head *head);
+
+/**
+ * btree_destroy - destroy mempool
+ *
+ * @head: the btree head to destroy
+ *
+ * This function destroys the internal memory pool, use only
+ * when using btree_init(), not with btree_init_mempool().
+ */
+void btree_destroy(struct btree_head *head);
+
+/**
+ * btree_lookup - look up a key in the btree
+ *
+ * @head: the btree to look in
+ * @geo: the btree geometry
+ * @key: the key to look up
+ *
+ * This function returns the value for the given key, or %NULL.
+ */
+void *btree_lookup(struct btree_head *head, struct btree_geo *geo,
+ unsigned long *key);
+
+/**
+ * btree_insert - insert an entry into the btree
+ *
+ * @head: the btree to add to
+ * @geo: the btree geometry
+ * @key: the key to add (must not already be present)
+ * @val: the value to add (must not be %NULL)
+ * @gfp: allocation flags for node allocations
+ *
+ * This function returns 0 if the item could be added, or an
+ * error code if it failed (may fail due to memory pressure).
+ */
+int __must_check btree_insert(struct btree_head *head, struct btree_geo *geo,
+ unsigned long *key, void *val, gfp_t gfp);
+/**
+ * btree_update - update an entry in the btree
+ *
+ * @head: the btree to update
+ * @geo: the btree geometry
+ * @key: the key to update
+ * @val: the value to change it to (must not be %NULL)
+ *
+ * This function returns 0 if the update was successful, or
+ * -%ENOENT if the key could not be found.
+ */
+int btree_update(struct btree_head *head, struct btree_geo *geo,
+ unsigned long *key, void *val);
+/**
+ * btree_remove - remove an entry from the btree
+ *
+ * @head: the btree to update
+ * @geo: the btree geometry
+ * @key: the key to remove
+ *
+ * This function returns the removed entry, or %NULL if the key
+ * could not be found.
+ */
+void *btree_remove(struct btree_head *head, struct btree_geo *geo,
+ unsigned long *key);
+
+/**
+ * btree_merge - merge two btrees
+ *
+ * @target: the tree that gets all the entries
+ * @victim: the tree that gets merged into @target
+ * @geo: the btree geometry
+ * @gfp: allocation flags
+ *
+ * The two trees @target and @victim may not contain the same keys,
+ * that is a bug and triggers a BUG(). This function returns zero
+ * if the trees were merged successfully, and may return a failure
+ * when memory allocation fails, in which case both trees might have
+ * been partially merged, i.e. some entries have been moved from
+ * @victim to @target.
+ */
+int btree_merge(struct btree_head *target, struct btree_head *victim,
+ struct btree_geo *geo, gfp_t gfp);
+
+/**
+ * btree_last - get last entry in btree
+ *
+ * @head: btree head
+ * @geo: btree geometry
+ * @key: last key
+ *
+ * Returns the last entry in the btree, and sets @key to the key
+ * of that entry; returns NULL if the tree is empty, in that case
+ * key is not changed.
+ */
+void *btree_last(struct btree_head *head, struct btree_geo *geo,
+ unsigned long *key);
+
+/**
+ * btree_get_prev - get previous entry
+ *
+ * @head: btree head
+ * @geo: btree geometry
+ * @key: pointer to key
+ *
+ * The function returns the next item right before the value pointed to by
+ * @key, and updates @key with its key, or returns %NULL when there is no
+ * entry with a key smaller than the given key.
+ */
+void *btree_get_prev(struct btree_head *head, struct btree_geo *geo,
+ unsigned long *key);
+
+
+/* internal use, use btree_visitor{l,32,64,128} */
+size_t btree_visitor(struct btree_head *head, struct btree_geo *geo,
+ unsigned long opaque,
+ void (*func)(void *elem, unsigned long opaque,
+ unsigned long *key, size_t index,
+ void *func2),
+ void *func2);
+
+/* internal use, use btree_grim_visitor{l,32,64,128} */
+size_t btree_grim_visitor(struct btree_head *head, struct btree_geo *geo,
+ unsigned long opaque,
+ void (*func)(void *elem, unsigned long opaque,
+ unsigned long *key,
+ size_t index, void *func2),
+ void *func2);
+
+
+#include <linux/btree-128.h>
+
+extern struct btree_geo btree_geo32;
+#define BTREE_TYPE_SUFFIX l
+#define BTREE_TYPE_BITS BITS_PER_LONG
+#define BTREE_TYPE_GEO &btree_geo32
+#define BTREE_KEYTYPE unsigned long
+#include <linux/btree-type.h>
+
+#define btree_for_each_safel(head, key, val) \
+ for (val = btree_lastl(head, &key); \
+ val; \
+ val = btree_get_prevl(head, &key))
+
+#define BTREE_TYPE_SUFFIX 32
+#define BTREE_TYPE_BITS 32
+#define BTREE_TYPE_GEO &btree_geo32
+#define BTREE_KEYTYPE u32
+#include <linux/btree-type.h>
+
+#define btree_for_each_safe32(head, key, val) \
+ for (val = btree_last32(head, &key); \
+ val; \
+ val = btree_get_prev32(head, &key))
+
+extern struct btree_geo btree_geo64;
+#define BTREE_TYPE_SUFFIX 64
+#define BTREE_TYPE_BITS 64
+#define BTREE_TYPE_GEO &btree_geo64
+#define BTREE_KEYTYPE u64
+#include <linux/btree-type.h>
+
+#define btree_for_each_safe64(head, key, val) \
+ for (val = btree_last64(head, &key); \
+ val; \
+ val = btree_get_prev64(head, &key))
+
+#endif
diff --git a/include/linux/coredump.h b/include/linux/coredump.h
new file mode 100644
index 00000000000..b3c91d7cede
--- /dev/null
+++ b/include/linux/coredump.h
@@ -0,0 +1,41 @@
+#ifndef _LINUX_COREDUMP_H
+#define _LINUX_COREDUMP_H
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+
+/*
+ * These are the only things you should do on a core-file: use only these
+ * functions to write out all the necessary info.
+ */
+static inline int dump_write(struct file *file, const void *addr, int nr)
+{
+ return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+}
+
+static inline int dump_seek(struct file *file, loff_t off)
+{
+ if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
+ if (file->f_op->llseek(file, off, SEEK_CUR) < 0)
+ return 0;
+ } else {
+ char *buf = (char *)get_zeroed_page(GFP_KERNEL);
+
+ if (!buf)
+ return 0;
+ while (off > 0) {
+ unsigned long n = off;
+
+ if (n > PAGE_SIZE)
+ n = PAGE_SIZE;
+ if (!dump_write(file, buf, n))
+ return 0;
+ off -= n;
+ }
+ free_page((unsigned long)buf);
+ }
+ return 1;
+}
+
+#endif /* _LINUX_COREDUMP_H */
diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h
index dbcee7647d9..bae6fe24d1f 100644
--- a/include/linux/cpumask.h
+++ b/include/linux/cpumask.h
@@ -90,10 +90,10 @@ extern const struct cpumask *const cpu_active_mask;
#define cpu_present(cpu) cpumask_test_cpu((cpu), cpu_present_mask)
#define cpu_active(cpu) cpumask_test_cpu((cpu), cpu_active_mask)
#else
-#define num_online_cpus() 1
-#define num_possible_cpus() 1
-#define num_present_cpus() 1
-#define num_active_cpus() 1
+#define num_online_cpus() 1U
+#define num_possible_cpus() 1U
+#define num_present_cpus() 1U
+#define num_active_cpus() 1U
#define cpu_online(cpu) ((cpu) == 0)
#define cpu_possible(cpu) ((cpu) == 0)
#define cpu_present(cpu) ((cpu) == 0)
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h
index d4c9c0b88ad..1381cd97b4e 100644
--- a/include/linux/device-mapper.h
+++ b/include/linux/device-mapper.h
@@ -118,10 +118,9 @@ struct dm_dev {
/*
* Constructors should call these functions to ensure destination devices
* are opened/closed correctly.
- * FIXME: too many arguments.
*/
-int dm_get_device(struct dm_target *ti, const char *path, sector_t start,
- sector_t len, fmode_t mode, struct dm_dev **result);
+int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
+ struct dm_dev **result);
void dm_put_device(struct dm_target *ti, struct dm_dev *d);
/*
diff --git a/include/linux/device.h b/include/linux/device.h
index b30527db3ac..182192892d4 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -106,7 +106,7 @@ extern int bus_unregister_notifier(struct bus_type *bus,
/* All 4 notifers below get called with the target struct device *
* as an argument. Note that those functions are likely to be called
- * with the device semaphore held in the core, so be careful.
+ * with the device lock held in the core, so be careful.
*/
#define BUS_NOTIFY_ADD_DEVICE 0x00000001 /* device added */
#define BUS_NOTIFY_DEL_DEVICE 0x00000002 /* device removed */
@@ -251,8 +251,10 @@ extern struct device *class_find_device(struct class *class,
struct class_attribute {
struct attribute attr;
- ssize_t (*show)(struct class *class, char *buf);
- ssize_t (*store)(struct class *class, const char *buf, size_t count);
+ ssize_t (*show)(struct class *class, struct class_attribute *attr,
+ char *buf);
+ ssize_t (*store)(struct class *class, struct class_attribute *attr,
+ const char *buf, size_t count);
};
#define CLASS_ATTR(_name, _mode, _show, _store) \
@@ -263,6 +265,23 @@ extern int __must_check class_create_file(struct class *class,
extern void class_remove_file(struct class *class,
const struct class_attribute *attr);
+/* Simple class attribute that is just a static string */
+
+struct class_attribute_string {
+ struct class_attribute attr;
+ char *str;
+};
+
+/* Currently read-only only */
+#define _CLASS_ATTR_STRING(_name, _mode, _str) \
+ { __ATTR(_name, _mode, show_class_attr_string, NULL), _str }
+#define CLASS_ATTR_STRING(_name, _mode, _str) \
+ struct class_attribute_string class_attr_##_name = \
+ _CLASS_ATTR_STRING(_name, _mode, _str)
+
+extern ssize_t show_class_attr_string(struct class *class, struct class_attribute *attr,
+ char *buf);
+
struct class_interface {
struct list_head node;
struct class *class;
@@ -489,6 +508,21 @@ static inline bool device_async_suspend_enabled(struct device *dev)
return !!dev->power.async_suspend;
}
+static inline void device_lock(struct device *dev)
+{
+ down(&dev->sem);
+}
+
+static inline int device_trylock(struct device *dev)
+{
+ return down_trylock(&dev->sem);
+}
+
+static inline void device_unlock(struct device *dev)
+{
+ up(&dev->sem);
+}
+
void driver_init(void);
/*
diff --git a/include/linux/dm-io.h b/include/linux/dm-io.h
index b6bf17ee2f6..5c9186b93ff 100644
--- a/include/linux/dm-io.h
+++ b/include/linux/dm-io.h
@@ -37,14 +37,14 @@ enum dm_io_mem_type {
struct dm_io_memory {
enum dm_io_mem_type type;
+ unsigned offset;
+
union {
struct page_list *pl;
struct bio_vec *bvec;
void *vma;
void *addr;
} ptr;
-
- unsigned offset;
};
struct dm_io_notify {
diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h
index aa95508d2f9..2c445e11379 100644
--- a/include/linux/dm-ioctl.h
+++ b/include/linux/dm-ioctl.h
@@ -266,9 +266,9 @@ enum {
#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
#define DM_VERSION_MAJOR 4
-#define DM_VERSION_MINOR 16
+#define DM_VERSION_MINOR 17
#define DM_VERSION_PATCHLEVEL 0
-#define DM_VERSION_EXTRA "-ioctl (2009-11-05)"
+#define DM_VERSION_EXTRA "-ioctl (2010-03-05)"
/* Status bits */
#define DM_READONLY_FLAG (1 << 0) /* In/Out */
@@ -316,4 +316,9 @@ enum {
*/
#define DM_QUERY_INACTIVE_TABLE_FLAG (1 << 12) /* In */
+/*
+ * If set, a uevent was generated for which the caller may need to wait.
+ */
+#define DM_UEVENT_GENERATED_FLAG (1 << 13) /* Out */
+
#endif /* _LINUX_DM_IOCTL_H */
diff --git a/include/linux/elf.h b/include/linux/elf.h
index ad990c5f63f..59785841805 100644
--- a/include/linux/elf.h
+++ b/include/linux/elf.h
@@ -50,6 +50,28 @@ typedef __s64 Elf64_Sxword;
#define PT_GNU_STACK (PT_LOOS + 0x474e551)
+/*
+ * Extended Numbering
+ *
+ * If the real number of program header table entries is larger than
+ * or equal to PN_XNUM(0xffff), it is set to sh_info field of the
+ * section header at index 0, and PN_XNUM is set to e_phnum
+ * field. Otherwise, the section header at index 0 is zero
+ * initialized, if it exists.
+ *
+ * Specifications are available in:
+ *
+ * - Sun microsystems: Linker and Libraries.
+ * Part No: 817-1984-17, September 2008.
+ * URL: http://docs.sun.com/app/docs/doc/817-1984
+ *
+ * - System V ABI AMD64 Architecture Processor Supplement
+ * Draft Version 0.99.,
+ * May 11, 2009.
+ * URL: http://www.x86-64.org/
+ */
+#define PN_XNUM 0xffff
+
/* These constants define the different elf file types */
#define ET_NONE 0
#define ET_REL 1
@@ -286,7 +308,7 @@ typedef struct elf64_phdr {
#define SHN_COMMON 0xfff2
#define SHN_HIRESERVE 0xffff
-typedef struct {
+typedef struct elf32_shdr {
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
@@ -394,16 +416,20 @@ typedef struct elf64_note {
extern Elf32_Dyn _DYNAMIC [];
#define elfhdr elf32_hdr
#define elf_phdr elf32_phdr
+#define elf_shdr elf32_shdr
#define elf_note elf32_note
#define elf_addr_t Elf32_Off
+#define Elf_Half Elf32_Half
#else
extern Elf64_Dyn _DYNAMIC [];
#define elfhdr elf64_hdr
#define elf_phdr elf64_phdr
+#define elf_shdr elf64_shdr
#define elf_note elf64_note
#define elf_addr_t Elf64_Off
+#define Elf_Half Elf64_Half
#endif
diff --git a/include/linux/elfcore.h b/include/linux/elfcore.h
index 00d6a68d042..e687bc3ba4d 100644
--- a/include/linux/elfcore.h
+++ b/include/linux/elfcore.h
@@ -8,6 +8,8 @@
#include <linux/user.h>
#endif
#include <linux/ptrace.h>
+#include <linux/elf.h>
+#include <linux/fs.h>
struct elf_siginfo
{
@@ -150,5 +152,20 @@ static inline int elf_core_copy_task_xfpregs(struct task_struct *t, elf_fpxregse
#endif /* __KERNEL__ */
+/*
+ * These functions parameterize elf_core_dump in fs/binfmt_elf.c to write out
+ * extra segments containing the gate DSO contents. Dumping its
+ * contents makes post-mortem fully interpretable later without matching up
+ * the same kernel and hardware config to see what PC values meant.
+ * Dumping its extra ELF program headers includes all the other information
+ * a debugger needs to easily find how the gate DSO was being used.
+ */
+extern Elf_Half elf_core_extra_phdrs(void);
+extern int
+elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
+ unsigned long limit);
+extern int
+elf_core_write_extra_data(struct file *file, size_t *size, unsigned long limit);
+extern size_t elf_core_extra_data_size(void);
#endif /* _LINUX_ELFCORE_H */
diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h
index dc12f416a49..a9cd507f8cd 100644
--- a/include/linux/exportfs.h
+++ b/include/linux/exportfs.h
@@ -96,6 +96,7 @@ struct fid {
* @fh_to_parent: find the implied object's parent and get a dentry for it
* @get_name: find the name for a given inode in a given directory
* @get_parent: find the parent of a given directory
+ * @commit_metadata: commit metadata changes to stable storage
*
* See Documentation/filesystems/nfs/Exporting for details on how to use
* this interface correctly.
@@ -137,6 +138,9 @@ struct fid {
* is also a directory. In the event that it cannot be found, or storage
* space cannot be allocated, a %ERR_PTR should be returned.
*
+ * commit_metadata:
+ * @commit_metadata should commit metadata changes to stable storage.
+ *
* Locking rules:
* get_parent is called with child->d_inode->i_mutex down
* get_name is not (which is possibly inconsistent)
@@ -152,6 +156,7 @@ struct export_operations {
int (*get_name)(struct dentry *parent, char *name,
struct dentry *child);
struct dentry * (*get_parent)(struct dentry *child);
+ int (*commit_metadata)(struct inode *inode);
};
extern int exportfs_encode_fh(struct dentry *dentry, struct fid *fid,
diff --git a/include/linux/firmware-map.h b/include/linux/firmware-map.h
index 875451f1373..c6dcc1dfe78 100644
--- a/include/linux/firmware-map.h
+++ b/include/linux/firmware-map.h
@@ -24,17 +24,17 @@
*/
#ifdef CONFIG_FIRMWARE_MEMMAP
-int firmware_map_add(u64 start, u64 end, const char *type);
int firmware_map_add_early(u64 start, u64 end, const char *type);
+int firmware_map_add_hotplug(u64 start, u64 end, const char *type);
#else /* CONFIG_FIRMWARE_MEMMAP */
-static inline int firmware_map_add(u64 start, u64 end, const char *type)
+static inline int firmware_map_add_early(u64 start, u64 end, const char *type)
{
return 0;
}
-static inline int firmware_map_add_early(u64 start, u64 end, const char *type)
+static inline int firmware_map_add_hotplug(u64 start, u64 end, const char *type)
{
return 0;
}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 45689621a85..10b8dedcd18 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -60,24 +60,24 @@ struct inodes_stat_t {
*/
/* file is open for reading */
-#define FMODE_READ ((__force fmode_t)1)
+#define FMODE_READ ((__force fmode_t)0x1)
/* file is open for writing */
-#define FMODE_WRITE ((__force fmode_t)2)
+#define FMODE_WRITE ((__force fmode_t)0x2)
/* file is seekable */
-#define FMODE_LSEEK ((__force fmode_t)4)
+#define FMODE_LSEEK ((__force fmode_t)0x4)
/* file can be accessed using pread */
-#define FMODE_PREAD ((__force fmode_t)8)
+#define FMODE_PREAD ((__force fmode_t)0x8)
/* file can be accessed using pwrite */
-#define FMODE_PWRITE ((__force fmode_t)16)
+#define FMODE_PWRITE ((__force fmode_t)0x10)
/* File is opened for execution with sys_execve / sys_uselib */
-#define FMODE_EXEC ((__force fmode_t)32)
+#define FMODE_EXEC ((__force fmode_t)0x20)
/* File is opened with O_NDELAY (only set for block devices) */
-#define FMODE_NDELAY ((__force fmode_t)64)
+#define FMODE_NDELAY ((__force fmode_t)0x40)
/* File is opened with O_EXCL (only set for block devices) */
-#define FMODE_EXCL ((__force fmode_t)128)
+#define FMODE_EXCL ((__force fmode_t)0x80)
/* File is opened using open(.., 3, ..) and is writeable only for ioctls
(specialy hack for floppy.c) */
-#define FMODE_WRITE_IOCTL ((__force fmode_t)256)
+#define FMODE_WRITE_IOCTL ((__force fmode_t)0x100)
/*
* Don't update ctime and mtime.
@@ -85,7 +85,10 @@ struct inodes_stat_t {
* Currently a special hack for the XFS open_by_handle ioctl, but we'll
* hopefully graduate it to a proper O_CMTIME flag supported by open(2) soon.
*/
-#define FMODE_NOCMTIME ((__force fmode_t)2048)
+#define FMODE_NOCMTIME ((__force fmode_t)0x800)
+
+/* Expect random access pattern */
+#define FMODE_RANDOM ((__force fmode_t)0x1000)
/*
* The below are the various read and write types that we support. Some of
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 557bdad320b..4c6d41333f9 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -30,7 +30,8 @@ struct vm_area_struct;
* _might_ fail. This depends upon the particular VM implementation.
*
* __GFP_NOFAIL: The VM implementation _must_ retry infinitely: the caller
- * cannot handle allocation failures.
+ * cannot handle allocation failures. This modifier is deprecated and no new
+ * users should be added.
*
* __GFP_NORETRY: The VM implementation must not retry indefinitely.
*
@@ -83,6 +84,7 @@ struct vm_area_struct;
#define GFP_HIGHUSER_MOVABLE (__GFP_WAIT | __GFP_IO | __GFP_FS | \
__GFP_HARDWALL | __GFP_HIGHMEM | \
__GFP_MOVABLE)
+#define GFP_IOFS (__GFP_IO | __GFP_FS)
#ifdef CONFIG_NUMA
#define GFP_THISNODE (__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY)
@@ -325,7 +327,7 @@ void free_pages_exact(void *virt, size_t size);
extern void __free_pages(struct page *page, unsigned int order);
extern void free_pages(unsigned long addr, unsigned int order);
-extern void free_hot_page(struct page *page);
+extern void free_hot_cold_page(struct page *page, int cold);
#define __free_page(page) __free_pages((page), 0)
#define free_page(addr) free_pages((addr),0)
@@ -337,9 +339,7 @@ void drain_local_pages(void *dummy);
extern gfp_t gfp_allowed_mask;
-static inline void set_gfp_allowed_mask(gfp_t mask)
-{
- gfp_allowed_mask = mask;
-}
+extern void set_gfp_allowed_mask(gfp_t mask);
+extern gfp_t clear_gfp_allowed_mask(gfp_t mask);
#endif /* __LINUX_GFP_H */
diff --git a/include/linux/htcpld.h b/include/linux/htcpld.h
new file mode 100644
index 00000000000..ab3f6cb4ddd
--- /dev/null
+++ b/include/linux/htcpld.h
@@ -0,0 +1,24 @@
+#ifndef __LINUX_HTCPLD_H
+#define __LINUX_HTCPLD_H
+
+struct htcpld_chip_platform_data {
+ unsigned int addr;
+ unsigned int reset;
+ unsigned int num_gpios;
+ unsigned int gpio_out_base;
+ unsigned int gpio_in_base;
+ unsigned int irq_base;
+ unsigned int num_irqs;
+};
+
+struct htcpld_core_platform_data {
+ unsigned int int_reset_gpio_hi;
+ unsigned int int_reset_gpio_lo;
+ unsigned int i2c_adapter_id;
+
+ struct htcpld_chip_platform_data *chip;
+ unsigned int num_chip;
+};
+
+#endif /* __LINUX_HTCPLD_H */
+
diff --git a/include/linux/i2c/pca953x.h b/include/linux/i2c/pca953x.h
index 81736d6a8db..d5c5a60c8a0 100644
--- a/include/linux/i2c/pca953x.h
+++ b/include/linux/i2c/pca953x.h
@@ -1,3 +1,9 @@
+#ifndef _LINUX_PCA953X_H
+#define _LINUX_PCA953X_H
+
+#include <linux/types.h>
+#include <linux/i2c.h>
+
/* platform data for the PCA9539 16-bit I/O expander driver */
struct pca953x_platform_data {
@@ -7,6 +13,9 @@ struct pca953x_platform_data {
/* initial polarity inversion setting */
uint16_t invert;
+ /* interrupt base */
+ int irq_base;
+
void *context; /* param to setup/teardown */
int (*setup)(struct i2c_client *client,
@@ -17,3 +26,5 @@ struct pca953x_platform_data {
void *context);
char **names;
};
+
+#endif /* _LINUX_PCA953X_H */
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index 7897f309656..fb6784e86d5 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -80,6 +80,11 @@
#define TWL_MODULE_PM_MASTER TWL4030_MODULE_PM_MASTER
#define TWL_MODULE_PM_RECEIVER TWL4030_MODULE_PM_RECEIVER
#define TWL_MODULE_RTC TWL4030_MODULE_RTC
+#define TWL_MODULE_PWM TWL4030_MODULE_PWM0
+
+#define TWL6030_MODULE_ID0 0x0D
+#define TWL6030_MODULE_ID1 0x0E
+#define TWL6030_MODULE_ID2 0x0F
#define GPIO_INTR_OFFSET 0
#define KEYPAD_INTR_OFFSET 1
@@ -239,6 +244,21 @@ int twl6030_interrupt_mask(u8 bit_mask, u8 offset);
/*----------------------------------------------------------------------*/
+/*Interface Bit Register (INTBR) offsets
+ *(Use TWL_4030_MODULE_INTBR)
+ */
+
+#define REG_GPPUPDCTR1 0x0F
+
+/*I2C1 and I2C4(SR) SDA/SCL pull-up control bits */
+
+#define I2C_SCL_CTRL_PU BIT(0)
+#define I2C_SDA_CTRL_PU BIT(2)
+#define SR_I2C_SCL_CTRL_PU BIT(4)
+#define SR_I2C_SDA_CTRL_PU BIT(6)
+
+/*----------------------------------------------------------------------*/
+
/*
* Keypad register offsets (use TWL4030_MODULE_KEYPAD)
* ... SIH/interrupt only
@@ -530,6 +550,7 @@ struct twl4030_power_data {
};
extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts);
+extern int twl4030_remove_script(u8 flags);
struct twl4030_codec_audio_data {
unsigned int audio_mclk;
@@ -605,12 +626,7 @@ int twl4030_sih_setup(int module);
#define TWL4030_VAUX3_DEV_GRP 0x1F
#define TWL4030_VAUX3_DEDICATED 0x22
-#if defined(CONFIG_TWL4030_BCI_BATTERY) || \
- defined(CONFIG_TWL4030_BCI_BATTERY_MODULE)
- extern int twl4030charger_usb_en(int enable);
-#else
- static inline int twl4030charger_usb_en(int enable) { return 0; }
-#endif
+static inline int twl4030charger_usb_en(int enable) { return 0; }
/*----------------------------------------------------------------------*/
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 58ae8e00fcd..3950d3c2850 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -106,7 +106,7 @@ extern char *kobject_get_path(struct kobject *kobj, gfp_t flag);
struct kobj_type {
void (*release)(struct kobject *kobj);
- struct sysfs_ops *sysfs_ops;
+ const struct sysfs_ops *sysfs_ops;
struct attribute **default_attrs;
};
@@ -118,9 +118,9 @@ struct kobj_uevent_env {
};
struct kset_uevent_ops {
- int (*filter)(struct kset *kset, struct kobject *kobj);
- const char *(*name)(struct kset *kset, struct kobject *kobj);
- int (*uevent)(struct kset *kset, struct kobject *kobj,
+ int (* const filter)(struct kset *kset, struct kobject *kobj);
+ const char *(* const name)(struct kset *kset, struct kobject *kobj);
+ int (* const uevent)(struct kset *kset, struct kobject *kobj,
struct kobj_uevent_env *env);
};
@@ -132,7 +132,7 @@ struct kobj_attribute {
const char *buf, size_t count);
};
-extern struct sysfs_ops kobj_sysfs_ops;
+extern const struct sysfs_ops kobj_sysfs_ops;
/**
* struct kset - a set of kobjects of a specific type, belonging to a specific subsystem.
@@ -155,14 +155,14 @@ struct kset {
struct list_head list;
spinlock_t list_lock;
struct kobject kobj;
- struct kset_uevent_ops *uevent_ops;
+ const struct kset_uevent_ops *uevent_ops;
};
extern void kset_init(struct kset *kset);
extern int __must_check kset_register(struct kset *kset);
extern void kset_unregister(struct kset *kset);
extern struct kset * __must_check kset_create_and_add(const char *name,
- struct kset_uevent_ops *u,
+ const struct kset_uevent_ops *u,
struct kobject *parent_kobj);
static inline struct kset *to_kset(struct kobject *kobj)
diff --git a/include/linux/list.h b/include/linux/list.h
index 5d9c6558e8a..8392884a297 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -498,7 +498,7 @@ static inline void list_splice_tail_init(struct list_head *list,
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
- * list_for_each_entry_safe_continue
+ * list_for_each_entry_safe_continue - continue list iteration safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
@@ -514,7 +514,7 @@ static inline void list_splice_tail_init(struct list_head *list,
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
- * list_for_each_entry_safe_from
+ * list_for_each_entry_safe_from - iterate over list from current point safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
@@ -529,7 +529,7 @@ static inline void list_splice_tail_init(struct list_head *list,
pos = n, n = list_entry(n->member.next, typeof(*n), member))
/**
- * list_for_each_entry_safe_reverse
+ * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
diff --git a/include/linux/mfd/88pm8607.h b/include/linux/mfd/88pm8607.h
deleted file mode 100644
index f41b428d2ce..00000000000
--- a/include/linux/mfd/88pm8607.h
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Marvell 88PM8607 Interface
- *
- * Copyright (C) 2009 Marvell International Ltd.
- * Haojian Zhuang <haojian.zhuang@marvell.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 __LINUX_MFD_88PM8607_H
-#define __LINUX_MFD_88PM8607_H
-
-enum {
- PM8607_ID_BUCK1 = 0,
- PM8607_ID_BUCK2,
- PM8607_ID_BUCK3,
-
- PM8607_ID_LDO1,
- PM8607_ID_LDO2,
- PM8607_ID_LDO3,
- PM8607_ID_LDO4,
- PM8607_ID_LDO5,
- PM8607_ID_LDO6,
- PM8607_ID_LDO7,
- PM8607_ID_LDO8,
- PM8607_ID_LDO9,
- PM8607_ID_LDO10,
- PM8607_ID_LDO12,
- PM8607_ID_LDO14,
-
- PM8607_ID_RG_MAX,
-};
-
-#define CHIP_ID (0x40)
-#define CHIP_ID_MASK (0xF8)
-
-/* Interrupt Registers */
-#define PM8607_STATUS_1 (0x01)
-#define PM8607_STATUS_2 (0x02)
-#define PM8607_INT_STATUS1 (0x03)
-#define PM8607_INT_STATUS2 (0x04)
-#define PM8607_INT_STATUS3 (0x05)
-#define PM8607_INT_MASK_1 (0x06)
-#define PM8607_INT_MASK_2 (0x07)
-#define PM8607_INT_MASK_3 (0x08)
-
-/* Regulator Control Registers */
-#define PM8607_LDO1 (0x10)
-#define PM8607_LDO2 (0x11)
-#define PM8607_LDO3 (0x12)
-#define PM8607_LDO4 (0x13)
-#define PM8607_LDO5 (0x14)
-#define PM8607_LDO6 (0x15)
-#define PM8607_LDO7 (0x16)
-#define PM8607_LDO8 (0x17)
-#define PM8607_LDO9 (0x18)
-#define PM8607_LDO10 (0x19)
-#define PM8607_LDO12 (0x1A)
-#define PM8607_LDO14 (0x1B)
-#define PM8607_SLEEP_MODE1 (0x1C)
-#define PM8607_SLEEP_MODE2 (0x1D)
-#define PM8607_SLEEP_MODE3 (0x1E)
-#define PM8607_SLEEP_MODE4 (0x1F)
-#define PM8607_GO (0x20)
-#define PM8607_SLEEP_BUCK1 (0x21)
-#define PM8607_SLEEP_BUCK2 (0x22)
-#define PM8607_SLEEP_BUCK3 (0x23)
-#define PM8607_BUCK1 (0x24)
-#define PM8607_BUCK2 (0x25)
-#define PM8607_BUCK3 (0x26)
-#define PM8607_BUCK_CONTROLS (0x27)
-#define PM8607_SUPPLIES_EN11 (0x2B)
-#define PM8607_SUPPLIES_EN12 (0x2C)
-#define PM8607_GROUP1 (0x2D)
-#define PM8607_GROUP2 (0x2E)
-#define PM8607_GROUP3 (0x2F)
-#define PM8607_GROUP4 (0x30)
-#define PM8607_GROUP5 (0x31)
-#define PM8607_GROUP6 (0x32)
-#define PM8607_SUPPLIES_EN21 (0x33)
-#define PM8607_SUPPLIES_EN22 (0x34)
-
-/* RTC Control Registers */
-#define PM8607_RTC1 (0xA0)
-#define PM8607_RTC_COUNTER1 (0xA1)
-#define PM8607_RTC_COUNTER2 (0xA2)
-#define PM8607_RTC_COUNTER3 (0xA3)
-#define PM8607_RTC_COUNTER4 (0xA4)
-#define PM8607_RTC_EXPIRE1 (0xA5)
-#define PM8607_RTC_EXPIRE2 (0xA6)
-#define PM8607_RTC_EXPIRE3 (0xA7)
-#define PM8607_RTC_EXPIRE4 (0xA8)
-#define PM8607_RTC_TRIM1 (0xA9)
-#define PM8607_RTC_TRIM2 (0xAA)
-#define PM8607_RTC_TRIM3 (0xAB)
-#define PM8607_RTC_TRIM4 (0xAC)
-#define PM8607_RTC_MISC1 (0xAD)
-#define PM8607_RTC_MISC2 (0xAE)
-#define PM8607_RTC_MISC3 (0xAF)
-
-/* Misc Registers */
-#define PM8607_CHIP_ID (0x00)
-#define PM8607_LDO1 (0x10)
-#define PM8607_DVC3 (0x26)
-#define PM8607_MISC1 (0x40)
-
-/* bit definitions for PM8607 events */
-#define PM8607_EVENT_ONKEY (1 << 0)
-#define PM8607_EVENT_EXTON (1 << 1)
-#define PM8607_EVENT_CHG (1 << 2)
-#define PM8607_EVENT_BAT (1 << 3)
-#define PM8607_EVENT_RTC (1 << 4)
-#define PM8607_EVENT_CC (1 << 5)
-#define PM8607_EVENT_VBAT (1 << 8)
-#define PM8607_EVENT_VCHG (1 << 9)
-#define PM8607_EVENT_VSYS (1 << 10)
-#define PM8607_EVENT_TINT (1 << 11)
-#define PM8607_EVENT_GPADC0 (1 << 12)
-#define PM8607_EVENT_GPADC1 (1 << 13)
-#define PM8607_EVENT_GPADC2 (1 << 14)
-#define PM8607_EVENT_GPADC3 (1 << 15)
-#define PM8607_EVENT_AUDIO_SHORT (1 << 16)
-#define PM8607_EVENT_PEN (1 << 17)
-#define PM8607_EVENT_HEADSET (1 << 18)
-#define PM8607_EVENT_HOOK (1 << 19)
-#define PM8607_EVENT_MICIN (1 << 20)
-#define PM8607_EVENT_CHG_TIMEOUT (1 << 21)
-#define PM8607_EVENT_CHG_DONE (1 << 22)
-#define PM8607_EVENT_CHG_FAULT (1 << 23)
-
-/* bit definitions of Status Query Interface */
-#define PM8607_STATUS_CC (1 << 3)
-#define PM8607_STATUS_PEN (1 << 4)
-#define PM8607_STATUS_HEADSET (1 << 5)
-#define PM8607_STATUS_HOOK (1 << 6)
-#define PM8607_STATUS_MICIN (1 << 7)
-#define PM8607_STATUS_ONKEY (1 << 8)
-#define PM8607_STATUS_EXTON (1 << 9)
-#define PM8607_STATUS_CHG (1 << 10)
-#define PM8607_STATUS_BAT (1 << 11)
-#define PM8607_STATUS_VBUS (1 << 12)
-#define PM8607_STATUS_OV (1 << 13)
-
-/* bit definitions of BUCK3 */
-#define PM8607_BUCK3_DOUBLE (1 << 6)
-
-/* bit definitions of Misc1 */
-#define PM8607_MISC1_PI2C (1 << 0)
-
-/* Interrupt Number in 88PM8607 */
-enum {
- PM8607_IRQ_ONKEY = 0,
- PM8607_IRQ_EXTON,
- PM8607_IRQ_CHG,
- PM8607_IRQ_BAT,
- PM8607_IRQ_RTC,
- PM8607_IRQ_VBAT = 8,
- PM8607_IRQ_VCHG,
- PM8607_IRQ_VSYS,
- PM8607_IRQ_TINT,
- PM8607_IRQ_GPADC0,
- PM8607_IRQ_GPADC1,
- PM8607_IRQ_GPADC2,
- PM8607_IRQ_GPADC3,
- PM8607_IRQ_AUDIO_SHORT = 16,
- PM8607_IRQ_PEN,
- PM8607_IRQ_HEADSET,
- PM8607_IRQ_HOOK,
- PM8607_IRQ_MICIN,
- PM8607_IRQ_CHG_FAIL,
- PM8607_IRQ_CHG_DONE,
- PM8607_IRQ_CHG_FAULT,
-};
-
-enum {
- PM8607_CHIP_A0 = 0x40,
- PM8607_CHIP_A1 = 0x41,
- PM8607_CHIP_B0 = 0x48,
-};
-
-
-struct pm8607_chip {
- struct device *dev;
- struct mutex io_lock;
- struct i2c_client *client;
-
- int (*read)(struct pm8607_chip *chip, int reg, int bytes, void *dest);
- int (*write)(struct pm8607_chip *chip, int reg, int bytes, void *src);
-
- int buck3_double; /* DVC ramp slope double */
- unsigned char chip_id;
-
-};
-
-#define PM8607_MAX_REGULATOR 15 /* 3 Bucks, 12 LDOs */
-
-enum {
- GI2C_PORT = 0,
- PI2C_PORT,
-};
-
-struct pm8607_platform_data {
- int i2c_port; /* Controlled by GI2C or PI2C */
- struct regulator_init_data *regulator[PM8607_MAX_REGULATOR];
-};
-
-extern int pm8607_reg_read(struct pm8607_chip *, int);
-extern int pm8607_reg_write(struct pm8607_chip *, int, unsigned char);
-extern int pm8607_bulk_read(struct pm8607_chip *, int, int,
- unsigned char *);
-extern int pm8607_bulk_write(struct pm8607_chip *, int, int,
- unsigned char *);
-extern int pm8607_set_bits(struct pm8607_chip *, int, unsigned char,
- unsigned char);
-#endif /* __LINUX_MFD_88PM8607_H */
diff --git a/include/linux/mfd/88pm860x.h b/include/linux/mfd/88pm860x.h
new file mode 100644
index 00000000000..73f92c5feea
--- /dev/null
+++ b/include/linux/mfd/88pm860x.h
@@ -0,0 +1,375 @@
+/*
+ * Marvell 88PM860x Interface
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ * Haojian Zhuang <haojian.zhuang@marvell.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 __LINUX_MFD_88PM860X_H
+#define __LINUX_MFD_88PM860X_H
+
+#include <linux/interrupt.h>
+
+#define MFD_NAME_SIZE (40)
+
+enum {
+ CHIP_INVALID = 0,
+ CHIP_PM8606,
+ CHIP_PM8607,
+ CHIP_MAX,
+};
+
+enum {
+ PM8606_ID_INVALID,
+ PM8606_ID_BACKLIGHT,
+ PM8606_ID_LED,
+ PM8606_ID_VIBRATOR,
+ PM8606_ID_TOUCH,
+ PM8606_ID_SOUND,
+ PM8606_ID_CHARGER,
+ PM8606_ID_MAX,
+};
+
+enum {
+ PM8606_BACKLIGHT1 = 0,
+ PM8606_BACKLIGHT2,
+ PM8606_BACKLIGHT3,
+};
+
+enum {
+ PM8606_LED1_RED = 0,
+ PM8606_LED1_GREEN,
+ PM8606_LED1_BLUE,
+ PM8606_LED2_RED,
+ PM8606_LED2_GREEN,
+ PM8606_LED2_BLUE,
+ PM8607_LED_VIBRATOR,
+};
+
+
+/* 8606 Registers */
+#define PM8606_DCM_BOOST (0x00)
+#define PM8606_PWM (0x01)
+
+/* Backlight Registers */
+#define PM8606_WLED1A (0x02)
+#define PM8606_WLED1B (0x03)
+#define PM8606_WLED2A (0x04)
+#define PM8606_WLED2B (0x05)
+#define PM8606_WLED3A (0x06)
+#define PM8606_WLED3B (0x07)
+
+/* LED Registers */
+#define PM8606_RGB2A (0x08)
+#define PM8606_RGB2B (0x09)
+#define PM8606_RGB2C (0x0A)
+#define PM8606_RGB2D (0x0B)
+#define PM8606_RGB1A (0x0C)
+#define PM8606_RGB1B (0x0D)
+#define PM8606_RGB1C (0x0E)
+#define PM8606_RGB1D (0x0F)
+
+#define PM8606_PREREGULATORA (0x10)
+#define PM8606_PREREGULATORB (0x11)
+#define PM8606_VIBRATORA (0x12)
+#define PM8606_VIBRATORB (0x13)
+#define PM8606_VCHG (0x14)
+#define PM8606_VSYS (0x15)
+#define PM8606_MISC (0x16)
+#define PM8606_CHIP_ID (0x17)
+#define PM8606_STATUS (0x18)
+#define PM8606_FLAGS (0x19)
+#define PM8606_PROTECTA (0x1A)
+#define PM8606_PROTECTB (0x1B)
+#define PM8606_PROTECTC (0x1C)
+
+/* Bit definitions of PM8606 registers */
+#define PM8606_DCM_500MA (0x0) /* current limit */
+#define PM8606_DCM_750MA (0x1)
+#define PM8606_DCM_1000MA (0x2)
+#define PM8606_DCM_1250MA (0x3)
+#define PM8606_DCM_250MV (0x0 << 2)
+#define PM8606_DCM_300MV (0x1 << 2)
+#define PM8606_DCM_350MV (0x2 << 2)
+#define PM8606_DCM_400MV (0x3 << 2)
+
+#define PM8606_PWM_31200HZ (0x0)
+#define PM8606_PWM_15600HZ (0x1)
+#define PM8606_PWM_7800HZ (0x2)
+#define PM8606_PWM_3900HZ (0x3)
+#define PM8606_PWM_1950HZ (0x4)
+#define PM8606_PWM_976HZ (0x5)
+#define PM8606_PWM_488HZ (0x6)
+#define PM8606_PWM_244HZ (0x7)
+#define PM8606_PWM_FREQ_MASK (0x7)
+
+#define PM8606_WLED_ON (1 << 0)
+#define PM8606_WLED_CURRENT(x) ((x & 0x1F) << 1)
+
+#define PM8606_LED_CURRENT(x) (((x >> 2) & 0x07) << 5)
+
+#define PM8606_VSYS_EN (1 << 1)
+
+#define PM8606_MISC_OSC_EN (1 << 4)
+
+enum {
+ PM8607_ID_BUCK1 = 0,
+ PM8607_ID_BUCK2,
+ PM8607_ID_BUCK3,
+
+ PM8607_ID_LDO1,
+ PM8607_ID_LDO2,
+ PM8607_ID_LDO3,
+ PM8607_ID_LDO4,
+ PM8607_ID_LDO5,
+ PM8607_ID_LDO6,
+ PM8607_ID_LDO7,
+ PM8607_ID_LDO8,
+ PM8607_ID_LDO9,
+ PM8607_ID_LDO10,
+ PM8607_ID_LDO12,
+ PM8607_ID_LDO14,
+
+ PM8607_ID_RG_MAX,
+};
+
+#define PM8607_VERSION (0x40) /* 8607 chip ID */
+#define PM8607_VERSION_MASK (0xF0) /* 8607 chip ID mask */
+
+/* Interrupt Registers */
+#define PM8607_STATUS_1 (0x01)
+#define PM8607_STATUS_2 (0x02)
+#define PM8607_INT_STATUS1 (0x03)
+#define PM8607_INT_STATUS2 (0x04)
+#define PM8607_INT_STATUS3 (0x05)
+#define PM8607_INT_MASK_1 (0x06)
+#define PM8607_INT_MASK_2 (0x07)
+#define PM8607_INT_MASK_3 (0x08)
+
+/* Regulator Control Registers */
+#define PM8607_LDO1 (0x10)
+#define PM8607_LDO2 (0x11)
+#define PM8607_LDO3 (0x12)
+#define PM8607_LDO4 (0x13)
+#define PM8607_LDO5 (0x14)
+#define PM8607_LDO6 (0x15)
+#define PM8607_LDO7 (0x16)
+#define PM8607_LDO8 (0x17)
+#define PM8607_LDO9 (0x18)
+#define PM8607_LDO10 (0x19)
+#define PM8607_LDO12 (0x1A)
+#define PM8607_LDO14 (0x1B)
+#define PM8607_SLEEP_MODE1 (0x1C)
+#define PM8607_SLEEP_MODE2 (0x1D)
+#define PM8607_SLEEP_MODE3 (0x1E)
+#define PM8607_SLEEP_MODE4 (0x1F)
+#define PM8607_GO (0x20)
+#define PM8607_SLEEP_BUCK1 (0x21)
+#define PM8607_SLEEP_BUCK2 (0x22)
+#define PM8607_SLEEP_BUCK3 (0x23)
+#define PM8607_BUCK1 (0x24)
+#define PM8607_BUCK2 (0x25)
+#define PM8607_BUCK3 (0x26)
+#define PM8607_BUCK_CONTROLS (0x27)
+#define PM8607_SUPPLIES_EN11 (0x2B)
+#define PM8607_SUPPLIES_EN12 (0x2C)
+#define PM8607_GROUP1 (0x2D)
+#define PM8607_GROUP2 (0x2E)
+#define PM8607_GROUP3 (0x2F)
+#define PM8607_GROUP4 (0x30)
+#define PM8607_GROUP5 (0x31)
+#define PM8607_GROUP6 (0x32)
+#define PM8607_SUPPLIES_EN21 (0x33)
+#define PM8607_SUPPLIES_EN22 (0x34)
+
+/* Vibrator Control Registers */
+#define PM8607_VIBRATOR_SET (0x28)
+#define PM8607_VIBRATOR_PWM (0x29)
+
+/* GPADC Registers */
+#define PM8607_GP_BIAS1 (0x4F)
+#define PM8607_MEAS_EN1 (0x50)
+#define PM8607_MEAS_EN2 (0x51)
+#define PM8607_MEAS_EN3 (0x52)
+#define PM8607_MEAS_OFF_TIME1 (0x53)
+#define PM8607_MEAS_OFF_TIME2 (0x54)
+#define PM8607_TSI_PREBIAS (0x55) /* prebias time */
+#define PM8607_PD_PREBIAS (0x56) /* prebias time */
+#define PM8607_GPADC_MISC1 (0x57)
+
+/* RTC Control Registers */
+#define PM8607_RTC1 (0xA0)
+#define PM8607_RTC_COUNTER1 (0xA1)
+#define PM8607_RTC_COUNTER2 (0xA2)
+#define PM8607_RTC_COUNTER3 (0xA3)
+#define PM8607_RTC_COUNTER4 (0xA4)
+#define PM8607_RTC_EXPIRE1 (0xA5)
+#define PM8607_RTC_EXPIRE2 (0xA6)
+#define PM8607_RTC_EXPIRE3 (0xA7)
+#define PM8607_RTC_EXPIRE4 (0xA8)
+#define PM8607_RTC_TRIM1 (0xA9)
+#define PM8607_RTC_TRIM2 (0xAA)
+#define PM8607_RTC_TRIM3 (0xAB)
+#define PM8607_RTC_TRIM4 (0xAC)
+#define PM8607_RTC_MISC1 (0xAD)
+#define PM8607_RTC_MISC2 (0xAE)
+#define PM8607_RTC_MISC3 (0xAF)
+
+/* Misc Registers */
+#define PM8607_CHIP_ID (0x00)
+#define PM8607_B0_MISC1 (0x0C)
+#define PM8607_LDO1 (0x10)
+#define PM8607_DVC3 (0x26)
+#define PM8607_A1_MISC1 (0x40)
+
+/* bit definitions of Status Query Interface */
+#define PM8607_STATUS_CC (1 << 3)
+#define PM8607_STATUS_PEN (1 << 4)
+#define PM8607_STATUS_HEADSET (1 << 5)
+#define PM8607_STATUS_HOOK (1 << 6)
+#define PM8607_STATUS_MICIN (1 << 7)
+#define PM8607_STATUS_ONKEY (1 << 8)
+#define PM8607_STATUS_EXTON (1 << 9)
+#define PM8607_STATUS_CHG (1 << 10)
+#define PM8607_STATUS_BAT (1 << 11)
+#define PM8607_STATUS_VBUS (1 << 12)
+#define PM8607_STATUS_OV (1 << 13)
+
+/* bit definitions of BUCK3 */
+#define PM8607_BUCK3_DOUBLE (1 << 6)
+
+/* bit definitions of Misc1 */
+#define PM8607_A1_MISC1_PI2C (1 << 0)
+#define PM8607_B0_MISC1_INV_INT (1 << 0)
+#define PM8607_B0_MISC1_INT_CLEAR (1 << 1)
+#define PM8607_B0_MISC1_INT_MASK (1 << 2)
+#define PM8607_B0_MISC1_PI2C (1 << 3)
+#define PM8607_B0_MISC1_RESET (1 << 6)
+
+/* bits definitions of GPADC */
+#define PM8607_GPADC_EN (1 << 0)
+#define PM8607_GPADC_PREBIAS_MASK (3 << 1)
+#define PM8607_GPADC_SLOT_CYCLE_MASK (3 << 3) /* slow mode */
+#define PM8607_GPADC_OFF_SCALE_MASK (3 << 5) /* GP sleep mode */
+#define PM8607_GPADC_SW_CAL_MASK (1 << 7)
+
+#define PM8607_PD_PREBIAS_MASK (0x1F << 0)
+#define PM8607_PD_PRECHG_MASK (7 << 5)
+
+/* Interrupt Number in 88PM8607 */
+enum {
+ PM8607_IRQ_ONKEY,
+ PM8607_IRQ_EXTON,
+ PM8607_IRQ_CHG,
+ PM8607_IRQ_BAT,
+ PM8607_IRQ_RTC,
+ PM8607_IRQ_CC,
+ PM8607_IRQ_VBAT,
+ PM8607_IRQ_VCHG,
+ PM8607_IRQ_VSYS,
+ PM8607_IRQ_TINT,
+ PM8607_IRQ_GPADC0,
+ PM8607_IRQ_GPADC1,
+ PM8607_IRQ_GPADC2,
+ PM8607_IRQ_GPADC3,
+ PM8607_IRQ_AUDIO_SHORT,
+ PM8607_IRQ_PEN,
+ PM8607_IRQ_HEADSET,
+ PM8607_IRQ_HOOK,
+ PM8607_IRQ_MICIN,
+ PM8607_IRQ_CHG_FAIL,
+ PM8607_IRQ_CHG_DONE,
+ PM8607_IRQ_CHG_FAULT,
+};
+
+enum {
+ PM8607_CHIP_A0 = 0x40,
+ PM8607_CHIP_A1 = 0x41,
+ PM8607_CHIP_B0 = 0x48,
+};
+
+struct pm860x_chip {
+ struct device *dev;
+ struct mutex io_lock;
+ struct mutex irq_lock;
+ struct i2c_client *client;
+ struct i2c_client *companion; /* companion chip client */
+
+ int buck3_double; /* DVC ramp slope double */
+ unsigned short companion_addr;
+ int id;
+ int irq_mode;
+ int irq_base;
+ int core_irq;
+ unsigned char chip_version;
+
+};
+
+#define PM8607_MAX_REGULATOR 15 /* 3 Bucks, 12 LDOs */
+
+enum {
+ GI2C_PORT = 0,
+ PI2C_PORT,
+};
+
+struct pm860x_backlight_pdata {
+ int id;
+ int pwm;
+ int iset;
+ unsigned long flags;
+};
+
+struct pm860x_led_pdata {
+ int id;
+ int iset;
+ unsigned long flags;
+};
+
+struct pm860x_touch_pdata {
+ int gpadc_prebias;
+ int slot_cycle;
+ int off_scale;
+ int sw_cal;
+ int tsi_prebias; /* time, slot */
+ int pen_prebias; /* time, slot */
+ int pen_prechg; /* time, slot */
+ int res_x; /* resistor of Xplate */
+ unsigned long flags;
+};
+
+struct pm860x_power_pdata {
+ unsigned fast_charge; /* charge current */
+};
+
+struct pm860x_platform_data {
+ struct pm860x_backlight_pdata *backlight;
+ struct pm860x_led_pdata *led;
+ struct pm860x_touch_pdata *touch;
+ struct pm860x_power_pdata *power;
+
+ unsigned short companion_addr; /* I2C address of companion chip */
+ int i2c_port; /* Controlled by GI2C or PI2C */
+ int irq_mode; /* Clear interrupt by read/write(0/1) */
+ int irq_base; /* IRQ base number of 88pm860x */
+ struct regulator_init_data *regulator[PM8607_MAX_REGULATOR];
+};
+
+extern char pm860x_backlight_name[][MFD_NAME_SIZE];
+extern char pm860x_led_name[][MFD_NAME_SIZE];
+
+extern int pm860x_reg_read(struct i2c_client *, int);
+extern int pm860x_reg_write(struct i2c_client *, int, unsigned char);
+extern int pm860x_bulk_read(struct i2c_client *, int, int, unsigned char *);
+extern int pm860x_bulk_write(struct i2c_client *, int, int, unsigned char *);
+extern int pm860x_set_bits(struct i2c_client *, int, unsigned char,
+ unsigned char);
+
+extern int pm860x_device_init(struct pm860x_chip *chip,
+ struct pm860x_platform_data *pdata);
+extern void pm860x_device_exit(struct pm860x_chip *chip);
+
+#endif /* __LINUX_MFD_88PM860X_H */
diff --git a/include/linux/mfd/ab3100.h b/include/linux/mfd/ab3100.h
index e9aa4c9d749..9a881c305a5 100644
--- a/include/linux/mfd/ab3100.h
+++ b/include/linux/mfd/ab3100.h
@@ -6,7 +6,6 @@
*/
#include <linux/device.h>
-#include <linux/workqueue.h>
#include <linux/regulator/machine.h>
#ifndef MFD_AB3100_H
@@ -74,7 +73,6 @@
* @testreg_client: secondary client for test registers
* @chip_name: name of this chip variant
* @chip_id: 8 bit chip ID for this chip variant
- * @work: an event handling worker
* @event_subscribers: event subscribers are listed here
* @startup_events: a copy of the first reading of the event registers
* @startup_events_read: whether the first events have been read
@@ -90,7 +88,6 @@ struct ab3100 {
struct i2c_client *testreg_client;
char chip_name[32];
u8 chip_id;
- struct work_struct work;
struct blocking_notifier_head event_subscribers;
u32 startup_events;
bool startup_events_read;
diff --git a/include/linux/mfd/max8925.h b/include/linux/mfd/max8925.h
new file mode 100644
index 00000000000..5259dfe8c58
--- /dev/null
+++ b/include/linux/mfd/max8925.h
@@ -0,0 +1,253 @@
+/*
+ * Maxim8925 Interface
+ *
+ * Copyright (C) 2009 Marvell International Ltd.
+ * Haojian Zhuang <haojian.zhuang@marvell.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 __LINUX_MFD_MAX8925_H
+#define __LINUX_MFD_MAX8925_H
+
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+
+/* Unified sub device IDs for MAX8925 */
+enum {
+ MAX8925_ID_SD1,
+ MAX8925_ID_SD2,
+ MAX8925_ID_SD3,
+ MAX8925_ID_LDO1,
+ MAX8925_ID_LDO2,
+ MAX8925_ID_LDO3,
+ MAX8925_ID_LDO4,
+ MAX8925_ID_LDO5,
+ MAX8925_ID_LDO6,
+ MAX8925_ID_LDO7,
+ MAX8925_ID_LDO8,
+ MAX8925_ID_LDO9,
+ MAX8925_ID_LDO10,
+ MAX8925_ID_LDO11,
+ MAX8925_ID_LDO12,
+ MAX8925_ID_LDO13,
+ MAX8925_ID_LDO14,
+ MAX8925_ID_LDO15,
+ MAX8925_ID_LDO16,
+ MAX8925_ID_LDO17,
+ MAX8925_ID_LDO18,
+ MAX8925_ID_LDO19,
+ MAX8925_ID_LDO20,
+ MAX8925_ID_MAX,
+};
+
+enum {
+ /*
+ * Charging current threshold trigger going from fast charge
+ * to TOPOFF charge. From 5% to 20% of fasting charging current.
+ */
+ MAX8925_TOPOFF_THR_5PER,
+ MAX8925_TOPOFF_THR_10PER,
+ MAX8925_TOPOFF_THR_15PER,
+ MAX8925_TOPOFF_THR_20PER,
+};
+
+enum {
+ /* Fast charging current */
+ MAX8925_FCHG_85MA,
+ MAX8925_FCHG_300MA,
+ MAX8925_FCHG_460MA,
+ MAX8925_FCHG_600MA,
+ MAX8925_FCHG_700MA,
+ MAX8925_FCHG_800MA,
+ MAX8925_FCHG_900MA,
+ MAX8925_FCHG_1000MA,
+};
+
+/* Charger registers */
+#define MAX8925_CHG_IRQ1 (0x7e)
+#define MAX8925_CHG_IRQ2 (0x7f)
+#define MAX8925_CHG_IRQ1_MASK (0x80)
+#define MAX8925_CHG_IRQ2_MASK (0x81)
+#define MAX8925_CHG_STATUS (0x82)
+
+/* GPM registers */
+#define MAX8925_SYSENSEL (0x00)
+#define MAX8925_ON_OFF_IRQ1 (0x01)
+#define MAX8925_ON_OFF_IRQ1_MASK (0x02)
+#define MAX8925_ON_OFF_STATUS (0x03)
+#define MAX8925_ON_OFF_IRQ2 (0x0d)
+#define MAX8925_ON_OFF_IRQ2_MASK (0x0e)
+#define MAX8925_RESET_CNFG (0x0f)
+
+/* Touch registers */
+#define MAX8925_TSC_IRQ (0x00)
+#define MAX8925_TSC_IRQ_MASK (0x01)
+#define MAX8925_TSC_CNFG1 (0x02)
+#define MAX8925_ADC_SCHED (0x10)
+#define MAX8925_ADC_RES_END (0x6f)
+
+#define MAX8925_NREF_OK (1 << 4)
+
+/* RTC registers */
+#define MAX8925_ALARM0_CNTL (0x18)
+#define MAX8925_ALARM1_CNTL (0x19)
+#define MAX8925_RTC_IRQ (0x1c)
+#define MAX8925_RTC_IRQ_MASK (0x1d)
+#define MAX8925_MPL_CNTL (0x1e)
+
+/* WLED registers */
+#define MAX8925_WLED_MODE_CNTL (0x84)
+#define MAX8925_WLED_CNTL (0x85)
+
+/* MAX8925 Registers */
+#define MAX8925_SDCTL1 (0x04)
+#define MAX8925_SDCTL2 (0x07)
+#define MAX8925_SDCTL3 (0x0A)
+#define MAX8925_SDV1 (0x06)
+#define MAX8925_SDV2 (0x09)
+#define MAX8925_SDV3 (0x0C)
+#define MAX8925_LDOCTL1 (0x18)
+#define MAX8925_LDOCTL2 (0x1C)
+#define MAX8925_LDOCTL3 (0x20)
+#define MAX8925_LDOCTL4 (0x24)
+#define MAX8925_LDOCTL5 (0x28)
+#define MAX8925_LDOCTL6 (0x2C)
+#define MAX8925_LDOCTL7 (0x30)
+#define MAX8925_LDOCTL8 (0x34)
+#define MAX8925_LDOCTL9 (0x38)
+#define MAX8925_LDOCTL10 (0x3C)
+#define MAX8925_LDOCTL11 (0x40)
+#define MAX8925_LDOCTL12 (0x44)
+#define MAX8925_LDOCTL13 (0x48)
+#define MAX8925_LDOCTL14 (0x4C)
+#define MAX8925_LDOCTL15 (0x50)
+#define MAX8925_LDOCTL16 (0x10)
+#define MAX8925_LDOCTL17 (0x14)
+#define MAX8925_LDOCTL18 (0x72)
+#define MAX8925_LDOCTL19 (0x5C)
+#define MAX8925_LDOCTL20 (0x9C)
+#define MAX8925_LDOVOUT1 (0x1A)
+#define MAX8925_LDOVOUT2 (0x1E)
+#define MAX8925_LDOVOUT3 (0x22)
+#define MAX8925_LDOVOUT4 (0x26)
+#define MAX8925_LDOVOUT5 (0x2A)
+#define MAX8925_LDOVOUT6 (0x2E)
+#define MAX8925_LDOVOUT7 (0x32)
+#define MAX8925_LDOVOUT8 (0x36)
+#define MAX8925_LDOVOUT9 (0x3A)
+#define MAX8925_LDOVOUT10 (0x3E)
+#define MAX8925_LDOVOUT11 (0x42)
+#define MAX8925_LDOVOUT12 (0x46)
+#define MAX8925_LDOVOUT13 (0x4A)
+#define MAX8925_LDOVOUT14 (0x4E)
+#define MAX8925_LDOVOUT15 (0x52)
+#define MAX8925_LDOVOUT16 (0x12)
+#define MAX8925_LDOVOUT17 (0x16)
+#define MAX8925_LDOVOUT18 (0x74)
+#define MAX8925_LDOVOUT19 (0x5E)
+#define MAX8925_LDOVOUT20 (0x9E)
+
+/* bit definitions */
+#define CHG_IRQ1_MASK (0x07)
+#define CHG_IRQ2_MASK (0xff)
+#define ON_OFF_IRQ1_MASK (0xff)
+#define ON_OFF_IRQ2_MASK (0x03)
+#define TSC_IRQ_MASK (0x03)
+#define RTC_IRQ_MASK (0x0c)
+
+#define MAX8925_MAX_REGULATOR (23)
+
+#define MAX8925_NAME_SIZE (32)
+
+/* IRQ definitions */
+enum {
+ MAX8925_IRQ_VCHG_DC_OVP,
+ MAX8925_IRQ_VCHG_DC_F,
+ MAX8925_IRQ_VCHG_DC_R,
+ MAX8925_IRQ_VCHG_USB_OVP,
+ MAX8925_IRQ_VCHG_USB_F,
+ MAX8925_IRQ_VCHG_USB_R,
+ MAX8925_IRQ_VCHG_THM_OK_R,
+ MAX8925_IRQ_VCHG_THM_OK_F,
+ MAX8925_IRQ_VCHG_SYSLOW_F,
+ MAX8925_IRQ_VCHG_SYSLOW_R,
+ MAX8925_IRQ_VCHG_RST,
+ MAX8925_IRQ_VCHG_DONE,
+ MAX8925_IRQ_VCHG_TOPOFF,
+ MAX8925_IRQ_VCHG_TMR_FAULT,
+ MAX8925_IRQ_GPM_RSTIN,
+ MAX8925_IRQ_GPM_MPL,
+ MAX8925_IRQ_GPM_SW_3SEC,
+ MAX8925_IRQ_GPM_EXTON_F,
+ MAX8925_IRQ_GPM_EXTON_R,
+ MAX8925_IRQ_GPM_SW_1SEC,
+ MAX8925_IRQ_GPM_SW_F,
+ MAX8925_IRQ_GPM_SW_R,
+ MAX8925_IRQ_GPM_SYSCKEN_F,
+ MAX8925_IRQ_GPM_SYSCKEN_R,
+ MAX8925_IRQ_RTC_ALARM1,
+ MAX8925_IRQ_RTC_ALARM0,
+ MAX8925_IRQ_TSC_STICK,
+ MAX8925_IRQ_TSC_NSTICK,
+ MAX8925_NR_IRQS,
+};
+
+struct max8925_chip {
+ struct device *dev;
+ struct i2c_client *i2c;
+ struct i2c_client *adc;
+ struct i2c_client *rtc;
+ struct mutex io_lock;
+ struct mutex irq_lock;
+
+ int irq_base;
+ int core_irq;
+ int tsc_irq;
+};
+
+struct max8925_backlight_pdata {
+ int lxw_scl; /* 0/1 -- 0.8Ohm/0.4Ohm */
+ int lxw_freq; /* 700KHz ~ 1400KHz */
+ int dual_string; /* 0/1 -- single/dual string */
+};
+
+struct max8925_touch_pdata {
+ unsigned int flags;
+};
+
+struct max8925_power_pdata {
+ int (*set_charger)(int);
+ unsigned batt_detect:1;
+ unsigned topoff_threshold:2;
+ unsigned fast_charge:3; /* charge current */
+};
+
+/*
+ * irq_base: stores IRQ base number of MAX8925 in platform
+ * tsc_irq: stores IRQ number of MAX8925 TSC
+ */
+struct max8925_platform_data {
+ struct max8925_backlight_pdata *backlight;
+ struct max8925_touch_pdata *touch;
+ struct max8925_power_pdata *power;
+ struct regulator_init_data *regulator[MAX8925_MAX_REGULATOR];
+
+ int irq_base;
+ int tsc_irq;
+};
+
+extern int max8925_reg_read(struct i2c_client *, int);
+extern int max8925_reg_write(struct i2c_client *, int, unsigned char);
+extern int max8925_bulk_read(struct i2c_client *, int, int, unsigned char *);
+extern int max8925_bulk_write(struct i2c_client *, int, int, unsigned char *);
+extern int max8925_set_bits(struct i2c_client *, int, unsigned char,
+ unsigned char);
+
+extern int max8925_device_init(struct max8925_chip *,
+ struct max8925_platform_data *);
+extern void max8925_device_exit(struct max8925_chip *);
+#endif /* __LINUX_MFD_MAX8925_H */
+
diff --git a/include/linux/mfd/mc13783.h b/include/linux/mfd/mc13783.h
index 94cb51a6403..8895d9d8879 100644
--- a/include/linux/mfd/mc13783.h
+++ b/include/linux/mfd/mc13783.h
@@ -26,10 +26,30 @@ int mc13783_irq_request(struct mc13783 *mc13783, int irq,
int mc13783_irq_request_nounmask(struct mc13783 *mc13783, int irq,
irq_handler_t handler, const char *name, void *dev);
int mc13783_irq_free(struct mc13783 *mc13783, int irq, void *dev);
-int mc13783_ackirq(struct mc13783 *mc13783, int irq);
-int mc13783_mask(struct mc13783 *mc13783, int irq);
-int mc13783_unmask(struct mc13783 *mc13783, int irq);
+int mc13783_irq_mask(struct mc13783 *mc13783, int irq);
+int mc13783_irq_unmask(struct mc13783 *mc13783, int irq);
+int mc13783_irq_status(struct mc13783 *mc13783, int irq,
+ int *enabled, int *pending);
+int mc13783_irq_ack(struct mc13783 *mc13783, int irq);
+
+static inline int mc13783_mask(struct mc13783 *mc13783, int irq) __deprecated;
+static inline int mc13783_mask(struct mc13783 *mc13783, int irq)
+{
+ return mc13783_irq_mask(mc13783, irq);
+}
+
+static inline int mc13783_unmask(struct mc13783 *mc13783, int irq) __deprecated;
+static inline int mc13783_unmask(struct mc13783 *mc13783, int irq)
+{
+ return mc13783_irq_unmask(mc13783, irq);
+}
+
+static inline int mc13783_ackirq(struct mc13783 *mc13783, int irq) __deprecated;
+static inline int mc13783_ackirq(struct mc13783 *mc13783, int irq)
+{
+ return mc13783_irq_ack(mc13783, irq);
+}
#define MC13783_ADC0 43
#define MC13783_ADC0_ADREFEN (1 << 10)
diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h
index 9cb1834deff..c3f7dff8eff 100644
--- a/include/linux/mfd/tmio.h
+++ b/include/linux/mfd/tmio.h
@@ -59,7 +59,8 @@ void tmio_core_mmc_clk_div(void __iomem *cnf, int shift, int state);
* data for the MMC controller
*/
struct tmio_mmc_data {
- const unsigned int hclk;
+ unsigned int hclk;
+ unsigned long capabilities;
void (*set_pwr)(struct platform_device *host, int state);
void (*set_clk_div)(struct platform_device *host, int state);
};
diff --git a/include/linux/mfd/ucb1x00.h b/include/linux/mfd/ucb1x00.h
index aa9c3789bed..4321f044d1e 100644
--- a/include/linux/mfd/ucb1x00.h
+++ b/include/linux/mfd/ucb1x00.h
@@ -12,6 +12,7 @@
#include <linux/mfd/mcp.h>
#include <linux/gpio.h>
+#include <linux/semaphore.h>
#define UCB_IO_DATA 0x00
#define UCB_IO_DIR 0x01
diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h
index 5184b79c700..5915f6e3d9a 100644
--- a/include/linux/mfd/wm831x/core.h
+++ b/include/linux/mfd/wm831x/core.h
@@ -15,6 +15,7 @@
#ifndef __MFD_WM831X_CORE_H__
#define __MFD_WM831X_CORE_H__
+#include <linux/completion.h>
#include <linux/interrupt.h>
/*
@@ -254,9 +255,14 @@ struct wm831x {
int irq_masks_cur[WM831X_NUM_IRQ_REGS]; /* Currently active value */
int irq_masks_cache[WM831X_NUM_IRQ_REGS]; /* Cached hardware value */
+ /* Chip revision based flags */
+ unsigned has_gpio_ena:1; /* Has GPIO enable bit */
+ unsigned has_cs_sts:1; /* Has current sink status bit */
+
int num_gpio;
struct mutex auxadc_lock;
+ struct completion auxadc_done;
/* The WM831x has a security key blocking access to certain
* registers. The mutex is taken by the accessors for locking
diff --git a/include/linux/mfd/wm831x/gpio.h b/include/linux/mfd/wm831x/gpio.h
index 2835614af0e..9b163c58865 100644
--- a/include/linux/mfd/wm831x/gpio.h
+++ b/include/linux/mfd/wm831x/gpio.h
@@ -41,6 +41,10 @@
#define WM831X_GPN_OD_MASK 0x0200 /* GPN_OD */
#define WM831X_GPN_OD_SHIFT 9 /* GPN_OD */
#define WM831X_GPN_OD_WIDTH 1 /* GPN_OD */
+#define WM831X_GPN_ENA 0x0080 /* GPN_ENA */
+#define WM831X_GPN_ENA_MASK 0x0080 /* GPN_ENA */
+#define WM831X_GPN_ENA_SHIFT 7 /* GPN_ENA */
+#define WM831X_GPN_ENA_WIDTH 1 /* GPN_ENA */
#define WM831X_GPN_TRI 0x0080 /* GPN_TRI */
#define WM831X_GPN_TRI_MASK 0x0080 /* GPN_TRI */
#define WM831X_GPN_TRI_SHIFT 7 /* GPN_TRI */
diff --git a/include/linux/mfd/wm8350/core.h b/include/linux/mfd/wm8350/core.h
index 43868899bf4..98fcc977e82 100644
--- a/include/linux/mfd/wm8350/core.h
+++ b/include/linux/mfd/wm8350/core.h
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/interrupt.h>
+#include <linux/completion.h>
#include <linux/mfd/wm8350/audio.h>
#include <linux/mfd/wm8350/gpio.h>
@@ -579,6 +580,8 @@
#define WM8350_NUM_IRQ 63
+#define WM8350_NUM_IRQ_REGS 7
+
struct wm8350_reg_access {
u16 readable; /* Mask of readable bits */
u16 writable; /* Mask of writable bits */
@@ -600,11 +603,6 @@ extern const u16 wm8352_mode3_defaults[];
struct wm8350;
-struct wm8350_irq {
- irq_handler_t handler;
- void *data;
-};
-
struct wm8350_hwmon {
struct platform_device *pdev;
struct device *classdev;
@@ -624,11 +622,13 @@ struct wm8350 {
u16 *reg_cache;
struct mutex auxadc_mutex;
+ struct completion auxadc_done;
/* Interrupt handling */
- struct mutex irq_mutex; /* IRQ table mutex */
- struct wm8350_irq irq[WM8350_NUM_IRQ];
+ struct mutex irq_lock;
int chip_irq;
+ int irq_base;
+ u16 irq_masks[WM8350_NUM_IRQ_REGS];
/* Client devices */
struct wm8350_codec codec;
@@ -647,11 +647,13 @@ struct wm8350 {
* used by the platform to configure GPIO functions and similar.
* @irq_high: Set if WM8350 IRQ is active high.
* @irq_base: Base IRQ for genirq (not currently used).
+ * @gpio_base: Base for gpiolib.
*/
struct wm8350_platform_data {
int (*init)(struct wm8350 *wm8350);
int irq_high;
int irq_base;
+ int gpio_base;
};
@@ -677,12 +679,33 @@ int wm8350_block_write(struct wm8350 *wm8350, int reg, int size, u16 *src);
/*
* WM8350 internal interrupts
*/
-int wm8350_register_irq(struct wm8350 *wm8350, int irq,
- irq_handler_t handler, unsigned long flags,
- const char *name, void *data);
-int wm8350_free_irq(struct wm8350 *wm8350, int irq);
-int wm8350_mask_irq(struct wm8350 *wm8350, int irq);
-int wm8350_unmask_irq(struct wm8350 *wm8350, int irq);
+static inline int wm8350_register_irq(struct wm8350 *wm8350, int irq,
+ irq_handler_t handler,
+ unsigned long flags,
+ const char *name, void *data)
+{
+ if (!wm8350->irq_base)
+ return -ENODEV;
+
+ return request_threaded_irq(irq + wm8350->irq_base, NULL,
+ handler, flags, name, data);
+}
+
+static inline void wm8350_free_irq(struct wm8350 *wm8350, int irq, void *data)
+{
+ free_irq(irq + wm8350->irq_base, data);
+}
+
+static inline void wm8350_mask_irq(struct wm8350 *wm8350, int irq)
+{
+ disable_irq(irq + wm8350->irq_base);
+}
+
+static inline void wm8350_unmask_irq(struct wm8350 *wm8350, int irq)
+{
+ enable_irq(irq + wm8350->irq_base);
+}
+
int wm8350_irq_init(struct wm8350 *wm8350, int irq,
struct wm8350_platform_data *pdata);
int wm8350_irq_exit(struct wm8350 *wm8350);
diff --git a/include/linux/mfd/wm8350/gpio.h b/include/linux/mfd/wm8350/gpio.h
index 71af3d6ebe9..d657bcd6d95 100644
--- a/include/linux/mfd/wm8350/gpio.h
+++ b/include/linux/mfd/wm8350/gpio.h
@@ -29,6 +29,7 @@
#define WM8350_GPIO_FUNCTION_SELECT_2 0x8D
#define WM8350_GPIO_FUNCTION_SELECT_3 0x8E
#define WM8350_GPIO_FUNCTION_SELECT_4 0x8F
+#define WM8350_GPIO_LEVEL 0xE6
/*
* GPIO Functions
diff --git a/include/linux/mfd/wm8350/rtc.h b/include/linux/mfd/wm8350/rtc.h
index 24add2bef6c..ebd72ffc62d 100644
--- a/include/linux/mfd/wm8350/rtc.h
+++ b/include/linux/mfd/wm8350/rtc.h
@@ -263,6 +263,7 @@ struct wm8350_rtc {
struct platform_device *pdev;
struct rtc_device *rtc;
int alarm_enabled; /* used over suspend/resume */
+ int update_enabled;
};
#endif
diff --git a/include/linux/mfd/wm8994/core.h b/include/linux/mfd/wm8994/core.h
new file mode 100644
index 00000000000..b06ff284674
--- /dev/null
+++ b/include/linux/mfd/wm8994/core.h
@@ -0,0 +1,54 @@
+/*
+ * include/linux/mfd/wm8994/core.h -- Core interface for WM8994
+ *
+ * Copyright 2009 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.
+ *
+ */
+
+#ifndef __MFD_WM8994_CORE_H__
+#define __MFD_WM8994_CORE_H__
+
+struct regulator_dev;
+struct regulator_bulk_data;
+
+#define WM8994_NUM_GPIO_REGS 11
+#define WM8994_NUM_LDO_REGS 2
+
+struct wm8994 {
+ struct mutex io_lock;
+
+ struct device *dev;
+ int (*read_dev)(struct wm8994 *wm8994, unsigned short reg,
+ int bytes, void *dest);
+ int (*write_dev)(struct wm8994 *wm8994, unsigned short reg,
+ int bytes, void *src);
+
+ void *control_data;
+
+ int gpio_base;
+
+ /* Used over suspend/resume */
+ u16 ldo_regs[WM8994_NUM_LDO_REGS];
+ u16 gpio_regs[WM8994_NUM_GPIO_REGS];
+
+ struct regulator_dev *dbvdd;
+ struct regulator_bulk_data *supplies;
+};
+
+/* Device I/O API */
+int wm8994_reg_read(struct wm8994 *wm8994, unsigned short reg);
+int wm8994_reg_write(struct wm8994 *wm8994, unsigned short reg,
+ unsigned short val);
+int wm8994_set_bits(struct wm8994 *wm8994, unsigned short reg,
+ unsigned short mask, unsigned short val);
+int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
+ int count, u16 *buf);
+
+#endif
diff --git a/include/linux/mfd/wm8994/gpio.h b/include/linux/mfd/wm8994/gpio.h
new file mode 100644
index 00000000000..b4d4c22991e
--- /dev/null
+++ b/include/linux/mfd/wm8994/gpio.h
@@ -0,0 +1,72 @@
+/*
+ * include/linux/mfd/wm8994/gpio.h - GPIO configuration for WM8994
+ *
+ * Copyright 2009 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.
+ *
+ */
+
+#ifndef __MFD_WM8994_GPIO_H__
+#define __MFD_WM8994_GPIO_H__
+
+#define WM8994_GPIO_MAX 11
+
+#define WM8994_GP_FN_PIN_SPECIFIC 0
+#define WM8994_GP_FN_GPIO 1
+#define WM8994_GP_FN_SDOUT 2
+#define WM8994_GP_FN_IRQ 3
+#define WM8994_GP_FN_TEMPERATURE 4
+#define WM8994_GP_FN_MICBIAS1_DET 5
+#define WM8994_GP_FN_MICBIAS1_SHORT 6
+#define WM8994_GP_FN_MICBIAS2_DET 7
+#define WM8994_GP_FN_MICBIAS2_SHORT 8
+#define WM8994_GP_FN_FLL1_LOCK 9
+#define WM8994_GP_FN_FLL2_LOCK 10
+#define WM8994_GP_FN_SRC1_LOCK 11
+#define WM8994_GP_FN_SRC2_LOCK 12
+#define WM8994_GP_FN_DRC1_ACT 13
+#define WM8994_GP_FN_DRC2_ACT 14
+#define WM8994_GP_FN_DRC3_ACT 15
+#define WM8994_GP_FN_WSEQ_STATUS 16
+#define WM8994_GP_FN_FIFO_ERROR 17
+#define WM8994_GP_FN_OPCLK 18
+
+#define WM8994_GPN_DIR 0x8000 /* GPN_DIR */
+#define WM8994_GPN_DIR_MASK 0x8000 /* GPN_DIR */
+#define WM8994_GPN_DIR_SHIFT 15 /* GPN_DIR */
+#define WM8994_GPN_DIR_WIDTH 1 /* GPN_DIR */
+#define WM8994_GPN_PU 0x4000 /* GPN_PU */
+#define WM8994_GPN_PU_MASK 0x4000 /* GPN_PU */
+#define WM8994_GPN_PU_SHIFT 14 /* GPN_PU */
+#define WM8994_GPN_PU_WIDTH 1 /* GPN_PU */
+#define WM8994_GPN_PD 0x2000 /* GPN_PD */
+#define WM8994_GPN_PD_MASK 0x2000 /* GPN_PD */
+#define WM8994_GPN_PD_SHIFT 13 /* GPN_PD */
+#define WM8994_GPN_PD_WIDTH 1 /* GPN_PD */
+#define WM8994_GPN_POL 0x0400 /* GPN_POL */
+#define WM8994_GPN_POL_MASK 0x0400 /* GPN_POL */
+#define WM8994_GPN_POL_SHIFT 10 /* GPN_POL */
+#define WM8994_GPN_POL_WIDTH 1 /* GPN_POL */
+#define WM8994_GPN_OP_CFG 0x0200 /* GPN_OP_CFG */
+#define WM8994_GPN_OP_CFG_MASK 0x0200 /* GPN_OP_CFG */
+#define WM8994_GPN_OP_CFG_SHIFT 9 /* GPN_OP_CFG */
+#define WM8994_GPN_OP_CFG_WIDTH 1 /* GPN_OP_CFG */
+#define WM8994_GPN_DB 0x0100 /* GPN_DB */
+#define WM8994_GPN_DB_MASK 0x0100 /* GPN_DB */
+#define WM8994_GPN_DB_SHIFT 8 /* GPN_DB */
+#define WM8994_GPN_DB_WIDTH 1 /* GPN_DB */
+#define WM8994_GPN_LVL 0x0040 /* GPN_LVL */
+#define WM8994_GPN_LVL_MASK 0x0040 /* GPN_LVL */
+#define WM8994_GPN_LVL_SHIFT 6 /* GPN_LVL */
+#define WM8994_GPN_LVL_WIDTH 1 /* GPN_LVL */
+#define WM8994_GPN_FN_MASK 0x001F /* GPN_FN - [4:0] */
+#define WM8994_GPN_FN_SHIFT 0 /* GPN_FN - [4:0] */
+#define WM8994_GPN_FN_WIDTH 5 /* GPN_FN - [4:0] */
+
+#endif
diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h
new file mode 100644
index 00000000000..70d6a8687dc
--- /dev/null
+++ b/include/linux/mfd/wm8994/pdata.h
@@ -0,0 +1,97 @@
+/*
+ * include/linux/mfd/wm8994/pdata.h -- Platform data for WM8994
+ *
+ * Copyright 2009 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.
+ *
+ */
+
+#ifndef __MFD_WM8994_PDATA_H__
+#define __MFD_WM8994_PDATA_H__
+
+#define WM8994_NUM_LDO 2
+#define WM8994_NUM_GPIO 11
+
+struct wm8994_ldo_pdata {
+ /** GPIOs to enable regulator, 0 or less if not available */
+ int enable;
+
+ const char *supply;
+ struct regulator_init_data *init_data;
+};
+
+#define WM8994_CONFIGURE_GPIO 0x8000
+
+#define WM8994_DRC_REGS 5
+#define WM8994_EQ_REGS 19
+
+/**
+ * DRC configurations are specified with a label and a set of register
+ * values to write (the enable bits will be ignored). At runtime an
+ * enumerated control will be presented for each DRC block allowing
+ * the user to choose the configration to use.
+ *
+ * Configurations may be generated by hand or by using the DRC control
+ * panel provided by the WISCE - see http://www.wolfsonmicro.com/wisce/
+ * for details.
+ */
+struct wm8994_drc_cfg {
+ const char *name;
+ u16 regs[WM8994_DRC_REGS];
+};
+
+/**
+ * ReTune Mobile configurations are specified with a label, sample
+ * rate and set of values to write (the enable bits will be ignored).
+ *
+ * Configurations are expected to be generated using the ReTune Mobile
+ * control panel in WISCE - see http://www.wolfsonmicro.com/wisce/
+ */
+struct wm8994_retune_mobile_cfg {
+ const char *name;
+ unsigned int rate;
+ u16 regs[WM8994_EQ_REGS];
+};
+
+struct wm8994_pdata {
+ int gpio_base;
+
+ /**
+ * Default values for GPIOs if non-zero, WM8994_CONFIGURE_GPIO
+ * can be used for all zero values.
+ */
+ int gpio_defaults[WM8994_NUM_GPIO];
+
+ struct wm8994_ldo_pdata ldo[WM8994_NUM_LDO];
+
+
+ int num_drc_cfgs;
+ struct wm8994_drc_cfg *drc_cfgs;
+
+ int num_retune_mobile_cfgs;
+ struct wm8994_retune_mobile_cfg *retune_mobile_cfgs;
+
+ /* LINEOUT can be differential or single ended */
+ unsigned int lineout1_diff:1;
+ unsigned int lineout2_diff:1;
+
+ /* Common mode feedback */
+ unsigned int lineout1fb:1;
+ unsigned int lineout2fb:1;
+
+ /* Microphone biases: 0=0.9*AVDD1 1=0.65*AVVD1 */
+ unsigned int micbias1_lvl:1;
+ unsigned int micbias2_lvl:1;
+
+ /* Jack detect threashold levels, see datasheet for values */
+ unsigned int jd_scthr:2;
+ unsigned int jd_thr:2;
+};
+
+#endif
diff --git a/include/linux/mfd/wm8994/registers.h b/include/linux/mfd/wm8994/registers.h
new file mode 100644
index 00000000000..967f62f5415
--- /dev/null
+++ b/include/linux/mfd/wm8994/registers.h
@@ -0,0 +1,4292 @@
+/*
+ * include/linux/mfd/wm8994/registers.h -- Register definitions for WM8994
+ *
+ * Copyright 2009 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.
+ *
+ */
+
+#ifndef __MFD_WM8994_REGISTERS_H__
+#define __MFD_WM8994_REGISTERS_H__
+
+/*
+ * Register values.
+ */
+#define WM8994_SOFTWARE_RESET 0x00
+#define WM8994_POWER_MANAGEMENT_1 0x01
+#define WM8994_POWER_MANAGEMENT_2 0x02
+#define WM8994_POWER_MANAGEMENT_3 0x03
+#define WM8994_POWER_MANAGEMENT_4 0x04
+#define WM8994_POWER_MANAGEMENT_5 0x05
+#define WM8994_POWER_MANAGEMENT_6 0x06
+#define WM8994_INPUT_MIXER_1 0x15
+#define WM8994_LEFT_LINE_INPUT_1_2_VOLUME 0x18
+#define WM8994_LEFT_LINE_INPUT_3_4_VOLUME 0x19
+#define WM8994_RIGHT_LINE_INPUT_1_2_VOLUME 0x1A
+#define WM8994_RIGHT_LINE_INPUT_3_4_VOLUME 0x1B
+#define WM8994_LEFT_OUTPUT_VOLUME 0x1C
+#define WM8994_RIGHT_OUTPUT_VOLUME 0x1D
+#define WM8994_LINE_OUTPUTS_VOLUME 0x1E
+#define WM8994_HPOUT2_VOLUME 0x1F
+#define WM8994_LEFT_OPGA_VOLUME 0x20
+#define WM8994_RIGHT_OPGA_VOLUME 0x21
+#define WM8994_SPKMIXL_ATTENUATION 0x22
+#define WM8994_SPKMIXR_ATTENUATION 0x23
+#define WM8994_SPKOUT_MIXERS 0x24
+#define WM8994_CLASSD 0x25
+#define WM8994_SPEAKER_VOLUME_LEFT 0x26
+#define WM8994_SPEAKER_VOLUME_RIGHT 0x27
+#define WM8994_INPUT_MIXER_2 0x28
+#define WM8994_INPUT_MIXER_3 0x29
+#define WM8994_INPUT_MIXER_4 0x2A
+#define WM8994_INPUT_MIXER_5 0x2B
+#define WM8994_INPUT_MIXER_6 0x2C
+#define WM8994_OUTPUT_MIXER_1 0x2D
+#define WM8994_OUTPUT_MIXER_2 0x2E
+#define WM8994_OUTPUT_MIXER_3 0x2F
+#define WM8994_OUTPUT_MIXER_4 0x30
+#define WM8994_OUTPUT_MIXER_5 0x31
+#define WM8994_OUTPUT_MIXER_6 0x32
+#define WM8994_HPOUT2_MIXER 0x33
+#define WM8994_LINE_MIXER_1 0x34
+#define WM8994_LINE_MIXER_2 0x35
+#define WM8994_SPEAKER_MIXER 0x36
+#define WM8994_ADDITIONAL_CONTROL 0x37
+#define WM8994_ANTIPOP_1 0x38
+#define WM8994_ANTIPOP_2 0x39
+#define WM8994_MICBIAS 0x3A
+#define WM8994_LDO_1 0x3B
+#define WM8994_LDO_2 0x3C
+#define WM8994_CHARGE_PUMP_1 0x4C
+#define WM8994_CLASS_W_1 0x51
+#define WM8994_DC_SERVO_1 0x54
+#define WM8994_DC_SERVO_2 0x55
+#define WM8994_DC_SERVO_4 0x57
+#define WM8994_DC_SERVO_READBACK 0x58
+#define WM8994_ANALOGUE_HP_1 0x60
+#define WM8994_CHIP_REVISION 0x100
+#define WM8994_CONTROL_INTERFACE 0x101
+#define WM8994_WRITE_SEQUENCER_CTRL_1 0x110
+#define WM8994_WRITE_SEQUENCER_CTRL_2 0x111
+#define WM8994_AIF1_CLOCKING_1 0x200
+#define WM8994_AIF1_CLOCKING_2 0x201
+#define WM8994_AIF2_CLOCKING_1 0x204
+#define WM8994_AIF2_CLOCKING_2 0x205
+#define WM8994_CLOCKING_1 0x208
+#define WM8994_CLOCKING_2 0x209
+#define WM8994_AIF1_RATE 0x210
+#define WM8994_AIF2_RATE 0x211
+#define WM8994_RATE_STATUS 0x212
+#define WM8994_FLL1_CONTROL_1 0x220
+#define WM8994_FLL1_CONTROL_2 0x221
+#define WM8994_FLL1_CONTROL_3 0x222
+#define WM8994_FLL1_CONTROL_4 0x223
+#define WM8994_FLL1_CONTROL_5 0x224
+#define WM8994_FLL2_CONTROL_1 0x240
+#define WM8994_FLL2_CONTROL_2 0x241
+#define WM8994_FLL2_CONTROL_3 0x242
+#define WM8994_FLL2_CONTROL_4 0x243
+#define WM8994_FLL2_CONTROL_5 0x244
+#define WM8994_AIF1_CONTROL_1 0x300
+#define WM8994_AIF1_CONTROL_2 0x301
+#define WM8994_AIF1_MASTER_SLAVE 0x302
+#define WM8994_AIF1_BCLK 0x303
+#define WM8994_AIF1ADC_LRCLK 0x304
+#define WM8994_AIF1DAC_LRCLK 0x305
+#define WM8994_AIF1DAC_DATA 0x306
+#define WM8994_AIF1ADC_DATA 0x307
+#define WM8994_AIF2_CONTROL_1 0x310
+#define WM8994_AIF2_CONTROL_2 0x311
+#define WM8994_AIF2_MASTER_SLAVE 0x312
+#define WM8994_AIF2_BCLK 0x313
+#define WM8994_AIF2ADC_LRCLK 0x314
+#define WM8994_AIF2DAC_LRCLK 0x315
+#define WM8994_AIF2DAC_DATA 0x316
+#define WM8994_AIF2ADC_DATA 0x317
+#define WM8994_AIF1_ADC1_LEFT_VOLUME 0x400
+#define WM8994_AIF1_ADC1_RIGHT_VOLUME 0x401
+#define WM8994_AIF1_DAC1_LEFT_VOLUME 0x402
+#define WM8994_AIF1_DAC1_RIGHT_VOLUME 0x403
+#define WM8994_AIF1_ADC2_LEFT_VOLUME 0x404
+#define WM8994_AIF1_ADC2_RIGHT_VOLUME 0x405
+#define WM8994_AIF1_DAC2_LEFT_VOLUME 0x406
+#define WM8994_AIF1_DAC2_RIGHT_VOLUME 0x407
+#define WM8994_AIF1_ADC1_FILTERS 0x410
+#define WM8994_AIF1_ADC2_FILTERS 0x411
+#define WM8994_AIF1_DAC1_FILTERS_1 0x420
+#define WM8994_AIF1_DAC1_FILTERS_2 0x421
+#define WM8994_AIF1_DAC2_FILTERS_1 0x422
+#define WM8994_AIF1_DAC2_FILTERS_2 0x423
+#define WM8994_AIF1_DRC1_1 0x440
+#define WM8994_AIF1_DRC1_2 0x441
+#define WM8994_AIF1_DRC1_3 0x442
+#define WM8994_AIF1_DRC1_4 0x443
+#define WM8994_AIF1_DRC1_5 0x444
+#define WM8994_AIF1_DRC2_1 0x450
+#define WM8994_AIF1_DRC2_2 0x451
+#define WM8994_AIF1_DRC2_3 0x452
+#define WM8994_AIF1_DRC2_4 0x453
+#define WM8994_AIF1_DRC2_5 0x454
+#define WM8994_AIF1_DAC1_EQ_GAINS_1 0x480
+#define WM8994_AIF1_DAC1_EQ_GAINS_2 0x481
+#define WM8994_AIF1_DAC1_EQ_BAND_1_A 0x482
+#define WM8994_AIF1_DAC1_EQ_BAND_1_B 0x483
+#define WM8994_AIF1_DAC1_EQ_BAND_1_PG 0x484
+#define WM8994_AIF1_DAC1_EQ_BAND_2_A 0x485
+#define WM8994_AIF1_DAC1_EQ_BAND_2_B 0x486
+#define WM8994_AIF1_DAC1_EQ_BAND_2_C 0x487
+#define WM8994_AIF1_DAC1_EQ_BAND_2_PG 0x488
+#define WM8994_AIF1_DAC1_EQ_BAND_3_A 0x489
+#define WM8994_AIF1_DAC1_EQ_BAND_3_B 0x48A
+#define WM8994_AIF1_DAC1_EQ_BAND_3_C 0x48B
+#define WM8994_AIF1_DAC1_EQ_BAND_3_PG 0x48C
+#define WM8994_AIF1_DAC1_EQ_BAND_4_A 0x48D
+#define WM8994_AIF1_DAC1_EQ_BAND_4_B 0x48E
+#define WM8994_AIF1_DAC1_EQ_BAND_4_C 0x48F
+#define WM8994_AIF1_DAC1_EQ_BAND_4_PG 0x490
+#define WM8994_AIF1_DAC1_EQ_BAND_5_A 0x491
+#define WM8994_AIF1_DAC1_EQ_BAND_5_B 0x492
+#define WM8994_AIF1_DAC1_EQ_BAND_5_PG 0x493
+#define WM8994_AIF1_DAC2_EQ_GAINS_1 0x4A0
+#define WM8994_AIF1_DAC2_EQ_GAINS_2 0x4A1
+#define WM8994_AIF1_DAC2_EQ_BAND_1_A 0x4A2
+#define WM8994_AIF1_DAC2_EQ_BAND_1_B 0x4A3
+#define WM8994_AIF1_DAC2_EQ_BAND_1_PG 0x4A4
+#define WM8994_AIF1_DAC2_EQ_BAND_2_A 0x4A5
+#define WM8994_AIF1_DAC2_EQ_BAND_2_B 0x4A6
+#define WM8994_AIF1_DAC2_EQ_BAND_2_C 0x4A7
+#define WM8994_AIF1_DAC2_EQ_BAND_2_PG 0x4A8
+#define WM8994_AIF1_DAC2_EQ_BAND_3_A 0x4A9
+#define WM8994_AIF1_DAC2_EQ_BAND_3_B 0x4AA
+#define WM8994_AIF1_DAC2_EQ_BAND_3_C 0x4AB
+#define WM8994_AIF1_DAC2_EQ_BAND_3_PG 0x4AC
+#define WM8994_AIF1_DAC2_EQ_BAND_4_A 0x4AD
+#define WM8994_AIF1_DAC2_EQ_BAND_4_B 0x4AE
+#define WM8994_AIF1_DAC2_EQ_BAND_4_C 0x4AF
+#define WM8994_AIF1_DAC2_EQ_BAND_4_PG 0x4B0
+#define WM8994_AIF1_DAC2_EQ_BAND_5_A 0x4B1
+#define WM8994_AIF1_DAC2_EQ_BAND_5_B 0x4B2
+#define WM8994_AIF1_DAC2_EQ_BAND_5_PG 0x4B3
+#define WM8994_AIF2_ADC_LEFT_VOLUME 0x500
+#define WM8994_AIF2_ADC_RIGHT_VOLUME 0x501
+#define WM8994_AIF2_DAC_LEFT_VOLUME 0x502
+#define WM8994_AIF2_DAC_RIGHT_VOLUME 0x503
+#define WM8994_AIF2_ADC_FILTERS 0x510
+#define WM8994_AIF2_DAC_FILTERS_1 0x520
+#define WM8994_AIF2_DAC_FILTERS_2 0x521
+#define WM8994_AIF2_DRC_1 0x540
+#define WM8994_AIF2_DRC_2 0x541
+#define WM8994_AIF2_DRC_3 0x542
+#define WM8994_AIF2_DRC_4 0x543
+#define WM8994_AIF2_DRC_5 0x544
+#define WM8994_AIF2_EQ_GAINS_1 0x580
+#define WM8994_AIF2_EQ_GAINS_2 0x581
+#define WM8994_AIF2_EQ_BAND_1_A 0x582
+#define WM8994_AIF2_EQ_BAND_1_B 0x583
+#define WM8994_AIF2_EQ_BAND_1_PG 0x584
+#define WM8994_AIF2_EQ_BAND_2_A 0x585
+#define WM8994_AIF2_EQ_BAND_2_B 0x586
+#define WM8994_AIF2_EQ_BAND_2_C 0x587
+#define WM8994_AIF2_EQ_BAND_2_PG 0x588
+#define WM8994_AIF2_EQ_BAND_3_A 0x589
+#define WM8994_AIF2_EQ_BAND_3_B 0x58A
+#define WM8994_AIF2_EQ_BAND_3_C 0x58B
+#define WM8994_AIF2_EQ_BAND_3_PG 0x58C
+#define WM8994_AIF2_EQ_BAND_4_A 0x58D
+#define WM8994_AIF2_EQ_BAND_4_B 0x58E
+#define WM8994_AIF2_EQ_BAND_4_C 0x58F
+#define WM8994_AIF2_EQ_BAND_4_PG 0x590
+#define WM8994_AIF2_EQ_BAND_5_A 0x591
+#define WM8994_AIF2_EQ_BAND_5_B 0x592
+#define WM8994_AIF2_EQ_BAND_5_PG 0x593
+#define WM8994_DAC1_MIXER_VOLUMES 0x600
+#define WM8994_DAC1_LEFT_MIXER_ROUTING 0x601
+#define WM8994_DAC1_RIGHT_MIXER_ROUTING 0x602
+#define WM8994_DAC2_MIXER_VOLUMES 0x603
+#define WM8994_DAC2_LEFT_MIXER_ROUTING 0x604
+#define WM8994_DAC2_RIGHT_MIXER_ROUTING 0x605
+#define WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING 0x606
+#define WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING 0x607
+#define WM8994_AIF1_ADC2_LEFT_MIXER_ROUTING 0x608
+#define WM8994_AIF1_ADC2_RIGHT_MIXER_ROUTING 0x609
+#define WM8994_DAC1_LEFT_VOLUME 0x610
+#define WM8994_DAC1_RIGHT_VOLUME 0x611
+#define WM8994_DAC2_LEFT_VOLUME 0x612
+#define WM8994_DAC2_RIGHT_VOLUME 0x613
+#define WM8994_DAC_SOFTMUTE 0x614
+#define WM8994_OVERSAMPLING 0x620
+#define WM8994_SIDETONE 0x621
+#define WM8994_GPIO_1 0x700
+#define WM8994_GPIO_2 0x701
+#define WM8994_GPIO_3 0x702
+#define WM8994_GPIO_4 0x703
+#define WM8994_GPIO_5 0x704
+#define WM8994_GPIO_6 0x705
+#define WM8994_GPIO_7 0x706
+#define WM8994_GPIO_8 0x707
+#define WM8994_GPIO_9 0x708
+#define WM8994_GPIO_10 0x709
+#define WM8994_GPIO_11 0x70A
+#define WM8994_PULL_CONTROL_1 0x720
+#define WM8994_PULL_CONTROL_2 0x721
+#define WM8994_INTERRUPT_STATUS_1 0x730
+#define WM8994_INTERRUPT_STATUS_2 0x731
+#define WM8994_INTERRUPT_RAW_STATUS_2 0x732
+#define WM8994_INTERRUPT_STATUS_1_MASK 0x738
+#define WM8994_INTERRUPT_STATUS_2_MASK 0x739
+#define WM8994_INTERRUPT_CONTROL 0x740
+#define WM8994_IRQ_DEBOUNCE 0x748
+#define WM8994_WRITE_SEQUENCER_0 0x3000
+#define WM8994_WRITE_SEQUENCER_1 0x3001
+#define WM8994_WRITE_SEQUENCER_2 0x3002
+#define WM8994_WRITE_SEQUENCER_3 0x3003
+#define WM8994_WRITE_SEQUENCER_4 0x3004
+#define WM8994_WRITE_SEQUENCER_5 0x3005
+#define WM8994_WRITE_SEQUENCER_6 0x3006
+#define WM8994_WRITE_SEQUENCER_7 0x3007
+#define WM8994_WRITE_SEQUENCER_8 0x3008
+#define WM8994_WRITE_SEQUENCER_9 0x3009
+#define WM8994_WRITE_SEQUENCER_10 0x300A
+#define WM8994_WRITE_SEQUENCER_11 0x300B
+#define WM8994_WRITE_SEQUENCER_12 0x300C
+#define WM8994_WRITE_SEQUENCER_13 0x300D
+#define WM8994_WRITE_SEQUENCER_14 0x300E
+#define WM8994_WRITE_SEQUENCER_15 0x300F
+#define WM8994_WRITE_SEQUENCER_16 0x3010
+#define WM8994_WRITE_SEQUENCER_17 0x3011
+#define WM8994_WRITE_SEQUENCER_18 0x3012
+#define WM8994_WRITE_SEQUENCER_19 0x3013
+#define WM8994_WRITE_SEQUENCER_20 0x3014
+#define WM8994_WRITE_SEQUENCER_21 0x3015
+#define WM8994_WRITE_SEQUENCER_22 0x3016
+#define WM8994_WRITE_SEQUENCER_23 0x3017
+#define WM8994_WRITE_SEQUENCER_24 0x3018
+#define WM8994_WRITE_SEQUENCER_25 0x3019
+#define WM8994_WRITE_SEQUENCER_26 0x301A
+#define WM8994_WRITE_SEQUENCER_27 0x301B
+#define WM8994_WRITE_SEQUENCER_28 0x301C
+#define WM8994_WRITE_SEQUENCER_29 0x301D
+#define WM8994_WRITE_SEQUENCER_30 0x301E
+#define WM8994_WRITE_SEQUENCER_31 0x301F
+#define WM8994_WRITE_SEQUENCER_32 0x3020
+#define WM8994_WRITE_SEQUENCER_33 0x3021
+#define WM8994_WRITE_SEQUENCER_34 0x3022
+#define WM8994_WRITE_SEQUENCER_35 0x3023
+#define WM8994_WRITE_SEQUENCER_36 0x3024
+#define WM8994_WRITE_SEQUENCER_37 0x3025
+#define WM8994_WRITE_SEQUENCER_38 0x3026
+#define WM8994_WRITE_SEQUENCER_39 0x3027
+#define WM8994_WRITE_SEQUENCER_40 0x3028
+#define WM8994_WRITE_SEQUENCER_41 0x3029
+#define WM8994_WRITE_SEQUENCER_42 0x302A
+#define WM8994_WRITE_SEQUENCER_43 0x302B
+#define WM8994_WRITE_SEQUENCER_44 0x302C
+#define WM8994_WRITE_SEQUENCER_45 0x302D
+#define WM8994_WRITE_SEQUENCER_46 0x302E
+#define WM8994_WRITE_SEQUENCER_47 0x302F
+#define WM8994_WRITE_SEQUENCER_48 0x3030
+#define WM8994_WRITE_SEQUENCER_49 0x3031
+#define WM8994_WRITE_SEQUENCER_50 0x3032
+#define WM8994_WRITE_SEQUENCER_51 0x3033
+#define WM8994_WRITE_SEQUENCER_52 0x3034
+#define WM8994_WRITE_SEQUENCER_53 0x3035
+#define WM8994_WRITE_SEQUENCER_54 0x3036
+#define WM8994_WRITE_SEQUENCER_55 0x3037
+#define WM8994_WRITE_SEQUENCER_56 0x3038
+#define WM8994_WRITE_SEQUENCER_57 0x3039
+#define WM8994_WRITE_SEQUENCER_58 0x303A
+#define WM8994_WRITE_SEQUENCER_59 0x303B
+#define WM8994_WRITE_SEQUENCER_60 0x303C
+#define WM8994_WRITE_SEQUENCER_61 0x303D
+#define WM8994_WRITE_SEQUENCER_62 0x303E
+#define WM8994_WRITE_SEQUENCER_63 0x303F
+#define WM8994_WRITE_SEQUENCER_64 0x3040
+#define WM8994_WRITE_SEQUENCER_65 0x3041
+#define WM8994_WRITE_SEQUENCER_66 0x3042
+#define WM8994_WRITE_SEQUENCER_67 0x3043
+#define WM8994_WRITE_SEQUENCER_68 0x3044
+#define WM8994_WRITE_SEQUENCER_69 0x3045
+#define WM8994_WRITE_SEQUENCER_70 0x3046
+#define WM8994_WRITE_SEQUENCER_71 0x3047
+#define WM8994_WRITE_SEQUENCER_72 0x3048
+#define WM8994_WRITE_SEQUENCER_73 0x3049
+#define WM8994_WRITE_SEQUENCER_74 0x304A
+#define WM8994_WRITE_SEQUENCER_75 0x304B
+#define WM8994_WRITE_SEQUENCER_76 0x304C
+#define WM8994_WRITE_SEQUENCER_77 0x304D
+#define WM8994_WRITE_SEQUENCER_78 0x304E
+#define WM8994_WRITE_SEQUENCER_79 0x304F
+#define WM8994_WRITE_SEQUENCER_80 0x3050
+#define WM8994_WRITE_SEQUENCER_81 0x3051
+#define WM8994_WRITE_SEQUENCER_82 0x3052
+#define WM8994_WRITE_SEQUENCER_83 0x3053
+#define WM8994_WRITE_SEQUENCER_84 0x3054
+#define WM8994_WRITE_SEQUENCER_85 0x3055
+#define WM8994_WRITE_SEQUENCER_86 0x3056
+#define WM8994_WRITE_SEQUENCER_87 0x3057
+#define WM8994_WRITE_SEQUENCER_88 0x3058
+#define WM8994_WRITE_SEQUENCER_89 0x3059
+#define WM8994_WRITE_SEQUENCER_90 0x305A
+#define WM8994_WRITE_SEQUENCER_91 0x305B
+#define WM8994_WRITE_SEQUENCER_92 0x305C
+#define WM8994_WRITE_SEQUENCER_93 0x305D
+#define WM8994_WRITE_SEQUENCER_94 0x305E
+#define WM8994_WRITE_SEQUENCER_95 0x305F
+#define WM8994_WRITE_SEQUENCER_96 0x3060
+#define WM8994_WRITE_SEQUENCER_97 0x3061
+#define WM8994_WRITE_SEQUENCER_98 0x3062
+#define WM8994_WRITE_SEQUENCER_99 0x3063
+#define WM8994_WRITE_SEQUENCER_100 0x3064
+#define WM8994_WRITE_SEQUENCER_101 0x3065
+#define WM8994_WRITE_SEQUENCER_102 0x3066
+#define WM8994_WRITE_SEQUENCER_103 0x3067
+#define WM8994_WRITE_SEQUENCER_104 0x3068
+#define WM8994_WRITE_SEQUENCER_105 0x3069
+#define WM8994_WRITE_SEQUENCER_106 0x306A
+#define WM8994_WRITE_SEQUENCER_107 0x306B
+#define WM8994_WRITE_SEQUENCER_108 0x306C
+#define WM8994_WRITE_SEQUENCER_109 0x306D
+#define WM8994_WRITE_SEQUENCER_110 0x306E
+#define WM8994_WRITE_SEQUENCER_111 0x306F
+#define WM8994_WRITE_SEQUENCER_112 0x3070
+#define WM8994_WRITE_SEQUENCER_113 0x3071
+#define WM8994_WRITE_SEQUENCER_114 0x3072
+#define WM8994_WRITE_SEQUENCER_115 0x3073
+#define WM8994_WRITE_SEQUENCER_116 0x3074
+#define WM8994_WRITE_SEQUENCER_117 0x3075
+#define WM8994_WRITE_SEQUENCER_118 0x3076
+#define WM8994_WRITE_SEQUENCER_119 0x3077
+#define WM8994_WRITE_SEQUENCER_120 0x3078
+#define WM8994_WRITE_SEQUENCER_121 0x3079
+#define WM8994_WRITE_SEQUENCER_122 0x307A
+#define WM8994_WRITE_SEQUENCER_123 0x307B
+#define WM8994_WRITE_SEQUENCER_124 0x307C
+#define WM8994_WRITE_SEQUENCER_125 0x307D
+#define WM8994_WRITE_SEQUENCER_126 0x307E
+#define WM8994_WRITE_SEQUENCER_127 0x307F
+#define WM8994_WRITE_SEQUENCER_128 0x3080
+#define WM8994_WRITE_SEQUENCER_129 0x3081
+#define WM8994_WRITE_SEQUENCER_130 0x3082
+#define WM8994_WRITE_SEQUENCER_131 0x3083
+#define WM8994_WRITE_SEQUENCER_132 0x3084
+#define WM8994_WRITE_SEQUENCER_133 0x3085
+#define WM8994_WRITE_SEQUENCER_134 0x3086
+#define WM8994_WRITE_SEQUENCER_135 0x3087
+#define WM8994_WRITE_SEQUENCER_136 0x3088
+#define WM8994_WRITE_SEQUENCER_137 0x3089
+#define WM8994_WRITE_SEQUENCER_138 0x308A
+#define WM8994_WRITE_SEQUENCER_139 0x308B
+#define WM8994_WRITE_SEQUENCER_140 0x308C
+#define WM8994_WRITE_SEQUENCER_141 0x308D
+#define WM8994_WRITE_SEQUENCER_142 0x308E
+#define WM8994_WRITE_SEQUENCER_143 0x308F
+#define WM8994_WRITE_SEQUENCER_144 0x3090
+#define WM8994_WRITE_SEQUENCER_145 0x3091
+#define WM8994_WRITE_SEQUENCER_146 0x3092
+#define WM8994_WRITE_SEQUENCER_147 0x3093
+#define WM8994_WRITE_SEQUENCER_148 0x3094
+#define WM8994_WRITE_SEQUENCER_149 0x3095
+#define WM8994_WRITE_SEQUENCER_150 0x3096
+#define WM8994_WRITE_SEQUENCER_151 0x3097
+#define WM8994_WRITE_SEQUENCER_152 0x3098
+#define WM8994_WRITE_SEQUENCER_153 0x3099
+#define WM8994_WRITE_SEQUENCER_154 0x309A
+#define WM8994_WRITE_SEQUENCER_155 0x309B
+#define WM8994_WRITE_SEQUENCER_156 0x309C
+#define WM8994_WRITE_SEQUENCER_157 0x309D
+#define WM8994_WRITE_SEQUENCER_158 0x309E
+#define WM8994_WRITE_SEQUENCER_159 0x309F
+#define WM8994_WRITE_SEQUENCER_160 0x30A0
+#define WM8994_WRITE_SEQUENCER_161 0x30A1
+#define WM8994_WRITE_SEQUENCER_162 0x30A2
+#define WM8994_WRITE_SEQUENCER_163 0x30A3
+#define WM8994_WRITE_SEQUENCER_164 0x30A4
+#define WM8994_WRITE_SEQUENCER_165 0x30A5
+#define WM8994_WRITE_SEQUENCER_166 0x30A6
+#define WM8994_WRITE_SEQUENCER_167 0x30A7
+#define WM8994_WRITE_SEQUENCER_168 0x30A8
+#define WM8994_WRITE_SEQUENCER_169 0x30A9
+#define WM8994_WRITE_SEQUENCER_170 0x30AA
+#define WM8994_WRITE_SEQUENCER_171 0x30AB
+#define WM8994_WRITE_SEQUENCER_172 0x30AC
+#define WM8994_WRITE_SEQUENCER_173 0x30AD
+#define WM8994_WRITE_SEQUENCER_174 0x30AE
+#define WM8994_WRITE_SEQUENCER_175 0x30AF
+#define WM8994_WRITE_SEQUENCER_176 0x30B0
+#define WM8994_WRITE_SEQUENCER_177 0x30B1
+#define WM8994_WRITE_SEQUENCER_178 0x30B2
+#define WM8994_WRITE_SEQUENCER_179 0x30B3
+#define WM8994_WRITE_SEQUENCER_180 0x30B4
+#define WM8994_WRITE_SEQUENCER_181 0x30B5
+#define WM8994_WRITE_SEQUENCER_182 0x30B6
+#define WM8994_WRITE_SEQUENCER_183 0x30B7
+#define WM8994_WRITE_SEQUENCER_184 0x30B8
+#define WM8994_WRITE_SEQUENCER_185 0x30B9
+#define WM8994_WRITE_SEQUENCER_186 0x30BA
+#define WM8994_WRITE_SEQUENCER_187 0x30BB
+#define WM8994_WRITE_SEQUENCER_188 0x30BC
+#define WM8994_WRITE_SEQUENCER_189 0x30BD
+#define WM8994_WRITE_SEQUENCER_190 0x30BE
+#define WM8994_WRITE_SEQUENCER_191 0x30BF
+#define WM8994_WRITE_SEQUENCER_192 0x30C0
+#define WM8994_WRITE_SEQUENCER_193 0x30C1
+#define WM8994_WRITE_SEQUENCER_194 0x30C2
+#define WM8994_WRITE_SEQUENCER_195 0x30C3
+#define WM8994_WRITE_SEQUENCER_196 0x30C4
+#define WM8994_WRITE_SEQUENCER_197 0x30C5
+#define WM8994_WRITE_SEQUENCER_198 0x30C6
+#define WM8994_WRITE_SEQUENCER_199 0x30C7
+#define WM8994_WRITE_SEQUENCER_200 0x30C8
+#define WM8994_WRITE_SEQUENCER_201 0x30C9
+#define WM8994_WRITE_SEQUENCER_202 0x30CA
+#define WM8994_WRITE_SEQUENCER_203 0x30CB
+#define WM8994_WRITE_SEQUENCER_204 0x30CC
+#define WM8994_WRITE_SEQUENCER_205 0x30CD
+#define WM8994_WRITE_SEQUENCER_206 0x30CE
+#define WM8994_WRITE_SEQUENCER_207 0x30CF
+#define WM8994_WRITE_SEQUENCER_208 0x30D0
+#define WM8994_WRITE_SEQUENCER_209 0x30D1
+#define WM8994_WRITE_SEQUENCER_210 0x30D2
+#define WM8994_WRITE_SEQUENCER_211 0x30D3
+#define WM8994_WRITE_SEQUENCER_212 0x30D4
+#define WM8994_WRITE_SEQUENCER_213 0x30D5
+#define WM8994_WRITE_SEQUENCER_214 0x30D6
+#define WM8994_WRITE_SEQUENCER_215 0x30D7
+#define WM8994_WRITE_SEQUENCER_216 0x30D8
+#define WM8994_WRITE_SEQUENCER_217 0x30D9
+#define WM8994_WRITE_SEQUENCER_218 0x30DA
+#define WM8994_WRITE_SEQUENCER_219 0x30DB
+#define WM8994_WRITE_SEQUENCER_220 0x30DC
+#define WM8994_WRITE_SEQUENCER_221 0x30DD
+#define WM8994_WRITE_SEQUENCER_222 0x30DE
+#define WM8994_WRITE_SEQUENCER_223 0x30DF
+#define WM8994_WRITE_SEQUENCER_224 0x30E0
+#define WM8994_WRITE_SEQUENCER_225 0x30E1
+#define WM8994_WRITE_SEQUENCER_226 0x30E2
+#define WM8994_WRITE_SEQUENCER_227 0x30E3
+#define WM8994_WRITE_SEQUENCER_228 0x30E4
+#define WM8994_WRITE_SEQUENCER_229 0x30E5
+#define WM8994_WRITE_SEQUENCER_230 0x30E6
+#define WM8994_WRITE_SEQUENCER_231 0x30E7
+#define WM8994_WRITE_SEQUENCER_232 0x30E8
+#define WM8994_WRITE_SEQUENCER_233 0x30E9
+#define WM8994_WRITE_SEQUENCER_234 0x30EA
+#define WM8994_WRITE_SEQUENCER_235 0x30EB
+#define WM8994_WRITE_SEQUENCER_236 0x30EC
+#define WM8994_WRITE_SEQUENCER_237 0x30ED
+#define WM8994_WRITE_SEQUENCER_238 0x30EE
+#define WM8994_WRITE_SEQUENCER_239 0x30EF
+#define WM8994_WRITE_SEQUENCER_240 0x30F0
+#define WM8994_WRITE_SEQUENCER_241 0x30F1
+#define WM8994_WRITE_SEQUENCER_242 0x30F2
+#define WM8994_WRITE_SEQUENCER_243 0x30F3
+#define WM8994_WRITE_SEQUENCER_244 0x30F4
+#define WM8994_WRITE_SEQUENCER_245 0x30F5
+#define WM8994_WRITE_SEQUENCER_246 0x30F6
+#define WM8994_WRITE_SEQUENCER_247 0x30F7
+#define WM8994_WRITE_SEQUENCER_248 0x30F8
+#define WM8994_WRITE_SEQUENCER_249 0x30F9
+#define WM8994_WRITE_SEQUENCER_250 0x30FA
+#define WM8994_WRITE_SEQUENCER_251 0x30FB
+#define WM8994_WRITE_SEQUENCER_252 0x30FC
+#define WM8994_WRITE_SEQUENCER_253 0x30FD
+#define WM8994_WRITE_SEQUENCER_254 0x30FE
+#define WM8994_WRITE_SEQUENCER_255 0x30FF
+#define WM8994_WRITE_SEQUENCER_256 0x3100
+#define WM8994_WRITE_SEQUENCER_257 0x3101
+#define WM8994_WRITE_SEQUENCER_258 0x3102
+#define WM8994_WRITE_SEQUENCER_259 0x3103
+#define WM8994_WRITE_SEQUENCER_260 0x3104
+#define WM8994_WRITE_SEQUENCER_261 0x3105
+#define WM8994_WRITE_SEQUENCER_262 0x3106
+#define WM8994_WRITE_SEQUENCER_263 0x3107
+#define WM8994_WRITE_SEQUENCER_264 0x3108
+#define WM8994_WRITE_SEQUENCER_265 0x3109
+#define WM8994_WRITE_SEQUENCER_266 0x310A
+#define WM8994_WRITE_SEQUENCER_267 0x310B
+#define WM8994_WRITE_SEQUENCER_268 0x310C
+#define WM8994_WRITE_SEQUENCER_269 0x310D
+#define WM8994_WRITE_SEQUENCER_270 0x310E
+#define WM8994_WRITE_SEQUENCER_271 0x310F
+#define WM8994_WRITE_SEQUENCER_272 0x3110
+#define WM8994_WRITE_SEQUENCER_273 0x3111
+#define WM8994_WRITE_SEQUENCER_274 0x3112
+#define WM8994_WRITE_SEQUENCER_275 0x3113
+#define WM8994_WRITE_SEQUENCER_276 0x3114
+#define WM8994_WRITE_SEQUENCER_277 0x3115
+#define WM8994_WRITE_SEQUENCER_278 0x3116
+#define WM8994_WRITE_SEQUENCER_279 0x3117
+#define WM8994_WRITE_SEQUENCER_280 0x3118
+#define WM8994_WRITE_SEQUENCER_281 0x3119
+#define WM8994_WRITE_SEQUENCER_282 0x311A
+#define WM8994_WRITE_SEQUENCER_283 0x311B
+#define WM8994_WRITE_SEQUENCER_284 0x311C
+#define WM8994_WRITE_SEQUENCER_285 0x311D
+#define WM8994_WRITE_SEQUENCER_286 0x311E
+#define WM8994_WRITE_SEQUENCER_287 0x311F
+#define WM8994_WRITE_SEQUENCER_288 0x3120
+#define WM8994_WRITE_SEQUENCER_289 0x3121
+#define WM8994_WRITE_SEQUENCER_290 0x3122
+#define WM8994_WRITE_SEQUENCER_291 0x3123
+#define WM8994_WRITE_SEQUENCER_292 0x3124
+#define WM8994_WRITE_SEQUENCER_293 0x3125
+#define WM8994_WRITE_SEQUENCER_294 0x3126
+#define WM8994_WRITE_SEQUENCER_295 0x3127
+#define WM8994_WRITE_SEQUENCER_296 0x3128
+#define WM8994_WRITE_SEQUENCER_297 0x3129
+#define WM8994_WRITE_SEQUENCER_298 0x312A
+#define WM8994_WRITE_SEQUENCER_299 0x312B
+#define WM8994_WRITE_SEQUENCER_300 0x312C
+#define WM8994_WRITE_SEQUENCER_301 0x312D
+#define WM8994_WRITE_SEQUENCER_302 0x312E
+#define WM8994_WRITE_SEQUENCER_303 0x312F
+#define WM8994_WRITE_SEQUENCER_304 0x3130
+#define WM8994_WRITE_SEQUENCER_305 0x3131
+#define WM8994_WRITE_SEQUENCER_306 0x3132
+#define WM8994_WRITE_SEQUENCER_307 0x3133
+#define WM8994_WRITE_SEQUENCER_308 0x3134
+#define WM8994_WRITE_SEQUENCER_309 0x3135
+#define WM8994_WRITE_SEQUENCER_310 0x3136
+#define WM8994_WRITE_SEQUENCER_311 0x3137
+#define WM8994_WRITE_SEQUENCER_312 0x3138
+#define WM8994_WRITE_SEQUENCER_313 0x3139
+#define WM8994_WRITE_SEQUENCER_314 0x313A
+#define WM8994_WRITE_SEQUENCER_315 0x313B
+#define WM8994_WRITE_SEQUENCER_316 0x313C
+#define WM8994_WRITE_SEQUENCER_317 0x313D
+#define WM8994_WRITE_SEQUENCER_318 0x313E
+#define WM8994_WRITE_SEQUENCER_319 0x313F
+#define WM8994_WRITE_SEQUENCER_320 0x3140
+#define WM8994_WRITE_SEQUENCER_321 0x3141
+#define WM8994_WRITE_SEQUENCER_322 0x3142
+#define WM8994_WRITE_SEQUENCER_323 0x3143
+#define WM8994_WRITE_SEQUENCER_324 0x3144
+#define WM8994_WRITE_SEQUENCER_325 0x3145
+#define WM8994_WRITE_SEQUENCER_326 0x3146
+#define WM8994_WRITE_SEQUENCER_327 0x3147
+#define WM8994_WRITE_SEQUENCER_328 0x3148
+#define WM8994_WRITE_SEQUENCER_329 0x3149
+#define WM8994_WRITE_SEQUENCER_330 0x314A
+#define WM8994_WRITE_SEQUENCER_331 0x314B
+#define WM8994_WRITE_SEQUENCER_332 0x314C
+#define WM8994_WRITE_SEQUENCER_333 0x314D
+#define WM8994_WRITE_SEQUENCER_334 0x314E
+#define WM8994_WRITE_SEQUENCER_335 0x314F
+#define WM8994_WRITE_SEQUENCER_336 0x3150
+#define WM8994_WRITE_SEQUENCER_337 0x3151
+#define WM8994_WRITE_SEQUENCER_338 0x3152
+#define WM8994_WRITE_SEQUENCER_339 0x3153
+#define WM8994_WRITE_SEQUENCER_340 0x3154
+#define WM8994_WRITE_SEQUENCER_341 0x3155
+#define WM8994_WRITE_SEQUENCER_342 0x3156
+#define WM8994_WRITE_SEQUENCER_343 0x3157
+#define WM8994_WRITE_SEQUENCER_344 0x3158
+#define WM8994_WRITE_SEQUENCER_345 0x3159
+#define WM8994_WRITE_SEQUENCER_346 0x315A
+#define WM8994_WRITE_SEQUENCER_347 0x315B
+#define WM8994_WRITE_SEQUENCER_348 0x315C
+#define WM8994_WRITE_SEQUENCER_349 0x315D
+#define WM8994_WRITE_SEQUENCER_350 0x315E
+#define WM8994_WRITE_SEQUENCER_351 0x315F
+#define WM8994_WRITE_SEQUENCER_352 0x3160
+#define WM8994_WRITE_SEQUENCER_353 0x3161
+#define WM8994_WRITE_SEQUENCER_354 0x3162
+#define WM8994_WRITE_SEQUENCER_355 0x3163
+#define WM8994_WRITE_SEQUENCER_356 0x3164
+#define WM8994_WRITE_SEQUENCER_357 0x3165
+#define WM8994_WRITE_SEQUENCER_358 0x3166
+#define WM8994_WRITE_SEQUENCER_359 0x3167
+#define WM8994_WRITE_SEQUENCER_360 0x3168
+#define WM8994_WRITE_SEQUENCER_361 0x3169
+#define WM8994_WRITE_SEQUENCER_362 0x316A
+#define WM8994_WRITE_SEQUENCER_363 0x316B
+#define WM8994_WRITE_SEQUENCER_364 0x316C
+#define WM8994_WRITE_SEQUENCER_365 0x316D
+#define WM8994_WRITE_SEQUENCER_366 0x316E
+#define WM8994_WRITE_SEQUENCER_367 0x316F
+#define WM8994_WRITE_SEQUENCER_368 0x3170
+#define WM8994_WRITE_SEQUENCER_369 0x3171
+#define WM8994_WRITE_SEQUENCER_370 0x3172
+#define WM8994_WRITE_SEQUENCER_371 0x3173
+#define WM8994_WRITE_SEQUENCER_372 0x3174
+#define WM8994_WRITE_SEQUENCER_373 0x3175
+#define WM8994_WRITE_SEQUENCER_374 0x3176
+#define WM8994_WRITE_SEQUENCER_375 0x3177
+#define WM8994_WRITE_SEQUENCER_376 0x3178
+#define WM8994_WRITE_SEQUENCER_377 0x3179
+#define WM8994_WRITE_SEQUENCER_378 0x317A
+#define WM8994_WRITE_SEQUENCER_379 0x317B
+#define WM8994_WRITE_SEQUENCER_380 0x317C
+#define WM8994_WRITE_SEQUENCER_381 0x317D
+#define WM8994_WRITE_SEQUENCER_382 0x317E
+#define WM8994_WRITE_SEQUENCER_383 0x317F
+#define WM8994_WRITE_SEQUENCER_384 0x3180
+#define WM8994_WRITE_SEQUENCER_385 0x3181
+#define WM8994_WRITE_SEQUENCER_386 0x3182
+#define WM8994_WRITE_SEQUENCER_387 0x3183
+#define WM8994_WRITE_SEQUENCER_388 0x3184
+#define WM8994_WRITE_SEQUENCER_389 0x3185
+#define WM8994_WRITE_SEQUENCER_390 0x3186
+#define WM8994_WRITE_SEQUENCER_391 0x3187
+#define WM8994_WRITE_SEQUENCER_392 0x3188
+#define WM8994_WRITE_SEQUENCER_393 0x3189
+#define WM8994_WRITE_SEQUENCER_394 0x318A
+#define WM8994_WRITE_SEQUENCER_395 0x318B
+#define WM8994_WRITE_SEQUENCER_396 0x318C
+#define WM8994_WRITE_SEQUENCER_397 0x318D
+#define WM8994_WRITE_SEQUENCER_398 0x318E
+#define WM8994_WRITE_SEQUENCER_399 0x318F
+#define WM8994_WRITE_SEQUENCER_400 0x3190
+#define WM8994_WRITE_SEQUENCER_401 0x3191
+#define WM8994_WRITE_SEQUENCER_402 0x3192
+#define WM8994_WRITE_SEQUENCER_403 0x3193
+#define WM8994_WRITE_SEQUENCER_404 0x3194
+#define WM8994_WRITE_SEQUENCER_405 0x3195
+#define WM8994_WRITE_SEQUENCER_406 0x3196
+#define WM8994_WRITE_SEQUENCER_407 0x3197
+#define WM8994_WRITE_SEQUENCER_408 0x3198
+#define WM8994_WRITE_SEQUENCER_409 0x3199
+#define WM8994_WRITE_SEQUENCER_410 0x319A
+#define WM8994_WRITE_SEQUENCER_411 0x319B
+#define WM8994_WRITE_SEQUENCER_412 0x319C
+#define WM8994_WRITE_SEQUENCER_413 0x319D
+#define WM8994_WRITE_SEQUENCER_414 0x319E
+#define WM8994_WRITE_SEQUENCER_415 0x319F
+#define WM8994_WRITE_SEQUENCER_416 0x31A0
+#define WM8994_WRITE_SEQUENCER_417 0x31A1
+#define WM8994_WRITE_SEQUENCER_418 0x31A2
+#define WM8994_WRITE_SEQUENCER_419 0x31A3
+#define WM8994_WRITE_SEQUENCER_420 0x31A4
+#define WM8994_WRITE_SEQUENCER_421 0x31A5
+#define WM8994_WRITE_SEQUENCER_422 0x31A6
+#define WM8994_WRITE_SEQUENCER_423 0x31A7
+#define WM8994_WRITE_SEQUENCER_424 0x31A8
+#define WM8994_WRITE_SEQUENCER_425 0x31A9
+#define WM8994_WRITE_SEQUENCER_426 0x31AA
+#define WM8994_WRITE_SEQUENCER_427 0x31AB
+#define WM8994_WRITE_SEQUENCER_428 0x31AC
+#define WM8994_WRITE_SEQUENCER_429 0x31AD
+#define WM8994_WRITE_SEQUENCER_430 0x31AE
+#define WM8994_WRITE_SEQUENCER_431 0x31AF
+#define WM8994_WRITE_SEQUENCER_432 0x31B0
+#define WM8994_WRITE_SEQUENCER_433 0x31B1
+#define WM8994_WRITE_SEQUENCER_434 0x31B2
+#define WM8994_WRITE_SEQUENCER_435 0x31B3
+#define WM8994_WRITE_SEQUENCER_436 0x31B4
+#define WM8994_WRITE_SEQUENCER_437 0x31B5
+#define WM8994_WRITE_SEQUENCER_438 0x31B6
+#define WM8994_WRITE_SEQUENCER_439 0x31B7
+#define WM8994_WRITE_SEQUENCER_440 0x31B8
+#define WM8994_WRITE_SEQUENCER_441 0x31B9
+#define WM8994_WRITE_SEQUENCER_442 0x31BA
+#define WM8994_WRITE_SEQUENCER_443 0x31BB
+#define WM8994_WRITE_SEQUENCER_444 0x31BC
+#define WM8994_WRITE_SEQUENCER_445 0x31BD
+#define WM8994_WRITE_SEQUENCER_446 0x31BE
+#define WM8994_WRITE_SEQUENCER_447 0x31BF
+#define WM8994_WRITE_SEQUENCER_448 0x31C0
+#define WM8994_WRITE_SEQUENCER_449 0x31C1
+#define WM8994_WRITE_SEQUENCER_450 0x31C2
+#define WM8994_WRITE_SEQUENCER_451 0x31C3
+#define WM8994_WRITE_SEQUENCER_452 0x31C4
+#define WM8994_WRITE_SEQUENCER_453 0x31C5
+#define WM8994_WRITE_SEQUENCER_454 0x31C6
+#define WM8994_WRITE_SEQUENCER_455 0x31C7
+#define WM8994_WRITE_SEQUENCER_456 0x31C8
+#define WM8994_WRITE_SEQUENCER_457 0x31C9
+#define WM8994_WRITE_SEQUENCER_458 0x31CA
+#define WM8994_WRITE_SEQUENCER_459 0x31CB
+#define WM8994_WRITE_SEQUENCER_460 0x31CC
+#define WM8994_WRITE_SEQUENCER_461 0x31CD
+#define WM8994_WRITE_SEQUENCER_462 0x31CE
+#define WM8994_WRITE_SEQUENCER_463 0x31CF
+#define WM8994_WRITE_SEQUENCER_464 0x31D0
+#define WM8994_WRITE_SEQUENCER_465 0x31D1
+#define WM8994_WRITE_SEQUENCER_466 0x31D2
+#define WM8994_WRITE_SEQUENCER_467 0x31D3
+#define WM8994_WRITE_SEQUENCER_468 0x31D4
+#define WM8994_WRITE_SEQUENCER_469 0x31D5
+#define WM8994_WRITE_SEQUENCER_470 0x31D6
+#define WM8994_WRITE_SEQUENCER_471 0x31D7
+#define WM8994_WRITE_SEQUENCER_472 0x31D8
+#define WM8994_WRITE_SEQUENCER_473 0x31D9
+#define WM8994_WRITE_SEQUENCER_474 0x31DA
+#define WM8994_WRITE_SEQUENCER_475 0x31DB
+#define WM8994_WRITE_SEQUENCER_476 0x31DC
+#define WM8994_WRITE_SEQUENCER_477 0x31DD
+#define WM8994_WRITE_SEQUENCER_478 0x31DE
+#define WM8994_WRITE_SEQUENCER_479 0x31DF
+#define WM8994_WRITE_SEQUENCER_480 0x31E0
+#define WM8994_WRITE_SEQUENCER_481 0x31E1
+#define WM8994_WRITE_SEQUENCER_482 0x31E2
+#define WM8994_WRITE_SEQUENCER_483 0x31E3
+#define WM8994_WRITE_SEQUENCER_484 0x31E4
+#define WM8994_WRITE_SEQUENCER_485 0x31E5
+#define WM8994_WRITE_SEQUENCER_486 0x31E6
+#define WM8994_WRITE_SEQUENCER_487 0x31E7
+#define WM8994_WRITE_SEQUENCER_488 0x31E8
+#define WM8994_WRITE_SEQUENCER_489 0x31E9
+#define WM8994_WRITE_SEQUENCER_490 0x31EA
+#define WM8994_WRITE_SEQUENCER_491 0x31EB
+#define WM8994_WRITE_SEQUENCER_492 0x31EC
+#define WM8994_WRITE_SEQUENCER_493 0x31ED
+#define WM8994_WRITE_SEQUENCER_494 0x31EE
+#define WM8994_WRITE_SEQUENCER_495 0x31EF
+#define WM8994_WRITE_SEQUENCER_496 0x31F0
+#define WM8994_WRITE_SEQUENCER_497 0x31F1
+#define WM8994_WRITE_SEQUENCER_498 0x31F2
+#define WM8994_WRITE_SEQUENCER_499 0x31F3
+#define WM8994_WRITE_SEQUENCER_500 0x31F4
+#define WM8994_WRITE_SEQUENCER_501 0x31F5
+#define WM8994_WRITE_SEQUENCER_502 0x31F6
+#define WM8994_WRITE_SEQUENCER_503 0x31F7
+#define WM8994_WRITE_SEQUENCER_504 0x31F8
+#define WM8994_WRITE_SEQUENCER_505 0x31F9
+#define WM8994_WRITE_SEQUENCER_506 0x31FA
+#define WM8994_WRITE_SEQUENCER_507 0x31FB
+#define WM8994_WRITE_SEQUENCER_508 0x31FC
+#define WM8994_WRITE_SEQUENCER_509 0x31FD
+#define WM8994_WRITE_SEQUENCER_510 0x31FE
+#define WM8994_WRITE_SEQUENCER_511 0x31FF
+
+#define WM8994_REGISTER_COUNT 736
+#define WM8994_MAX_REGISTER 0x31FF
+#define WM8994_MAX_CACHED_REGISTER 0x749
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - Software Reset
+ */
+#define WM8994_SW_RESET_MASK 0xFFFF /* SW_RESET - [15:0] */
+#define WM8994_SW_RESET_SHIFT 0 /* SW_RESET - [15:0] */
+#define WM8994_SW_RESET_WIDTH 16 /* SW_RESET - [15:0] */
+
+/*
+ * R1 (0x01) - Power Management (1)
+ */
+#define WM8994_SPKOUTR_ENA 0x2000 /* SPKOUTR_ENA */
+#define WM8994_SPKOUTR_ENA_MASK 0x2000 /* SPKOUTR_ENA */
+#define WM8994_SPKOUTR_ENA_SHIFT 13 /* SPKOUTR_ENA */
+#define WM8994_SPKOUTR_ENA_WIDTH 1 /* SPKOUTR_ENA */
+#define WM8994_SPKOUTL_ENA 0x1000 /* SPKOUTL_ENA */
+#define WM8994_SPKOUTL_ENA_MASK 0x1000 /* SPKOUTL_ENA */
+#define WM8994_SPKOUTL_ENA_SHIFT 12 /* SPKOUTL_ENA */
+#define WM8994_SPKOUTL_ENA_WIDTH 1 /* SPKOUTL_ENA */
+#define WM8994_HPOUT2_ENA 0x0800 /* HPOUT2_ENA */
+#define WM8994_HPOUT2_ENA_MASK 0x0800 /* HPOUT2_ENA */
+#define WM8994_HPOUT2_ENA_SHIFT 11 /* HPOUT2_ENA */
+#define WM8994_HPOUT2_ENA_WIDTH 1 /* HPOUT2_ENA */
+#define WM8994_HPOUT1L_ENA 0x0200 /* HPOUT1L_ENA */
+#define WM8994_HPOUT1L_ENA_MASK 0x0200 /* HPOUT1L_ENA */
+#define WM8994_HPOUT1L_ENA_SHIFT 9 /* HPOUT1L_ENA */
+#define WM8994_HPOUT1L_ENA_WIDTH 1 /* HPOUT1L_ENA */
+#define WM8994_HPOUT1R_ENA 0x0100 /* HPOUT1R_ENA */
+#define WM8994_HPOUT1R_ENA_MASK 0x0100 /* HPOUT1R_ENA */
+#define WM8994_HPOUT1R_ENA_SHIFT 8 /* HPOUT1R_ENA */
+#define WM8994_HPOUT1R_ENA_WIDTH 1 /* HPOUT1R_ENA */
+#define WM8994_MICB2_ENA 0x0020 /* MICB2_ENA */
+#define WM8994_MICB2_ENA_MASK 0x0020 /* MICB2_ENA */
+#define WM8994_MICB2_ENA_SHIFT 5 /* MICB2_ENA */
+#define WM8994_MICB2_ENA_WIDTH 1 /* MICB2_ENA */
+#define WM8994_MICB1_ENA 0x0010 /* MICB1_ENA */
+#define WM8994_MICB1_ENA_MASK 0x0010 /* MICB1_ENA */
+#define WM8994_MICB1_ENA_SHIFT 4 /* MICB1_ENA */
+#define WM8994_MICB1_ENA_WIDTH 1 /* MICB1_ENA */
+#define WM8994_VMID_SEL_MASK 0x0006 /* VMID_SEL - [2:1] */
+#define WM8994_VMID_SEL_SHIFT 1 /* VMID_SEL - [2:1] */
+#define WM8994_VMID_SEL_WIDTH 2 /* VMID_SEL - [2:1] */
+#define WM8994_BIAS_ENA 0x0001 /* BIAS_ENA */
+#define WM8994_BIAS_ENA_MASK 0x0001 /* BIAS_ENA */
+#define WM8994_BIAS_ENA_SHIFT 0 /* BIAS_ENA */
+#define WM8994_BIAS_ENA_WIDTH 1 /* BIAS_ENA */
+
+/*
+ * R2 (0x02) - Power Management (2)
+ */
+#define WM8994_TSHUT_ENA 0x4000 /* TSHUT_ENA */
+#define WM8994_TSHUT_ENA_MASK 0x4000 /* TSHUT_ENA */
+#define WM8994_TSHUT_ENA_SHIFT 14 /* TSHUT_ENA */
+#define WM8994_TSHUT_ENA_WIDTH 1 /* TSHUT_ENA */
+#define WM8994_TSHUT_OPDIS 0x2000 /* TSHUT_OPDIS */
+#define WM8994_TSHUT_OPDIS_MASK 0x2000 /* TSHUT_OPDIS */
+#define WM8994_TSHUT_OPDIS_SHIFT 13 /* TSHUT_OPDIS */
+#define WM8994_TSHUT_OPDIS_WIDTH 1 /* TSHUT_OPDIS */
+#define WM8994_OPCLK_ENA 0x0800 /* OPCLK_ENA */
+#define WM8994_OPCLK_ENA_MASK 0x0800 /* OPCLK_ENA */
+#define WM8994_OPCLK_ENA_SHIFT 11 /* OPCLK_ENA */
+#define WM8994_OPCLK_ENA_WIDTH 1 /* OPCLK_ENA */
+#define WM8994_MIXINL_ENA 0x0200 /* MIXINL_ENA */
+#define WM8994_MIXINL_ENA_MASK 0x0200 /* MIXINL_ENA */
+#define WM8994_MIXINL_ENA_SHIFT 9 /* MIXINL_ENA */
+#define WM8994_MIXINL_ENA_WIDTH 1 /* MIXINL_ENA */
+#define WM8994_MIXINR_ENA 0x0100 /* MIXINR_ENA */
+#define WM8994_MIXINR_ENA_MASK 0x0100 /* MIXINR_ENA */
+#define WM8994_MIXINR_ENA_SHIFT 8 /* MIXINR_ENA */
+#define WM8994_MIXINR_ENA_WIDTH 1 /* MIXINR_ENA */
+#define WM8994_IN2L_ENA 0x0080 /* IN2L_ENA */
+#define WM8994_IN2L_ENA_MASK 0x0080 /* IN2L_ENA */
+#define WM8994_IN2L_ENA_SHIFT 7 /* IN2L_ENA */
+#define WM8994_IN2L_ENA_WIDTH 1 /* IN2L_ENA */
+#define WM8994_IN1L_ENA 0x0040 /* IN1L_ENA */
+#define WM8994_IN1L_ENA_MASK 0x0040 /* IN1L_ENA */
+#define WM8994_IN1L_ENA_SHIFT 6 /* IN1L_ENA */
+#define WM8994_IN1L_ENA_WIDTH 1 /* IN1L_ENA */
+#define WM8994_IN2R_ENA 0x0020 /* IN2R_ENA */
+#define WM8994_IN2R_ENA_MASK 0x0020 /* IN2R_ENA */
+#define WM8994_IN2R_ENA_SHIFT 5 /* IN2R_ENA */
+#define WM8994_IN2R_ENA_WIDTH 1 /* IN2R_ENA */
+#define WM8994_IN1R_ENA 0x0010 /* IN1R_ENA */
+#define WM8994_IN1R_ENA_MASK 0x0010 /* IN1R_ENA */
+#define WM8994_IN1R_ENA_SHIFT 4 /* IN1R_ENA */
+#define WM8994_IN1R_ENA_WIDTH 1 /* IN1R_ENA */
+
+/*
+ * R3 (0x03) - Power Management (3)
+ */
+#define WM8994_LINEOUT1N_ENA 0x2000 /* LINEOUT1N_ENA */
+#define WM8994_LINEOUT1N_ENA_MASK 0x2000 /* LINEOUT1N_ENA */
+#define WM8994_LINEOUT1N_ENA_SHIFT 13 /* LINEOUT1N_ENA */
+#define WM8994_LINEOUT1N_ENA_WIDTH 1 /* LINEOUT1N_ENA */
+#define WM8994_LINEOUT1P_ENA 0x1000 /* LINEOUT1P_ENA */
+#define WM8994_LINEOUT1P_ENA_MASK 0x1000 /* LINEOUT1P_ENA */
+#define WM8994_LINEOUT1P_ENA_SHIFT 12 /* LINEOUT1P_ENA */
+#define WM8994_LINEOUT1P_ENA_WIDTH 1 /* LINEOUT1P_ENA */
+#define WM8994_LINEOUT2N_ENA 0x0800 /* LINEOUT2N_ENA */
+#define WM8994_LINEOUT2N_ENA_MASK 0x0800 /* LINEOUT2N_ENA */
+#define WM8994_LINEOUT2N_ENA_SHIFT 11 /* LINEOUT2N_ENA */
+#define WM8994_LINEOUT2N_ENA_WIDTH 1 /* LINEOUT2N_ENA */
+#define WM8994_LINEOUT2P_ENA 0x0400 /* LINEOUT2P_ENA */
+#define WM8994_LINEOUT2P_ENA_MASK 0x0400 /* LINEOUT2P_ENA */
+#define WM8994_LINEOUT2P_ENA_SHIFT 10 /* LINEOUT2P_ENA */
+#define WM8994_LINEOUT2P_ENA_WIDTH 1 /* LINEOUT2P_ENA */
+#define WM8994_SPKRVOL_ENA 0x0200 /* SPKRVOL_ENA */
+#define WM8994_SPKRVOL_ENA_MASK 0x0200 /* SPKRVOL_ENA */
+#define WM8994_SPKRVOL_ENA_SHIFT 9 /* SPKRVOL_ENA */
+#define WM8994_SPKRVOL_ENA_WIDTH 1 /* SPKRVOL_ENA */
+#define WM8994_SPKLVOL_ENA 0x0100 /* SPKLVOL_ENA */
+#define WM8994_SPKLVOL_ENA_MASK 0x0100 /* SPKLVOL_ENA */
+#define WM8994_SPKLVOL_ENA_SHIFT 8 /* SPKLVOL_ENA */
+#define WM8994_SPKLVOL_ENA_WIDTH 1 /* SPKLVOL_ENA */
+#define WM8994_MIXOUTLVOL_ENA 0x0080 /* MIXOUTLVOL_ENA */
+#define WM8994_MIXOUTLVOL_ENA_MASK 0x0080 /* MIXOUTLVOL_ENA */
+#define WM8994_MIXOUTLVOL_ENA_SHIFT 7 /* MIXOUTLVOL_ENA */
+#define WM8994_MIXOUTLVOL_ENA_WIDTH 1 /* MIXOUTLVOL_ENA */
+#define WM8994_MIXOUTRVOL_ENA 0x0040 /* MIXOUTRVOL_ENA */
+#define WM8994_MIXOUTRVOL_ENA_MASK 0x0040 /* MIXOUTRVOL_ENA */
+#define WM8994_MIXOUTRVOL_ENA_SHIFT 6 /* MIXOUTRVOL_ENA */
+#define WM8994_MIXOUTRVOL_ENA_WIDTH 1 /* MIXOUTRVOL_ENA */
+#define WM8994_MIXOUTL_ENA 0x0020 /* MIXOUTL_ENA */
+#define WM8994_MIXOUTL_ENA_MASK 0x0020 /* MIXOUTL_ENA */
+#define WM8994_MIXOUTL_ENA_SHIFT 5 /* MIXOUTL_ENA */
+#define WM8994_MIXOUTL_ENA_WIDTH 1 /* MIXOUTL_ENA */
+#define WM8994_MIXOUTR_ENA 0x0010 /* MIXOUTR_ENA */
+#define WM8994_MIXOUTR_ENA_MASK 0x0010 /* MIXOUTR_ENA */
+#define WM8994_MIXOUTR_ENA_SHIFT 4 /* MIXOUTR_ENA */
+#define WM8994_MIXOUTR_ENA_WIDTH 1 /* MIXOUTR_ENA */
+
+/*
+ * R4 (0x04) - Power Management (4)
+ */
+#define WM8994_AIF2ADCL_ENA 0x2000 /* AIF2ADCL_ENA */
+#define WM8994_AIF2ADCL_ENA_MASK 0x2000 /* AIF2ADCL_ENA */
+#define WM8994_AIF2ADCL_ENA_SHIFT 13 /* AIF2ADCL_ENA */
+#define WM8994_AIF2ADCL_ENA_WIDTH 1 /* AIF2ADCL_ENA */
+#define WM8994_AIF2ADCR_ENA 0x1000 /* AIF2ADCR_ENA */
+#define WM8994_AIF2ADCR_ENA_MASK 0x1000 /* AIF2ADCR_ENA */
+#define WM8994_AIF2ADCR_ENA_SHIFT 12 /* AIF2ADCR_ENA */
+#define WM8994_AIF2ADCR_ENA_WIDTH 1 /* AIF2ADCR_ENA */
+#define WM8994_AIF1ADC2L_ENA 0x0800 /* AIF1ADC2L_ENA */
+#define WM8994_AIF1ADC2L_ENA_MASK 0x0800 /* AIF1ADC2L_ENA */
+#define WM8994_AIF1ADC2L_ENA_SHIFT 11 /* AIF1ADC2L_ENA */
+#define WM8994_AIF1ADC2L_ENA_WIDTH 1 /* AIF1ADC2L_ENA */
+#define WM8994_AIF1ADC2R_ENA 0x0400 /* AIF1ADC2R_ENA */
+#define WM8994_AIF1ADC2R_ENA_MASK 0x0400 /* AIF1ADC2R_ENA */
+#define WM8994_AIF1ADC2R_ENA_SHIFT 10 /* AIF1ADC2R_ENA */
+#define WM8994_AIF1ADC2R_ENA_WIDTH 1 /* AIF1ADC2R_ENA */
+#define WM8994_AIF1ADC1L_ENA 0x0200 /* AIF1ADC1L_ENA */
+#define WM8994_AIF1ADC1L_ENA_MASK 0x0200 /* AIF1ADC1L_ENA */
+#define WM8994_AIF1ADC1L_ENA_SHIFT 9 /* AIF1ADC1L_ENA */
+#define WM8994_AIF1ADC1L_ENA_WIDTH 1 /* AIF1ADC1L_ENA */
+#define WM8994_AIF1ADC1R_ENA 0x0100 /* AIF1ADC1R_ENA */
+#define WM8994_AIF1ADC1R_ENA_MASK 0x0100 /* AIF1ADC1R_ENA */
+#define WM8994_AIF1ADC1R_ENA_SHIFT 8 /* AIF1ADC1R_ENA */
+#define WM8994_AIF1ADC1R_ENA_WIDTH 1 /* AIF1ADC1R_ENA */
+#define WM8994_DMIC2L_ENA 0x0020 /* DMIC2L_ENA */
+#define WM8994_DMIC2L_ENA_MASK 0x0020 /* DMIC2L_ENA */
+#define WM8994_DMIC2L_ENA_SHIFT 5 /* DMIC2L_ENA */
+#define WM8994_DMIC2L_ENA_WIDTH 1 /* DMIC2L_ENA */
+#define WM8994_DMIC2R_ENA 0x0010 /* DMIC2R_ENA */
+#define WM8994_DMIC2R_ENA_MASK 0x0010 /* DMIC2R_ENA */
+#define WM8994_DMIC2R_ENA_SHIFT 4 /* DMIC2R_ENA */
+#define WM8994_DMIC2R_ENA_WIDTH 1 /* DMIC2R_ENA */
+#define WM8994_DMIC1L_ENA 0x0008 /* DMIC1L_ENA */
+#define WM8994_DMIC1L_ENA_MASK 0x0008 /* DMIC1L_ENA */
+#define WM8994_DMIC1L_ENA_SHIFT 3 /* DMIC1L_ENA */
+#define WM8994_DMIC1L_ENA_WIDTH 1 /* DMIC1L_ENA */
+#define WM8994_DMIC1R_ENA 0x0004 /* DMIC1R_ENA */
+#define WM8994_DMIC1R_ENA_MASK 0x0004 /* DMIC1R_ENA */
+#define WM8994_DMIC1R_ENA_SHIFT 2 /* DMIC1R_ENA */
+#define WM8994_DMIC1R_ENA_WIDTH 1 /* DMIC1R_ENA */
+#define WM8994_ADCL_ENA 0x0002 /* ADCL_ENA */
+#define WM8994_ADCL_ENA_MASK 0x0002 /* ADCL_ENA */
+#define WM8994_ADCL_ENA_SHIFT 1 /* ADCL_ENA */
+#define WM8994_ADCL_ENA_WIDTH 1 /* ADCL_ENA */
+#define WM8994_ADCR_ENA 0x0001 /* ADCR_ENA */
+#define WM8994_ADCR_ENA_MASK 0x0001 /* ADCR_ENA */
+#define WM8994_ADCR_ENA_SHIFT 0 /* ADCR_ENA */
+#define WM8994_ADCR_ENA_WIDTH 1 /* ADCR_ENA */
+
+/*
+ * R5 (0x05) - Power Management (5)
+ */
+#define WM8994_AIF2DACL_ENA 0x2000 /* AIF2DACL_ENA */
+#define WM8994_AIF2DACL_ENA_MASK 0x2000 /* AIF2DACL_ENA */
+#define WM8994_AIF2DACL_ENA_SHIFT 13 /* AIF2DACL_ENA */
+#define WM8994_AIF2DACL_ENA_WIDTH 1 /* AIF2DACL_ENA */
+#define WM8994_AIF2DACR_ENA 0x1000 /* AIF2DACR_ENA */
+#define WM8994_AIF2DACR_ENA_MASK 0x1000 /* AIF2DACR_ENA */
+#define WM8994_AIF2DACR_ENA_SHIFT 12 /* AIF2DACR_ENA */
+#define WM8994_AIF2DACR_ENA_WIDTH 1 /* AIF2DACR_ENA */
+#define WM8994_AIF1DAC2L_ENA 0x0800 /* AIF1DAC2L_ENA */
+#define WM8994_AIF1DAC2L_ENA_MASK 0x0800 /* AIF1DAC2L_ENA */
+#define WM8994_AIF1DAC2L_ENA_SHIFT 11 /* AIF1DAC2L_ENA */
+#define WM8994_AIF1DAC2L_ENA_WIDTH 1 /* AIF1DAC2L_ENA */
+#define WM8994_AIF1DAC2R_ENA 0x0400 /* AIF1DAC2R_ENA */
+#define WM8994_AIF1DAC2R_ENA_MASK 0x0400 /* AIF1DAC2R_ENA */
+#define WM8994_AIF1DAC2R_ENA_SHIFT 10 /* AIF1DAC2R_ENA */
+#define WM8994_AIF1DAC2R_ENA_WIDTH 1 /* AIF1DAC2R_ENA */
+#define WM8994_AIF1DAC1L_ENA 0x0200 /* AIF1DAC1L_ENA */
+#define WM8994_AIF1DAC1L_ENA_MASK 0x0200 /* AIF1DAC1L_ENA */
+#define WM8994_AIF1DAC1L_ENA_SHIFT 9 /* AIF1DAC1L_ENA */
+#define WM8994_AIF1DAC1L_ENA_WIDTH 1 /* AIF1DAC1L_ENA */
+#define WM8994_AIF1DAC1R_ENA 0x0100 /* AIF1DAC1R_ENA */
+#define WM8994_AIF1DAC1R_ENA_MASK 0x0100 /* AIF1DAC1R_ENA */
+#define WM8994_AIF1DAC1R_ENA_SHIFT 8 /* AIF1DAC1R_ENA */
+#define WM8994_AIF1DAC1R_ENA_WIDTH 1 /* AIF1DAC1R_ENA */
+#define WM8994_DAC2L_ENA 0x0008 /* DAC2L_ENA */
+#define WM8994_DAC2L_ENA_MASK 0x0008 /* DAC2L_ENA */
+#define WM8994_DAC2L_ENA_SHIFT 3 /* DAC2L_ENA */
+#define WM8994_DAC2L_ENA_WIDTH 1 /* DAC2L_ENA */
+#define WM8994_DAC2R_ENA 0x0004 /* DAC2R_ENA */
+#define WM8994_DAC2R_ENA_MASK 0x0004 /* DAC2R_ENA */
+#define WM8994_DAC2R_ENA_SHIFT 2 /* DAC2R_ENA */
+#define WM8994_DAC2R_ENA_WIDTH 1 /* DAC2R_ENA */
+#define WM8994_DAC1L_ENA 0x0002 /* DAC1L_ENA */
+#define WM8994_DAC1L_ENA_MASK 0x0002 /* DAC1L_ENA */
+#define WM8994_DAC1L_ENA_SHIFT 1 /* DAC1L_ENA */
+#define WM8994_DAC1L_ENA_WIDTH 1 /* DAC1L_ENA */
+#define WM8994_DAC1R_ENA 0x0001 /* DAC1R_ENA */
+#define WM8994_DAC1R_ENA_MASK 0x0001 /* DAC1R_ENA */
+#define WM8994_DAC1R_ENA_SHIFT 0 /* DAC1R_ENA */
+#define WM8994_DAC1R_ENA_WIDTH 1 /* DAC1R_ENA */
+
+/*
+ * R6 (0x06) - Power Management (6)
+ */
+#define WM8994_AIF3_TRI 0x0020 /* AIF3_TRI */
+#define WM8994_AIF3_TRI_MASK 0x0020 /* AIF3_TRI */
+#define WM8994_AIF3_TRI_SHIFT 5 /* AIF3_TRI */
+#define WM8994_AIF3_TRI_WIDTH 1 /* AIF3_TRI */
+#define WM8994_AIF3_ADCDAT_SRC_MASK 0x0018 /* AIF3_ADCDAT_SRC - [4:3] */
+#define WM8994_AIF3_ADCDAT_SRC_SHIFT 3 /* AIF3_ADCDAT_SRC - [4:3] */
+#define WM8994_AIF3_ADCDAT_SRC_WIDTH 2 /* AIF3_ADCDAT_SRC - [4:3] */
+#define WM8994_AIF2_ADCDAT_SRC 0x0004 /* AIF2_ADCDAT_SRC */
+#define WM8994_AIF2_ADCDAT_SRC_MASK 0x0004 /* AIF2_ADCDAT_SRC */
+#define WM8994_AIF2_ADCDAT_SRC_SHIFT 2 /* AIF2_ADCDAT_SRC */
+#define WM8994_AIF2_ADCDAT_SRC_WIDTH 1 /* AIF2_ADCDAT_SRC */
+#define WM8994_AIF2_DACDAT_SRC 0x0002 /* AIF2_DACDAT_SRC */
+#define WM8994_AIF2_DACDAT_SRC_MASK 0x0002 /* AIF2_DACDAT_SRC */
+#define WM8994_AIF2_DACDAT_SRC_SHIFT 1 /* AIF2_DACDAT_SRC */
+#define WM8994_AIF2_DACDAT_SRC_WIDTH 1 /* AIF2_DACDAT_SRC */
+#define WM8994_AIF1_DACDAT_SRC 0x0001 /* AIF1_DACDAT_SRC */
+#define WM8994_AIF1_DACDAT_SRC_MASK 0x0001 /* AIF1_DACDAT_SRC */
+#define WM8994_AIF1_DACDAT_SRC_SHIFT 0 /* AIF1_DACDAT_SRC */
+#define WM8994_AIF1_DACDAT_SRC_WIDTH 1 /* AIF1_DACDAT_SRC */
+
+/*
+ * R21 (0x15) - Input Mixer (1)
+ */
+#define WM8994_IN1RP_MIXINR_BOOST 0x0100 /* IN1RP_MIXINR_BOOST */
+#define WM8994_IN1RP_MIXINR_BOOST_MASK 0x0100 /* IN1RP_MIXINR_BOOST */
+#define WM8994_IN1RP_MIXINR_BOOST_SHIFT 8 /* IN1RP_MIXINR_BOOST */
+#define WM8994_IN1RP_MIXINR_BOOST_WIDTH 1 /* IN1RP_MIXINR_BOOST */
+#define WM8994_IN1LP_MIXINL_BOOST 0x0080 /* IN1LP_MIXINL_BOOST */
+#define WM8994_IN1LP_MIXINL_BOOST_MASK 0x0080 /* IN1LP_MIXINL_BOOST */
+#define WM8994_IN1LP_MIXINL_BOOST_SHIFT 7 /* IN1LP_MIXINL_BOOST */
+#define WM8994_IN1LP_MIXINL_BOOST_WIDTH 1 /* IN1LP_MIXINL_BOOST */
+#define WM8994_INPUTS_CLAMP 0x0040 /* INPUTS_CLAMP */
+#define WM8994_INPUTS_CLAMP_MASK 0x0040 /* INPUTS_CLAMP */
+#define WM8994_INPUTS_CLAMP_SHIFT 6 /* INPUTS_CLAMP */
+#define WM8994_INPUTS_CLAMP_WIDTH 1 /* INPUTS_CLAMP */
+
+/*
+ * R24 (0x18) - Left Line Input 1&2 Volume
+ */
+#define WM8994_IN1_VU 0x0100 /* IN1_VU */
+#define WM8994_IN1_VU_MASK 0x0100 /* IN1_VU */
+#define WM8994_IN1_VU_SHIFT 8 /* IN1_VU */
+#define WM8994_IN1_VU_WIDTH 1 /* IN1_VU */
+#define WM8994_IN1L_MUTE 0x0080 /* IN1L_MUTE */
+#define WM8994_IN1L_MUTE_MASK 0x0080 /* IN1L_MUTE */
+#define WM8994_IN1L_MUTE_SHIFT 7 /* IN1L_MUTE */
+#define WM8994_IN1L_MUTE_WIDTH 1 /* IN1L_MUTE */
+#define WM8994_IN1L_ZC 0x0040 /* IN1L_ZC */
+#define WM8994_IN1L_ZC_MASK 0x0040 /* IN1L_ZC */
+#define WM8994_IN1L_ZC_SHIFT 6 /* IN1L_ZC */
+#define WM8994_IN1L_ZC_WIDTH 1 /* IN1L_ZC */
+#define WM8994_IN1L_VOL_MASK 0x001F /* IN1L_VOL - [4:0] */
+#define WM8994_IN1L_VOL_SHIFT 0 /* IN1L_VOL - [4:0] */
+#define WM8994_IN1L_VOL_WIDTH 5 /* IN1L_VOL - [4:0] */
+
+/*
+ * R25 (0x19) - Left Line Input 3&4 Volume
+ */
+#define WM8994_IN2_VU 0x0100 /* IN2_VU */
+#define WM8994_IN2_VU_MASK 0x0100 /* IN2_VU */
+#define WM8994_IN2_VU_SHIFT 8 /* IN2_VU */
+#define WM8994_IN2_VU_WIDTH 1 /* IN2_VU */
+#define WM8994_IN2L_MUTE 0x0080 /* IN2L_MUTE */
+#define WM8994_IN2L_MUTE_MASK 0x0080 /* IN2L_MUTE */
+#define WM8994_IN2L_MUTE_SHIFT 7 /* IN2L_MUTE */
+#define WM8994_IN2L_MUTE_WIDTH 1 /* IN2L_MUTE */
+#define WM8994_IN2L_ZC 0x0040 /* IN2L_ZC */
+#define WM8994_IN2L_ZC_MASK 0x0040 /* IN2L_ZC */
+#define WM8994_IN2L_ZC_SHIFT 6 /* IN2L_ZC */
+#define WM8994_IN2L_ZC_WIDTH 1 /* IN2L_ZC */
+#define WM8994_IN2L_VOL_MASK 0x001F /* IN2L_VOL - [4:0] */
+#define WM8994_IN2L_VOL_SHIFT 0 /* IN2L_VOL - [4:0] */
+#define WM8994_IN2L_VOL_WIDTH 5 /* IN2L_VOL - [4:0] */
+
+/*
+ * R26 (0x1A) - Right Line Input 1&2 Volume
+ */
+#define WM8994_IN1_VU 0x0100 /* IN1_VU */
+#define WM8994_IN1_VU_MASK 0x0100 /* IN1_VU */
+#define WM8994_IN1_VU_SHIFT 8 /* IN1_VU */
+#define WM8994_IN1_VU_WIDTH 1 /* IN1_VU */
+#define WM8994_IN1R_MUTE 0x0080 /* IN1R_MUTE */
+#define WM8994_IN1R_MUTE_MASK 0x0080 /* IN1R_MUTE */
+#define WM8994_IN1R_MUTE_SHIFT 7 /* IN1R_MUTE */
+#define WM8994_IN1R_MUTE_WIDTH 1 /* IN1R_MUTE */
+#define WM8994_IN1R_ZC 0x0040 /* IN1R_ZC */
+#define WM8994_IN1R_ZC_MASK 0x0040 /* IN1R_ZC */
+#define WM8994_IN1R_ZC_SHIFT 6 /* IN1R_ZC */
+#define WM8994_IN1R_ZC_WIDTH 1 /* IN1R_ZC */
+#define WM8994_IN1R_VOL_MASK 0x001F /* IN1R_VOL - [4:0] */
+#define WM8994_IN1R_VOL_SHIFT 0 /* IN1R_VOL - [4:0] */
+#define WM8994_IN1R_VOL_WIDTH 5 /* IN1R_VOL - [4:0] */
+
+/*
+ * R27 (0x1B) - Right Line Input 3&4 Volume
+ */
+#define WM8994_IN2_VU 0x0100 /* IN2_VU */
+#define WM8994_IN2_VU_MASK 0x0100 /* IN2_VU */
+#define WM8994_IN2_VU_SHIFT 8 /* IN2_VU */
+#define WM8994_IN2_VU_WIDTH 1 /* IN2_VU */
+#define WM8994_IN2R_MUTE 0x0080 /* IN2R_MUTE */
+#define WM8994_IN2R_MUTE_MASK 0x0080 /* IN2R_MUTE */
+#define WM8994_IN2R_MUTE_SHIFT 7 /* IN2R_MUTE */
+#define WM8994_IN2R_MUTE_WIDTH 1 /* IN2R_MUTE */
+#define WM8994_IN2R_ZC 0x0040 /* IN2R_ZC */
+#define WM8994_IN2R_ZC_MASK 0x0040 /* IN2R_ZC */
+#define WM8994_IN2R_ZC_SHIFT 6 /* IN2R_ZC */
+#define WM8994_IN2R_ZC_WIDTH 1 /* IN2R_ZC */
+#define WM8994_IN2R_VOL_MASK 0x001F /* IN2R_VOL - [4:0] */
+#define WM8994_IN2R_VOL_SHIFT 0 /* IN2R_VOL - [4:0] */
+#define WM8994_IN2R_VOL_WIDTH 5 /* IN2R_VOL - [4:0] */
+
+/*
+ * R28 (0x1C) - Left Output Volume
+ */
+#define WM8994_HPOUT1_VU 0x0100 /* HPOUT1_VU */
+#define WM8994_HPOUT1_VU_MASK 0x0100 /* HPOUT1_VU */
+#define WM8994_HPOUT1_VU_SHIFT 8 /* HPOUT1_VU */
+#define WM8994_HPOUT1_VU_WIDTH 1 /* HPOUT1_VU */
+#define WM8994_HPOUT1L_ZC 0x0080 /* HPOUT1L_ZC */
+#define WM8994_HPOUT1L_ZC_MASK 0x0080 /* HPOUT1L_ZC */
+#define WM8994_HPOUT1L_ZC_SHIFT 7 /* HPOUT1L_ZC */
+#define WM8994_HPOUT1L_ZC_WIDTH 1 /* HPOUT1L_ZC */
+#define WM8994_HPOUT1L_MUTE_N 0x0040 /* HPOUT1L_MUTE_N */
+#define WM8994_HPOUT1L_MUTE_N_MASK 0x0040 /* HPOUT1L_MUTE_N */
+#define WM8994_HPOUT1L_MUTE_N_SHIFT 6 /* HPOUT1L_MUTE_N */
+#define WM8994_HPOUT1L_MUTE_N_WIDTH 1 /* HPOUT1L_MUTE_N */
+#define WM8994_HPOUT1L_VOL_MASK 0x003F /* HPOUT1L_VOL - [5:0] */
+#define WM8994_HPOUT1L_VOL_SHIFT 0 /* HPOUT1L_VOL - [5:0] */
+#define WM8994_HPOUT1L_VOL_WIDTH 6 /* HPOUT1L_VOL - [5:0] */
+
+/*
+ * R29 (0x1D) - Right Output Volume
+ */
+#define WM8994_HPOUT1_VU 0x0100 /* HPOUT1_VU */
+#define WM8994_HPOUT1_VU_MASK 0x0100 /* HPOUT1_VU */
+#define WM8994_HPOUT1_VU_SHIFT 8 /* HPOUT1_VU */
+#define WM8994_HPOUT1_VU_WIDTH 1 /* HPOUT1_VU */
+#define WM8994_HPOUT1R_ZC 0x0080 /* HPOUT1R_ZC */
+#define WM8994_HPOUT1R_ZC_MASK 0x0080 /* HPOUT1R_ZC */
+#define WM8994_HPOUT1R_ZC_SHIFT 7 /* HPOUT1R_ZC */
+#define WM8994_HPOUT1R_ZC_WIDTH 1 /* HPOUT1R_ZC */
+#define WM8994_HPOUT1R_MUTE_N 0x0040 /* HPOUT1R_MUTE_N */
+#define WM8994_HPOUT1R_MUTE_N_MASK 0x0040 /* HPOUT1R_MUTE_N */
+#define WM8994_HPOUT1R_MUTE_N_SHIFT 6 /* HPOUT1R_MUTE_N */
+#define WM8994_HPOUT1R_MUTE_N_WIDTH 1 /* HPOUT1R_MUTE_N */
+#define WM8994_HPOUT1R_VOL_MASK 0x003F /* HPOUT1R_VOL - [5:0] */
+#define WM8994_HPOUT1R_VOL_SHIFT 0 /* HPOUT1R_VOL - [5:0] */
+#define WM8994_HPOUT1R_VOL_WIDTH 6 /* HPOUT1R_VOL - [5:0] */
+
+/*
+ * R30 (0x1E) - Line Outputs Volume
+ */
+#define WM8994_LINEOUT1N_MUTE 0x0040 /* LINEOUT1N_MUTE */
+#define WM8994_LINEOUT1N_MUTE_MASK 0x0040 /* LINEOUT1N_MUTE */
+#define WM8994_LINEOUT1N_MUTE_SHIFT 6 /* LINEOUT1N_MUTE */
+#define WM8994_LINEOUT1N_MUTE_WIDTH 1 /* LINEOUT1N_MUTE */
+#define WM8994_LINEOUT1P_MUTE 0x0020 /* LINEOUT1P_MUTE */
+#define WM8994_LINEOUT1P_MUTE_MASK 0x0020 /* LINEOUT1P_MUTE */
+#define WM8994_LINEOUT1P_MUTE_SHIFT 5 /* LINEOUT1P_MUTE */
+#define WM8994_LINEOUT1P_MUTE_WIDTH 1 /* LINEOUT1P_MUTE */
+#define WM8994_LINEOUT1_VOL 0x0010 /* LINEOUT1_VOL */
+#define WM8994_LINEOUT1_VOL_MASK 0x0010 /* LINEOUT1_VOL */
+#define WM8994_LINEOUT1_VOL_SHIFT 4 /* LINEOUT1_VOL */
+#define WM8994_LINEOUT1_VOL_WIDTH 1 /* LINEOUT1_VOL */
+#define WM8994_LINEOUT2N_MUTE 0x0004 /* LINEOUT2N_MUTE */
+#define WM8994_LINEOUT2N_MUTE_MASK 0x0004 /* LINEOUT2N_MUTE */
+#define WM8994_LINEOUT2N_MUTE_SHIFT 2 /* LINEOUT2N_MUTE */
+#define WM8994_LINEOUT2N_MUTE_WIDTH 1 /* LINEOUT2N_MUTE */
+#define WM8994_LINEOUT2P_MUTE 0x0002 /* LINEOUT2P_MUTE */
+#define WM8994_LINEOUT2P_MUTE_MASK 0x0002 /* LINEOUT2P_MUTE */
+#define WM8994_LINEOUT2P_MUTE_SHIFT 1 /* LINEOUT2P_MUTE */
+#define WM8994_LINEOUT2P_MUTE_WIDTH 1 /* LINEOUT2P_MUTE */
+#define WM8994_LINEOUT2_VOL 0x0001 /* LINEOUT2_VOL */
+#define WM8994_LINEOUT2_VOL_MASK 0x0001 /* LINEOUT2_VOL */
+#define WM8994_LINEOUT2_VOL_SHIFT 0 /* LINEOUT2_VOL */
+#define WM8994_LINEOUT2_VOL_WIDTH 1 /* LINEOUT2_VOL */
+
+/*
+ * R31 (0x1F) - HPOUT2 Volume
+ */
+#define WM8994_HPOUT2_MUTE 0x0020 /* HPOUT2_MUTE */
+#define WM8994_HPOUT2_MUTE_MASK 0x0020 /* HPOUT2_MUTE */
+#define WM8994_HPOUT2_MUTE_SHIFT 5 /* HPOUT2_MUTE */
+#define WM8994_HPOUT2_MUTE_WIDTH 1 /* HPOUT2_MUTE */
+#define WM8994_HPOUT2_VOL 0x0010 /* HPOUT2_VOL */
+#define WM8994_HPOUT2_VOL_MASK 0x0010 /* HPOUT2_VOL */
+#define WM8994_HPOUT2_VOL_SHIFT 4 /* HPOUT2_VOL */
+#define WM8994_HPOUT2_VOL_WIDTH 1 /* HPOUT2_VOL */
+
+/*
+ * R32 (0x20) - Left OPGA Volume
+ */
+#define WM8994_MIXOUT_VU 0x0100 /* MIXOUT_VU */
+#define WM8994_MIXOUT_VU_MASK 0x0100 /* MIXOUT_VU */
+#define WM8994_MIXOUT_VU_SHIFT 8 /* MIXOUT_VU */
+#define WM8994_MIXOUT_VU_WIDTH 1 /* MIXOUT_VU */
+#define WM8994_MIXOUTL_ZC 0x0080 /* MIXOUTL_ZC */
+#define WM8994_MIXOUTL_ZC_MASK 0x0080 /* MIXOUTL_ZC */
+#define WM8994_MIXOUTL_ZC_SHIFT 7 /* MIXOUTL_ZC */
+#define WM8994_MIXOUTL_ZC_WIDTH 1 /* MIXOUTL_ZC */
+#define WM8994_MIXOUTL_MUTE_N 0x0040 /* MIXOUTL_MUTE_N */
+#define WM8994_MIXOUTL_MUTE_N_MASK 0x0040 /* MIXOUTL_MUTE_N */
+#define WM8994_MIXOUTL_MUTE_N_SHIFT 6 /* MIXOUTL_MUTE_N */
+#define WM8994_MIXOUTL_MUTE_N_WIDTH 1 /* MIXOUTL_MUTE_N */
+#define WM8994_MIXOUTL_VOL_MASK 0x003F /* MIXOUTL_VOL - [5:0] */
+#define WM8994_MIXOUTL_VOL_SHIFT 0 /* MIXOUTL_VOL - [5:0] */
+#define WM8994_MIXOUTL_VOL_WIDTH 6 /* MIXOUTL_VOL - [5:0] */
+
+/*
+ * R33 (0x21) - Right OPGA Volume
+ */
+#define WM8994_MIXOUT_VU 0x0100 /* MIXOUT_VU */
+#define WM8994_MIXOUT_VU_MASK 0x0100 /* MIXOUT_VU */
+#define WM8994_MIXOUT_VU_SHIFT 8 /* MIXOUT_VU */
+#define WM8994_MIXOUT_VU_WIDTH 1 /* MIXOUT_VU */
+#define WM8994_MIXOUTR_ZC 0x0080 /* MIXOUTR_ZC */
+#define WM8994_MIXOUTR_ZC_MASK 0x0080 /* MIXOUTR_ZC */
+#define WM8994_MIXOUTR_ZC_SHIFT 7 /* MIXOUTR_ZC */
+#define WM8994_MIXOUTR_ZC_WIDTH 1 /* MIXOUTR_ZC */
+#define WM8994_MIXOUTR_MUTE_N 0x0040 /* MIXOUTR_MUTE_N */
+#define WM8994_MIXOUTR_MUTE_N_MASK 0x0040 /* MIXOUTR_MUTE_N */
+#define WM8994_MIXOUTR_MUTE_N_SHIFT 6 /* MIXOUTR_MUTE_N */
+#define WM8994_MIXOUTR_MUTE_N_WIDTH 1 /* MIXOUTR_MUTE_N */
+#define WM8994_MIXOUTR_VOL_MASK 0x003F /* MIXOUTR_VOL - [5:0] */
+#define WM8994_MIXOUTR_VOL_SHIFT 0 /* MIXOUTR_VOL - [5:0] */
+#define WM8994_MIXOUTR_VOL_WIDTH 6 /* MIXOUTR_VOL - [5:0] */
+
+/*
+ * R34 (0x22) - SPKMIXL Attenuation
+ */
+#define WM8994_DAC2L_SPKMIXL_VOL 0x0040 /* DAC2L_SPKMIXL_VOL */
+#define WM8994_DAC2L_SPKMIXL_VOL_MASK 0x0040 /* DAC2L_SPKMIXL_VOL */
+#define WM8994_DAC2L_SPKMIXL_VOL_SHIFT 6 /* DAC2L_SPKMIXL_VOL */
+#define WM8994_DAC2L_SPKMIXL_VOL_WIDTH 1 /* DAC2L_SPKMIXL_VOL */
+#define WM8994_MIXINL_SPKMIXL_VOL 0x0020 /* MIXINL_SPKMIXL_VOL */
+#define WM8994_MIXINL_SPKMIXL_VOL_MASK 0x0020 /* MIXINL_SPKMIXL_VOL */
+#define WM8994_MIXINL_SPKMIXL_VOL_SHIFT 5 /* MIXINL_SPKMIXL_VOL */
+#define WM8994_MIXINL_SPKMIXL_VOL_WIDTH 1 /* MIXINL_SPKMIXL_VOL */
+#define WM8994_IN1LP_SPKMIXL_VOL 0x0010 /* IN1LP_SPKMIXL_VOL */
+#define WM8994_IN1LP_SPKMIXL_VOL_MASK 0x0010 /* IN1LP_SPKMIXL_VOL */
+#define WM8994_IN1LP_SPKMIXL_VOL_SHIFT 4 /* IN1LP_SPKMIXL_VOL */
+#define WM8994_IN1LP_SPKMIXL_VOL_WIDTH 1 /* IN1LP_SPKMIXL_VOL */
+#define WM8994_MIXOUTL_SPKMIXL_VOL 0x0008 /* MIXOUTL_SPKMIXL_VOL */
+#define WM8994_MIXOUTL_SPKMIXL_VOL_MASK 0x0008 /* MIXOUTL_SPKMIXL_VOL */
+#define WM8994_MIXOUTL_SPKMIXL_VOL_SHIFT 3 /* MIXOUTL_SPKMIXL_VOL */
+#define WM8994_MIXOUTL_SPKMIXL_VOL_WIDTH 1 /* MIXOUTL_SPKMIXL_VOL */
+#define WM8994_DAC1L_SPKMIXL_VOL 0x0004 /* DAC1L_SPKMIXL_VOL */
+#define WM8994_DAC1L_SPKMIXL_VOL_MASK 0x0004 /* DAC1L_SPKMIXL_VOL */
+#define WM8994_DAC1L_SPKMIXL_VOL_SHIFT 2 /* DAC1L_SPKMIXL_VOL */
+#define WM8994_DAC1L_SPKMIXL_VOL_WIDTH 1 /* DAC1L_SPKMIXL_VOL */
+#define WM8994_SPKMIXL_VOL_MASK 0x0003 /* SPKMIXL_VOL - [1:0] */
+#define WM8994_SPKMIXL_VOL_SHIFT 0 /* SPKMIXL_VOL - [1:0] */
+#define WM8994_SPKMIXL_VOL_WIDTH 2 /* SPKMIXL_VOL - [1:0] */
+
+/*
+ * R35 (0x23) - SPKMIXR Attenuation
+ */
+#define WM8994_SPKOUT_CLASSAB 0x0100 /* SPKOUT_CLASSAB */
+#define WM8994_SPKOUT_CLASSAB_MASK 0x0100 /* SPKOUT_CLASSAB */
+#define WM8994_SPKOUT_CLASSAB_SHIFT 8 /* SPKOUT_CLASSAB */
+#define WM8994_SPKOUT_CLASSAB_WIDTH 1 /* SPKOUT_CLASSAB */
+#define WM8994_DAC2R_SPKMIXR_VOL 0x0040 /* DAC2R_SPKMIXR_VOL */
+#define WM8994_DAC2R_SPKMIXR_VOL_MASK 0x0040 /* DAC2R_SPKMIXR_VOL */
+#define WM8994_DAC2R_SPKMIXR_VOL_SHIFT 6 /* DAC2R_SPKMIXR_VOL */
+#define WM8994_DAC2R_SPKMIXR_VOL_WIDTH 1 /* DAC2R_SPKMIXR_VOL */
+#define WM8994_MIXINR_SPKMIXR_VOL 0x0020 /* MIXINR_SPKMIXR_VOL */
+#define WM8994_MIXINR_SPKMIXR_VOL_MASK 0x0020 /* MIXINR_SPKMIXR_VOL */
+#define WM8994_MIXINR_SPKMIXR_VOL_SHIFT 5 /* MIXINR_SPKMIXR_VOL */
+#define WM8994_MIXINR_SPKMIXR_VOL_WIDTH 1 /* MIXINR_SPKMIXR_VOL */
+#define WM8994_IN1RP_SPKMIXR_VOL 0x0010 /* IN1RP_SPKMIXR_VOL */
+#define WM8994_IN1RP_SPKMIXR_VOL_MASK 0x0010 /* IN1RP_SPKMIXR_VOL */
+#define WM8994_IN1RP_SPKMIXR_VOL_SHIFT 4 /* IN1RP_SPKMIXR_VOL */
+#define WM8994_IN1RP_SPKMIXR_VOL_WIDTH 1 /* IN1RP_SPKMIXR_VOL */
+#define WM8994_MIXOUTR_SPKMIXR_VOL 0x0008 /* MIXOUTR_SPKMIXR_VOL */
+#define WM8994_MIXOUTR_SPKMIXR_VOL_MASK 0x0008 /* MIXOUTR_SPKMIXR_VOL */
+#define WM8994_MIXOUTR_SPKMIXR_VOL_SHIFT 3 /* MIXOUTR_SPKMIXR_VOL */
+#define WM8994_MIXOUTR_SPKMIXR_VOL_WIDTH 1 /* MIXOUTR_SPKMIXR_VOL */
+#define WM8994_DAC1R_SPKMIXR_VOL 0x0004 /* DAC1R_SPKMIXR_VOL */
+#define WM8994_DAC1R_SPKMIXR_VOL_MASK 0x0004 /* DAC1R_SPKMIXR_VOL */
+#define WM8994_DAC1R_SPKMIXR_VOL_SHIFT 2 /* DAC1R_SPKMIXR_VOL */
+#define WM8994_DAC1R_SPKMIXR_VOL_WIDTH 1 /* DAC1R_SPKMIXR_VOL */
+#define WM8994_SPKMIXR_VOL_MASK 0x0003 /* SPKMIXR_VOL - [1:0] */
+#define WM8994_SPKMIXR_VOL_SHIFT 0 /* SPKMIXR_VOL - [1:0] */
+#define WM8994_SPKMIXR_VOL_WIDTH 2 /* SPKMIXR_VOL - [1:0] */
+
+/*
+ * R36 (0x24) - SPKOUT Mixers
+ */
+#define WM8994_IN2LRP_TO_SPKOUTL 0x0020 /* IN2LRP_TO_SPKOUTL */
+#define WM8994_IN2LRP_TO_SPKOUTL_MASK 0x0020 /* IN2LRP_TO_SPKOUTL */
+#define WM8994_IN2LRP_TO_SPKOUTL_SHIFT 5 /* IN2LRP_TO_SPKOUTL */
+#define WM8994_IN2LRP_TO_SPKOUTL_WIDTH 1 /* IN2LRP_TO_SPKOUTL */
+#define WM8994_SPKMIXL_TO_SPKOUTL 0x0010 /* SPKMIXL_TO_SPKOUTL */
+#define WM8994_SPKMIXL_TO_SPKOUTL_MASK 0x0010 /* SPKMIXL_TO_SPKOUTL */
+#define WM8994_SPKMIXL_TO_SPKOUTL_SHIFT 4 /* SPKMIXL_TO_SPKOUTL */
+#define WM8994_SPKMIXL_TO_SPKOUTL_WIDTH 1 /* SPKMIXL_TO_SPKOUTL */
+#define WM8994_SPKMIXR_TO_SPKOUTL 0x0008 /* SPKMIXR_TO_SPKOUTL */
+#define WM8994_SPKMIXR_TO_SPKOUTL_MASK 0x0008 /* SPKMIXR_TO_SPKOUTL */
+#define WM8994_SPKMIXR_TO_SPKOUTL_SHIFT 3 /* SPKMIXR_TO_SPKOUTL */
+#define WM8994_SPKMIXR_TO_SPKOUTL_WIDTH 1 /* SPKMIXR_TO_SPKOUTL */
+#define WM8994_IN2LRP_TO_SPKOUTR 0x0004 /* IN2LRP_TO_SPKOUTR */
+#define WM8994_IN2LRP_TO_SPKOUTR_MASK 0x0004 /* IN2LRP_TO_SPKOUTR */
+#define WM8994_IN2LRP_TO_SPKOUTR_SHIFT 2 /* IN2LRP_TO_SPKOUTR */
+#define WM8994_IN2LRP_TO_SPKOUTR_WIDTH 1 /* IN2LRP_TO_SPKOUTR */
+#define WM8994_SPKMIXL_TO_SPKOUTR 0x0002 /* SPKMIXL_TO_SPKOUTR */
+#define WM8994_SPKMIXL_TO_SPKOUTR_MASK 0x0002 /* SPKMIXL_TO_SPKOUTR */
+#define WM8994_SPKMIXL_TO_SPKOUTR_SHIFT 1 /* SPKMIXL_TO_SPKOUTR */
+#define WM8994_SPKMIXL_TO_SPKOUTR_WIDTH 1 /* SPKMIXL_TO_SPKOUTR */
+#define WM8994_SPKMIXR_TO_SPKOUTR 0x0001 /* SPKMIXR_TO_SPKOUTR */
+#define WM8994_SPKMIXR_TO_SPKOUTR_MASK 0x0001 /* SPKMIXR_TO_SPKOUTR */
+#define WM8994_SPKMIXR_TO_SPKOUTR_SHIFT 0 /* SPKMIXR_TO_SPKOUTR */
+#define WM8994_SPKMIXR_TO_SPKOUTR_WIDTH 1 /* SPKMIXR_TO_SPKOUTR */
+
+/*
+ * R37 (0x25) - ClassD
+ */
+#define WM8994_SPKOUTL_BOOST_MASK 0x0038 /* SPKOUTL_BOOST - [5:3] */
+#define WM8994_SPKOUTL_BOOST_SHIFT 3 /* SPKOUTL_BOOST - [5:3] */
+#define WM8994_SPKOUTL_BOOST_WIDTH 3 /* SPKOUTL_BOOST - [5:3] */
+#define WM8994_SPKOUTR_BOOST_MASK 0x0007 /* SPKOUTR_BOOST - [2:0] */
+#define WM8994_SPKOUTR_BOOST_SHIFT 0 /* SPKOUTR_BOOST - [2:0] */
+#define WM8994_SPKOUTR_BOOST_WIDTH 3 /* SPKOUTR_BOOST - [2:0] */
+
+/*
+ * R38 (0x26) - Speaker Volume Left
+ */
+#define WM8994_SPKOUT_VU 0x0100 /* SPKOUT_VU */
+#define WM8994_SPKOUT_VU_MASK 0x0100 /* SPKOUT_VU */
+#define WM8994_SPKOUT_VU_SHIFT 8 /* SPKOUT_VU */
+#define WM8994_SPKOUT_VU_WIDTH 1 /* SPKOUT_VU */
+#define WM8994_SPKOUTL_ZC 0x0080 /* SPKOUTL_ZC */
+#define WM8994_SPKOUTL_ZC_MASK 0x0080 /* SPKOUTL_ZC */
+#define WM8994_SPKOUTL_ZC_SHIFT 7 /* SPKOUTL_ZC */
+#define WM8994_SPKOUTL_ZC_WIDTH 1 /* SPKOUTL_ZC */
+#define WM8994_SPKOUTL_MUTE_N 0x0040 /* SPKOUTL_MUTE_N */
+#define WM8994_SPKOUTL_MUTE_N_MASK 0x0040 /* SPKOUTL_MUTE_N */
+#define WM8994_SPKOUTL_MUTE_N_SHIFT 6 /* SPKOUTL_MUTE_N */
+#define WM8994_SPKOUTL_MUTE_N_WIDTH 1 /* SPKOUTL_MUTE_N */
+#define WM8994_SPKOUTL_VOL_MASK 0x003F /* SPKOUTL_VOL - [5:0] */
+#define WM8994_SPKOUTL_VOL_SHIFT 0 /* SPKOUTL_VOL - [5:0] */
+#define WM8994_SPKOUTL_VOL_WIDTH 6 /* SPKOUTL_VOL - [5:0] */
+
+/*
+ * R39 (0x27) - Speaker Volume Right
+ */
+#define WM8994_SPKOUT_VU 0x0100 /* SPKOUT_VU */
+#define WM8994_SPKOUT_VU_MASK 0x0100 /* SPKOUT_VU */
+#define WM8994_SPKOUT_VU_SHIFT 8 /* SPKOUT_VU */
+#define WM8994_SPKOUT_VU_WIDTH 1 /* SPKOUT_VU */
+#define WM8994_SPKOUTR_ZC 0x0080 /* SPKOUTR_ZC */
+#define WM8994_SPKOUTR_ZC_MASK 0x0080 /* SPKOUTR_ZC */
+#define WM8994_SPKOUTR_ZC_SHIFT 7 /* SPKOUTR_ZC */
+#define WM8994_SPKOUTR_ZC_WIDTH 1 /* SPKOUTR_ZC */
+#define WM8994_SPKOUTR_MUTE_N 0x0040 /* SPKOUTR_MUTE_N */
+#define WM8994_SPKOUTR_MUTE_N_MASK 0x0040 /* SPKOUTR_MUTE_N */
+#define WM8994_SPKOUTR_MUTE_N_SHIFT 6 /* SPKOUTR_MUTE_N */
+#define WM8994_SPKOUTR_MUTE_N_WIDTH 1 /* SPKOUTR_MUTE_N */
+#define WM8994_SPKOUTR_VOL_MASK 0x003F /* SPKOUTR_VOL - [5:0] */
+#define WM8994_SPKOUTR_VOL_SHIFT 0 /* SPKOUTR_VOL - [5:0] */
+#define WM8994_SPKOUTR_VOL_WIDTH 6 /* SPKOUTR_VOL - [5:0] */
+
+/*
+ * R40 (0x28) - Input Mixer (2)
+ */
+#define WM8994_IN2LP_TO_IN2L 0x0080 /* IN2LP_TO_IN2L */
+#define WM8994_IN2LP_TO_IN2L_MASK 0x0080 /* IN2LP_TO_IN2L */
+#define WM8994_IN2LP_TO_IN2L_SHIFT 7 /* IN2LP_TO_IN2L */
+#define WM8994_IN2LP_TO_IN2L_WIDTH 1 /* IN2LP_TO_IN2L */
+#define WM8994_IN2LN_TO_IN2L 0x0040 /* IN2LN_TO_IN2L */
+#define WM8994_IN2LN_TO_IN2L_MASK 0x0040 /* IN2LN_TO_IN2L */
+#define WM8994_IN2LN_TO_IN2L_SHIFT 6 /* IN2LN_TO_IN2L */
+#define WM8994_IN2LN_TO_IN2L_WIDTH 1 /* IN2LN_TO_IN2L */
+#define WM8994_IN1LP_TO_IN1L 0x0020 /* IN1LP_TO_IN1L */
+#define WM8994_IN1LP_TO_IN1L_MASK 0x0020 /* IN1LP_TO_IN1L */
+#define WM8994_IN1LP_TO_IN1L_SHIFT 5 /* IN1LP_TO_IN1L */
+#define WM8994_IN1LP_TO_IN1L_WIDTH 1 /* IN1LP_TO_IN1L */
+#define WM8994_IN1LN_TO_IN1L 0x0010 /* IN1LN_TO_IN1L */
+#define WM8994_IN1LN_TO_IN1L_MASK 0x0010 /* IN1LN_TO_IN1L */
+#define WM8994_IN1LN_TO_IN1L_SHIFT 4 /* IN1LN_TO_IN1L */
+#define WM8994_IN1LN_TO_IN1L_WIDTH 1 /* IN1LN_TO_IN1L */
+#define WM8994_IN2RP_TO_IN2R 0x0008 /* IN2RP_TO_IN2R */
+#define WM8994_IN2RP_TO_IN2R_MASK 0x0008 /* IN2RP_TO_IN2R */
+#define WM8994_IN2RP_TO_IN2R_SHIFT 3 /* IN2RP_TO_IN2R */
+#define WM8994_IN2RP_TO_IN2R_WIDTH 1 /* IN2RP_TO_IN2R */
+#define WM8994_IN2RN_TO_IN2R 0x0004 /* IN2RN_TO_IN2R */
+#define WM8994_IN2RN_TO_IN2R_MASK 0x0004 /* IN2RN_TO_IN2R */
+#define WM8994_IN2RN_TO_IN2R_SHIFT 2 /* IN2RN_TO_IN2R */
+#define WM8994_IN2RN_TO_IN2R_WIDTH 1 /* IN2RN_TO_IN2R */
+#define WM8994_IN1RP_TO_IN1R 0x0002 /* IN1RP_TO_IN1R */
+#define WM8994_IN1RP_TO_IN1R_MASK 0x0002 /* IN1RP_TO_IN1R */
+#define WM8994_IN1RP_TO_IN1R_SHIFT 1 /* IN1RP_TO_IN1R */
+#define WM8994_IN1RP_TO_IN1R_WIDTH 1 /* IN1RP_TO_IN1R */
+#define WM8994_IN1RN_TO_IN1R 0x0001 /* IN1RN_TO_IN1R */
+#define WM8994_IN1RN_TO_IN1R_MASK 0x0001 /* IN1RN_TO_IN1R */
+#define WM8994_IN1RN_TO_IN1R_SHIFT 0 /* IN1RN_TO_IN1R */
+#define WM8994_IN1RN_TO_IN1R_WIDTH 1 /* IN1RN_TO_IN1R */
+
+/*
+ * R41 (0x29) - Input Mixer (3)
+ */
+#define WM8994_IN2L_TO_MIXINL 0x0100 /* IN2L_TO_MIXINL */
+#define WM8994_IN2L_TO_MIXINL_MASK 0x0100 /* IN2L_TO_MIXINL */
+#define WM8994_IN2L_TO_MIXINL_SHIFT 8 /* IN2L_TO_MIXINL */
+#define WM8994_IN2L_TO_MIXINL_WIDTH 1 /* IN2L_TO_MIXINL */
+#define WM8994_IN2L_MIXINL_VOL 0x0080 /* IN2L_MIXINL_VOL */
+#define WM8994_IN2L_MIXINL_VOL_MASK 0x0080 /* IN2L_MIXINL_VOL */
+#define WM8994_IN2L_MIXINL_VOL_SHIFT 7 /* IN2L_MIXINL_VOL */
+#define WM8994_IN2L_MIXINL_VOL_WIDTH 1 /* IN2L_MIXINL_VOL */
+#define WM8994_IN1L_TO_MIXINL 0x0020 /* IN1L_TO_MIXINL */
+#define WM8994_IN1L_TO_MIXINL_MASK 0x0020 /* IN1L_TO_MIXINL */
+#define WM8994_IN1L_TO_MIXINL_SHIFT 5 /* IN1L_TO_MIXINL */
+#define WM8994_IN1L_TO_MIXINL_WIDTH 1 /* IN1L_TO_MIXINL */
+#define WM8994_IN1L_MIXINL_VOL 0x0010 /* IN1L_MIXINL_VOL */
+#define WM8994_IN1L_MIXINL_VOL_MASK 0x0010 /* IN1L_MIXINL_VOL */
+#define WM8994_IN1L_MIXINL_VOL_SHIFT 4 /* IN1L_MIXINL_VOL */
+#define WM8994_IN1L_MIXINL_VOL_WIDTH 1 /* IN1L_MIXINL_VOL */
+#define WM8994_MIXOUTL_MIXINL_VOL_MASK 0x0007 /* MIXOUTL_MIXINL_VOL - [2:0] */
+#define WM8994_MIXOUTL_MIXINL_VOL_SHIFT 0 /* MIXOUTL_MIXINL_VOL - [2:0] */
+#define WM8994_MIXOUTL_MIXINL_VOL_WIDTH 3 /* MIXOUTL_MIXINL_VOL - [2:0] */
+
+/*
+ * R42 (0x2A) - Input Mixer (4)
+ */
+#define WM8994_IN2R_TO_MIXINR 0x0100 /* IN2R_TO_MIXINR */
+#define WM8994_IN2R_TO_MIXINR_MASK 0x0100 /* IN2R_TO_MIXINR */
+#define WM8994_IN2R_TO_MIXINR_SHIFT 8 /* IN2R_TO_MIXINR */
+#define WM8994_IN2R_TO_MIXINR_WIDTH 1 /* IN2R_TO_MIXINR */
+#define WM8994_IN2R_MIXINR_VOL 0x0080 /* IN2R_MIXINR_VOL */
+#define WM8994_IN2R_MIXINR_VOL_MASK 0x0080 /* IN2R_MIXINR_VOL */
+#define WM8994_IN2R_MIXINR_VOL_SHIFT 7 /* IN2R_MIXINR_VOL */
+#define WM8994_IN2R_MIXINR_VOL_WIDTH 1 /* IN2R_MIXINR_VOL */
+#define WM8994_IN1R_TO_MIXINR 0x0020 /* IN1R_TO_MIXINR */
+#define WM8994_IN1R_TO_MIXINR_MASK 0x0020 /* IN1R_TO_MIXINR */
+#define WM8994_IN1R_TO_MIXINR_SHIFT 5 /* IN1R_TO_MIXINR */
+#define WM8994_IN1R_TO_MIXINR_WIDTH 1 /* IN1R_TO_MIXINR */
+#define WM8994_IN1R_MIXINR_VOL 0x0010 /* IN1R_MIXINR_VOL */
+#define WM8994_IN1R_MIXINR_VOL_MASK 0x0010 /* IN1R_MIXINR_VOL */
+#define WM8994_IN1R_MIXINR_VOL_SHIFT 4 /* IN1R_MIXINR_VOL */
+#define WM8994_IN1R_MIXINR_VOL_WIDTH 1 /* IN1R_MIXINR_VOL */
+#define WM8994_MIXOUTR_MIXINR_VOL_MASK 0x0007 /* MIXOUTR_MIXINR_VOL - [2:0] */
+#define WM8994_MIXOUTR_MIXINR_VOL_SHIFT 0 /* MIXOUTR_MIXINR_VOL - [2:0] */
+#define WM8994_MIXOUTR_MIXINR_VOL_WIDTH 3 /* MIXOUTR_MIXINR_VOL - [2:0] */
+
+/*
+ * R43 (0x2B) - Input Mixer (5)
+ */
+#define WM8994_IN1LP_MIXINL_VOL_MASK 0x01C0 /* IN1LP_MIXINL_VOL - [8:6] */
+#define WM8994_IN1LP_MIXINL_VOL_SHIFT 6 /* IN1LP_MIXINL_VOL - [8:6] */
+#define WM8994_IN1LP_MIXINL_VOL_WIDTH 3 /* IN1LP_MIXINL_VOL - [8:6] */
+#define WM8994_IN2LRP_MIXINL_VOL_MASK 0x0007 /* IN2LRP_MIXINL_VOL - [2:0] */
+#define WM8994_IN2LRP_MIXINL_VOL_SHIFT 0 /* IN2LRP_MIXINL_VOL - [2:0] */
+#define WM8994_IN2LRP_MIXINL_VOL_WIDTH 3 /* IN2LRP_MIXINL_VOL - [2:0] */
+
+/*
+ * R44 (0x2C) - Input Mixer (6)
+ */
+#define WM8994_IN1RP_MIXINR_VOL_MASK 0x01C0 /* IN1RP_MIXINR_VOL - [8:6] */
+#define WM8994_IN1RP_MIXINR_VOL_SHIFT 6 /* IN1RP_MIXINR_VOL - [8:6] */
+#define WM8994_IN1RP_MIXINR_VOL_WIDTH 3 /* IN1RP_MIXINR_VOL - [8:6] */
+#define WM8994_IN2LRP_MIXINR_VOL_MASK 0x0007 /* IN2LRP_MIXINR_VOL - [2:0] */
+#define WM8994_IN2LRP_MIXINR_VOL_SHIFT 0 /* IN2LRP_MIXINR_VOL - [2:0] */
+#define WM8994_IN2LRP_MIXINR_VOL_WIDTH 3 /* IN2LRP_MIXINR_VOL - [2:0] */
+
+/*
+ * R45 (0x2D) - Output Mixer (1)
+ */
+#define WM8994_DAC1L_TO_HPOUT1L 0x0100 /* DAC1L_TO_HPOUT1L */
+#define WM8994_DAC1L_TO_HPOUT1L_MASK 0x0100 /* DAC1L_TO_HPOUT1L */
+#define WM8994_DAC1L_TO_HPOUT1L_SHIFT 8 /* DAC1L_TO_HPOUT1L */
+#define WM8994_DAC1L_TO_HPOUT1L_WIDTH 1 /* DAC1L_TO_HPOUT1L */
+#define WM8994_MIXINR_TO_MIXOUTL 0x0080 /* MIXINR_TO_MIXOUTL */
+#define WM8994_MIXINR_TO_MIXOUTL_MASK 0x0080 /* MIXINR_TO_MIXOUTL */
+#define WM8994_MIXINR_TO_MIXOUTL_SHIFT 7 /* MIXINR_TO_MIXOUTL */
+#define WM8994_MIXINR_TO_MIXOUTL_WIDTH 1 /* MIXINR_TO_MIXOUTL */
+#define WM8994_MIXINL_TO_MIXOUTL 0x0040 /* MIXINL_TO_MIXOUTL */
+#define WM8994_MIXINL_TO_MIXOUTL_MASK 0x0040 /* MIXINL_TO_MIXOUTL */
+#define WM8994_MIXINL_TO_MIXOUTL_SHIFT 6 /* MIXINL_TO_MIXOUTL */
+#define WM8994_MIXINL_TO_MIXOUTL_WIDTH 1 /* MIXINL_TO_MIXOUTL */
+#define WM8994_IN2RN_TO_MIXOUTL 0x0020 /* IN2RN_TO_MIXOUTL */
+#define WM8994_IN2RN_TO_MIXOUTL_MASK 0x0020 /* IN2RN_TO_MIXOUTL */
+#define WM8994_IN2RN_TO_MIXOUTL_SHIFT 5 /* IN2RN_TO_MIXOUTL */
+#define WM8994_IN2RN_TO_MIXOUTL_WIDTH 1 /* IN2RN_TO_MIXOUTL */
+#define WM8994_IN2LN_TO_MIXOUTL 0x0010 /* IN2LN_TO_MIXOUTL */
+#define WM8994_IN2LN_TO_MIXOUTL_MASK 0x0010 /* IN2LN_TO_MIXOUTL */
+#define WM8994_IN2LN_TO_MIXOUTL_SHIFT 4 /* IN2LN_TO_MIXOUTL */
+#define WM8994_IN2LN_TO_MIXOUTL_WIDTH 1 /* IN2LN_TO_MIXOUTL */
+#define WM8994_IN1R_TO_MIXOUTL 0x0008 /* IN1R_TO_MIXOUTL */
+#define WM8994_IN1R_TO_MIXOUTL_MASK 0x0008 /* IN1R_TO_MIXOUTL */
+#define WM8994_IN1R_TO_MIXOUTL_SHIFT 3 /* IN1R_TO_MIXOUTL */
+#define WM8994_IN1R_TO_MIXOUTL_WIDTH 1 /* IN1R_TO_MIXOUTL */
+#define WM8994_IN1L_TO_MIXOUTL 0x0004 /* IN1L_TO_MIXOUTL */
+#define WM8994_IN1L_TO_MIXOUTL_MASK 0x0004 /* IN1L_TO_MIXOUTL */
+#define WM8994_IN1L_TO_MIXOUTL_SHIFT 2 /* IN1L_TO_MIXOUTL */
+#define WM8994_IN1L_TO_MIXOUTL_WIDTH 1 /* IN1L_TO_MIXOUTL */
+#define WM8994_IN2LP_TO_MIXOUTL 0x0002 /* IN2LP_TO_MIXOUTL */
+#define WM8994_IN2LP_TO_MIXOUTL_MASK 0x0002 /* IN2LP_TO_MIXOUTL */
+#define WM8994_IN2LP_TO_MIXOUTL_SHIFT 1 /* IN2LP_TO_MIXOUTL */
+#define WM8994_IN2LP_TO_MIXOUTL_WIDTH 1 /* IN2LP_TO_MIXOUTL */
+#define WM8994_DAC1L_TO_MIXOUTL 0x0001 /* DAC1L_TO_MIXOUTL */
+#define WM8994_DAC1L_TO_MIXOUTL_MASK 0x0001 /* DAC1L_TO_MIXOUTL */
+#define WM8994_DAC1L_TO_MIXOUTL_SHIFT 0 /* DAC1L_TO_MIXOUTL */
+#define WM8994_DAC1L_TO_MIXOUTL_WIDTH 1 /* DAC1L_TO_MIXOUTL */
+
+/*
+ * R46 (0x2E) - Output Mixer (2)
+ */
+#define WM8994_DAC1R_TO_HPOUT1R 0x0100 /* DAC1R_TO_HPOUT1R */
+#define WM8994_DAC1R_TO_HPOUT1R_MASK 0x0100 /* DAC1R_TO_HPOUT1R */
+#define WM8994_DAC1R_TO_HPOUT1R_SHIFT 8 /* DAC1R_TO_HPOUT1R */
+#define WM8994_DAC1R_TO_HPOUT1R_WIDTH 1 /* DAC1R_TO_HPOUT1R */
+#define WM8994_MIXINL_TO_MIXOUTR 0x0080 /* MIXINL_TO_MIXOUTR */
+#define WM8994_MIXINL_TO_MIXOUTR_MASK 0x0080 /* MIXINL_TO_MIXOUTR */
+#define WM8994_MIXINL_TO_MIXOUTR_SHIFT 7 /* MIXINL_TO_MIXOUTR */
+#define WM8994_MIXINL_TO_MIXOUTR_WIDTH 1 /* MIXINL_TO_MIXOUTR */
+#define WM8994_MIXINR_TO_MIXOUTR 0x0040 /* MIXINR_TO_MIXOUTR */
+#define WM8994_MIXINR_TO_MIXOUTR_MASK 0x0040 /* MIXINR_TO_MIXOUTR */
+#define WM8994_MIXINR_TO_MIXOUTR_SHIFT 6 /* MIXINR_TO_MIXOUTR */
+#define WM8994_MIXINR_TO_MIXOUTR_WIDTH 1 /* MIXINR_TO_MIXOUTR */
+#define WM8994_IN2LN_TO_MIXOUTR 0x0020 /* IN2LN_TO_MIXOUTR */
+#define WM8994_IN2LN_TO_MIXOUTR_MASK 0x0020 /* IN2LN_TO_MIXOUTR */
+#define WM8994_IN2LN_TO_MIXOUTR_SHIFT 5 /* IN2LN_TO_MIXOUTR */
+#define WM8994_IN2LN_TO_MIXOUTR_WIDTH 1 /* IN2LN_TO_MIXOUTR */
+#define WM8994_IN2RN_TO_MIXOUTR 0x0010 /* IN2RN_TO_MIXOUTR */
+#define WM8994_IN2RN_TO_MIXOUTR_MASK 0x0010 /* IN2RN_TO_MIXOUTR */
+#define WM8994_IN2RN_TO_MIXOUTR_SHIFT 4 /* IN2RN_TO_MIXOUTR */
+#define WM8994_IN2RN_TO_MIXOUTR_WIDTH 1 /* IN2RN_TO_MIXOUTR */
+#define WM8994_IN1L_TO_MIXOUTR 0x0008 /* IN1L_TO_MIXOUTR */
+#define WM8994_IN1L_TO_MIXOUTR_MASK 0x0008 /* IN1L_TO_MIXOUTR */
+#define WM8994_IN1L_TO_MIXOUTR_SHIFT 3 /* IN1L_TO_MIXOUTR */
+#define WM8994_IN1L_TO_MIXOUTR_WIDTH 1 /* IN1L_TO_MIXOUTR */
+#define WM8994_IN1R_TO_MIXOUTR 0x0004 /* IN1R_TO_MIXOUTR */
+#define WM8994_IN1R_TO_MIXOUTR_MASK 0x0004 /* IN1R_TO_MIXOUTR */
+#define WM8994_IN1R_TO_MIXOUTR_SHIFT 2 /* IN1R_TO_MIXOUTR */
+#define WM8994_IN1R_TO_MIXOUTR_WIDTH 1 /* IN1R_TO_MIXOUTR */
+#define WM8994_IN2RP_TO_MIXOUTR 0x0002 /* IN2RP_TO_MIXOUTR */
+#define WM8994_IN2RP_TO_MIXOUTR_MASK 0x0002 /* IN2RP_TO_MIXOUTR */
+#define WM8994_IN2RP_TO_MIXOUTR_SHIFT 1 /* IN2RP_TO_MIXOUTR */
+#define WM8994_IN2RP_TO_MIXOUTR_WIDTH 1 /* IN2RP_TO_MIXOUTR */
+#define WM8994_DAC1R_TO_MIXOUTR 0x0001 /* DAC1R_TO_MIXOUTR */
+#define WM8994_DAC1R_TO_MIXOUTR_MASK 0x0001 /* DAC1R_TO_MIXOUTR */
+#define WM8994_DAC1R_TO_MIXOUTR_SHIFT 0 /* DAC1R_TO_MIXOUTR */
+#define WM8994_DAC1R_TO_MIXOUTR_WIDTH 1 /* DAC1R_TO_MIXOUTR */
+
+/*
+ * R47 (0x2F) - Output Mixer (3)
+ */
+#define WM8994_IN2LP_MIXOUTL_VOL_MASK 0x0E00 /* IN2LP_MIXOUTL_VOL - [11:9] */
+#define WM8994_IN2LP_MIXOUTL_VOL_SHIFT 9 /* IN2LP_MIXOUTL_VOL - [11:9] */
+#define WM8994_IN2LP_MIXOUTL_VOL_WIDTH 3 /* IN2LP_MIXOUTL_VOL - [11:9] */
+#define WM8994_IN2LN_MIXOUTL_VOL_MASK 0x01C0 /* IN2LN_MIXOUTL_VOL - [8:6] */
+#define WM8994_IN2LN_MIXOUTL_VOL_SHIFT 6 /* IN2LN_MIXOUTL_VOL - [8:6] */
+#define WM8994_IN2LN_MIXOUTL_VOL_WIDTH 3 /* IN2LN_MIXOUTL_VOL - [8:6] */
+#define WM8994_IN1R_MIXOUTL_VOL_MASK 0x0038 /* IN1R_MIXOUTL_VOL - [5:3] */
+#define WM8994_IN1R_MIXOUTL_VOL_SHIFT 3 /* IN1R_MIXOUTL_VOL - [5:3] */
+#define WM8994_IN1R_MIXOUTL_VOL_WIDTH 3 /* IN1R_MIXOUTL_VOL - [5:3] */
+#define WM8994_IN1L_MIXOUTL_VOL_MASK 0x0007 /* IN1L_MIXOUTL_VOL - [2:0] */
+#define WM8994_IN1L_MIXOUTL_VOL_SHIFT 0 /* IN1L_MIXOUTL_VOL - [2:0] */
+#define WM8994_IN1L_MIXOUTL_VOL_WIDTH 3 /* IN1L_MIXOUTL_VOL - [2:0] */
+
+/*
+ * R48 (0x30) - Output Mixer (4)
+ */
+#define WM8994_IN2RP_MIXOUTR_VOL_MASK 0x0E00 /* IN2RP_MIXOUTR_VOL - [11:9] */
+#define WM8994_IN2RP_MIXOUTR_VOL_SHIFT 9 /* IN2RP_MIXOUTR_VOL - [11:9] */
+#define WM8994_IN2RP_MIXOUTR_VOL_WIDTH 3 /* IN2RP_MIXOUTR_VOL - [11:9] */
+#define WM8994_IN2RN_MIXOUTR_VOL_MASK 0x01C0 /* IN2RN_MIXOUTR_VOL - [8:6] */
+#define WM8994_IN2RN_MIXOUTR_VOL_SHIFT 6 /* IN2RN_MIXOUTR_VOL - [8:6] */
+#define WM8994_IN2RN_MIXOUTR_VOL_WIDTH 3 /* IN2RN_MIXOUTR_VOL - [8:6] */
+#define WM8994_IN1L_MIXOUTR_VOL_MASK 0x0038 /* IN1L_MIXOUTR_VOL - [5:3] */
+#define WM8994_IN1L_MIXOUTR_VOL_SHIFT 3 /* IN1L_MIXOUTR_VOL - [5:3] */
+#define WM8994_IN1L_MIXOUTR_VOL_WIDTH 3 /* IN1L_MIXOUTR_VOL - [5:3] */
+#define WM8994_IN1R_MIXOUTR_VOL_MASK 0x0007 /* IN1R_MIXOUTR_VOL - [2:0] */
+#define WM8994_IN1R_MIXOUTR_VOL_SHIFT 0 /* IN1R_MIXOUTR_VOL - [2:0] */
+#define WM8994_IN1R_MIXOUTR_VOL_WIDTH 3 /* IN1R_MIXOUTR_VOL - [2:0] */
+
+/*
+ * R49 (0x31) - Output Mixer (5)
+ */
+#define WM8994_DAC1L_MIXOUTL_VOL_MASK 0x0E00 /* DAC1L_MIXOUTL_VOL - [11:9] */
+#define WM8994_DAC1L_MIXOUTL_VOL_SHIFT 9 /* DAC1L_MIXOUTL_VOL - [11:9] */
+#define WM8994_DAC1L_MIXOUTL_VOL_WIDTH 3 /* DAC1L_MIXOUTL_VOL - [11:9] */
+#define WM8994_IN2RN_MIXOUTL_VOL_MASK 0x01C0 /* IN2RN_MIXOUTL_VOL - [8:6] */
+#define WM8994_IN2RN_MIXOUTL_VOL_SHIFT 6 /* IN2RN_MIXOUTL_VOL - [8:6] */
+#define WM8994_IN2RN_MIXOUTL_VOL_WIDTH 3 /* IN2RN_MIXOUTL_VOL - [8:6] */
+#define WM8994_MIXINR_MIXOUTL_VOL_MASK 0x0038 /* MIXINR_MIXOUTL_VOL - [5:3] */
+#define WM8994_MIXINR_MIXOUTL_VOL_SHIFT 3 /* MIXINR_MIXOUTL_VOL - [5:3] */
+#define WM8994_MIXINR_MIXOUTL_VOL_WIDTH 3 /* MIXINR_MIXOUTL_VOL - [5:3] */
+#define WM8994_MIXINL_MIXOUTL_VOL_MASK 0x0007 /* MIXINL_MIXOUTL_VOL - [2:0] */
+#define WM8994_MIXINL_MIXOUTL_VOL_SHIFT 0 /* MIXINL_MIXOUTL_VOL - [2:0] */
+#define WM8994_MIXINL_MIXOUTL_VOL_WIDTH 3 /* MIXINL_MIXOUTL_VOL - [2:0] */
+
+/*
+ * R50 (0x32) - Output Mixer (6)
+ */
+#define WM8994_DAC1R_MIXOUTR_VOL_MASK 0x0E00 /* DAC1R_MIXOUTR_VOL - [11:9] */
+#define WM8994_DAC1R_MIXOUTR_VOL_SHIFT 9 /* DAC1R_MIXOUTR_VOL - [11:9] */
+#define WM8994_DAC1R_MIXOUTR_VOL_WIDTH 3 /* DAC1R_MIXOUTR_VOL - [11:9] */
+#define WM8994_IN2LN_MIXOUTR_VOL_MASK 0x01C0 /* IN2LN_MIXOUTR_VOL - [8:6] */
+#define WM8994_IN2LN_MIXOUTR_VOL_SHIFT 6 /* IN2LN_MIXOUTR_VOL - [8:6] */
+#define WM8994_IN2LN_MIXOUTR_VOL_WIDTH 3 /* IN2LN_MIXOUTR_VOL - [8:6] */
+#define WM8994_MIXINL_MIXOUTR_VOL_MASK 0x0038 /* MIXINL_MIXOUTR_VOL - [5:3] */
+#define WM8994_MIXINL_MIXOUTR_VOL_SHIFT 3 /* MIXINL_MIXOUTR_VOL - [5:3] */
+#define WM8994_MIXINL_MIXOUTR_VOL_WIDTH 3 /* MIXINL_MIXOUTR_VOL - [5:3] */
+#define WM8994_MIXINR_MIXOUTR_VOL_MASK 0x0007 /* MIXINR_MIXOUTR_VOL - [2:0] */
+#define WM8994_MIXINR_MIXOUTR_VOL_SHIFT 0 /* MIXINR_MIXOUTR_VOL - [2:0] */
+#define WM8994_MIXINR_MIXOUTR_VOL_WIDTH 3 /* MIXINR_MIXOUTR_VOL - [2:0] */
+
+/*
+ * R51 (0x33) - HPOUT2 Mixer
+ */
+#define WM8994_IN2LRP_TO_HPOUT2 0x0020 /* IN2LRP_TO_HPOUT2 */
+#define WM8994_IN2LRP_TO_HPOUT2_MASK 0x0020 /* IN2LRP_TO_HPOUT2 */
+#define WM8994_IN2LRP_TO_HPOUT2_SHIFT 5 /* IN2LRP_TO_HPOUT2 */
+#define WM8994_IN2LRP_TO_HPOUT2_WIDTH 1 /* IN2LRP_TO_HPOUT2 */
+#define WM8994_MIXOUTLVOL_TO_HPOUT2 0x0010 /* MIXOUTLVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTLVOL_TO_HPOUT2_MASK 0x0010 /* MIXOUTLVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTLVOL_TO_HPOUT2_SHIFT 4 /* MIXOUTLVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTLVOL_TO_HPOUT2_WIDTH 1 /* MIXOUTLVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTRVOL_TO_HPOUT2 0x0008 /* MIXOUTRVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTRVOL_TO_HPOUT2_MASK 0x0008 /* MIXOUTRVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTRVOL_TO_HPOUT2_SHIFT 3 /* MIXOUTRVOL_TO_HPOUT2 */
+#define WM8994_MIXOUTRVOL_TO_HPOUT2_WIDTH 1 /* MIXOUTRVOL_TO_HPOUT2 */
+
+/*
+ * R52 (0x34) - Line Mixer (1)
+ */
+#define WM8994_MIXOUTL_TO_LINEOUT1N 0x0040 /* MIXOUTL_TO_LINEOUT1N */
+#define WM8994_MIXOUTL_TO_LINEOUT1N_MASK 0x0040 /* MIXOUTL_TO_LINEOUT1N */
+#define WM8994_MIXOUTL_TO_LINEOUT1N_SHIFT 6 /* MIXOUTL_TO_LINEOUT1N */
+#define WM8994_MIXOUTL_TO_LINEOUT1N_WIDTH 1 /* MIXOUTL_TO_LINEOUT1N */
+#define WM8994_MIXOUTR_TO_LINEOUT1N 0x0020 /* MIXOUTR_TO_LINEOUT1N */
+#define WM8994_MIXOUTR_TO_LINEOUT1N_MASK 0x0020 /* MIXOUTR_TO_LINEOUT1N */
+#define WM8994_MIXOUTR_TO_LINEOUT1N_SHIFT 5 /* MIXOUTR_TO_LINEOUT1N */
+#define WM8994_MIXOUTR_TO_LINEOUT1N_WIDTH 1 /* MIXOUTR_TO_LINEOUT1N */
+#define WM8994_LINEOUT1_MODE 0x0010 /* LINEOUT1_MODE */
+#define WM8994_LINEOUT1_MODE_MASK 0x0010 /* LINEOUT1_MODE */
+#define WM8994_LINEOUT1_MODE_SHIFT 4 /* LINEOUT1_MODE */
+#define WM8994_LINEOUT1_MODE_WIDTH 1 /* LINEOUT1_MODE */
+#define WM8994_IN1R_TO_LINEOUT1P 0x0004 /* IN1R_TO_LINEOUT1P */
+#define WM8994_IN1R_TO_LINEOUT1P_MASK 0x0004 /* IN1R_TO_LINEOUT1P */
+#define WM8994_IN1R_TO_LINEOUT1P_SHIFT 2 /* IN1R_TO_LINEOUT1P */
+#define WM8994_IN1R_TO_LINEOUT1P_WIDTH 1 /* IN1R_TO_LINEOUT1P */
+#define WM8994_IN1L_TO_LINEOUT1P 0x0002 /* IN1L_TO_LINEOUT1P */
+#define WM8994_IN1L_TO_LINEOUT1P_MASK 0x0002 /* IN1L_TO_LINEOUT1P */
+#define WM8994_IN1L_TO_LINEOUT1P_SHIFT 1 /* IN1L_TO_LINEOUT1P */
+#define WM8994_IN1L_TO_LINEOUT1P_WIDTH 1 /* IN1L_TO_LINEOUT1P */
+#define WM8994_MIXOUTL_TO_LINEOUT1P 0x0001 /* MIXOUTL_TO_LINEOUT1P */
+#define WM8994_MIXOUTL_TO_LINEOUT1P_MASK 0x0001 /* MIXOUTL_TO_LINEOUT1P */
+#define WM8994_MIXOUTL_TO_LINEOUT1P_SHIFT 0 /* MIXOUTL_TO_LINEOUT1P */
+#define WM8994_MIXOUTL_TO_LINEOUT1P_WIDTH 1 /* MIXOUTL_TO_LINEOUT1P */
+
+/*
+ * R53 (0x35) - Line Mixer (2)
+ */
+#define WM8994_MIXOUTR_TO_LINEOUT2N 0x0040 /* MIXOUTR_TO_LINEOUT2N */
+#define WM8994_MIXOUTR_TO_LINEOUT2N_MASK 0x0040 /* MIXOUTR_TO_LINEOUT2N */
+#define WM8994_MIXOUTR_TO_LINEOUT2N_SHIFT 6 /* MIXOUTR_TO_LINEOUT2N */
+#define WM8994_MIXOUTR_TO_LINEOUT2N_WIDTH 1 /* MIXOUTR_TO_LINEOUT2N */
+#define WM8994_MIXOUTL_TO_LINEOUT2N 0x0020 /* MIXOUTL_TO_LINEOUT2N */
+#define WM8994_MIXOUTL_TO_LINEOUT2N_MASK 0x0020 /* MIXOUTL_TO_LINEOUT2N */
+#define WM8994_MIXOUTL_TO_LINEOUT2N_SHIFT 5 /* MIXOUTL_TO_LINEOUT2N */
+#define WM8994_MIXOUTL_TO_LINEOUT2N_WIDTH 1 /* MIXOUTL_TO_LINEOUT2N */
+#define WM8994_LINEOUT2_MODE 0x0010 /* LINEOUT2_MODE */
+#define WM8994_LINEOUT2_MODE_MASK 0x0010 /* LINEOUT2_MODE */
+#define WM8994_LINEOUT2_MODE_SHIFT 4 /* LINEOUT2_MODE */
+#define WM8994_LINEOUT2_MODE_WIDTH 1 /* LINEOUT2_MODE */
+#define WM8994_IN1L_TO_LINEOUT2P 0x0004 /* IN1L_TO_LINEOUT2P */
+#define WM8994_IN1L_TO_LINEOUT2P_MASK 0x0004 /* IN1L_TO_LINEOUT2P */
+#define WM8994_IN1L_TO_LINEOUT2P_SHIFT 2 /* IN1L_TO_LINEOUT2P */
+#define WM8994_IN1L_TO_LINEOUT2P_WIDTH 1 /* IN1L_TO_LINEOUT2P */
+#define WM8994_IN1R_TO_LINEOUT2P 0x0002 /* IN1R_TO_LINEOUT2P */
+#define WM8994_IN1R_TO_LINEOUT2P_MASK 0x0002 /* IN1R_TO_LINEOUT2P */
+#define WM8994_IN1R_TO_LINEOUT2P_SHIFT 1 /* IN1R_TO_LINEOUT2P */
+#define WM8994_IN1R_TO_LINEOUT2P_WIDTH 1 /* IN1R_TO_LINEOUT2P */
+#define WM8994_MIXOUTR_TO_LINEOUT2P 0x0001 /* MIXOUTR_TO_LINEOUT2P */
+#define WM8994_MIXOUTR_TO_LINEOUT2P_MASK 0x0001 /* MIXOUTR_TO_LINEOUT2P */
+#define WM8994_MIXOUTR_TO_LINEOUT2P_SHIFT 0 /* MIXOUTR_TO_LINEOUT2P */
+#define WM8994_MIXOUTR_TO_LINEOUT2P_WIDTH 1 /* MIXOUTR_TO_LINEOUT2P */
+
+/*
+ * R54 (0x36) - Speaker Mixer
+ */
+#define WM8994_DAC2L_TO_SPKMIXL 0x0200 /* DAC2L_TO_SPKMIXL */
+#define WM8994_DAC2L_TO_SPKMIXL_MASK 0x0200 /* DAC2L_TO_SPKMIXL */
+#define WM8994_DAC2L_TO_SPKMIXL_SHIFT 9 /* DAC2L_TO_SPKMIXL */
+#define WM8994_DAC2L_TO_SPKMIXL_WIDTH 1 /* DAC2L_TO_SPKMIXL */
+#define WM8994_DAC2R_TO_SPKMIXR 0x0100 /* DAC2R_TO_SPKMIXR */
+#define WM8994_DAC2R_TO_SPKMIXR_MASK 0x0100 /* DAC2R_TO_SPKMIXR */
+#define WM8994_DAC2R_TO_SPKMIXR_SHIFT 8 /* DAC2R_TO_SPKMIXR */
+#define WM8994_DAC2R_TO_SPKMIXR_WIDTH 1 /* DAC2R_TO_SPKMIXR */
+#define WM8994_MIXINL_TO_SPKMIXL 0x0080 /* MIXINL_TO_SPKMIXL */
+#define WM8994_MIXINL_TO_SPKMIXL_MASK 0x0080 /* MIXINL_TO_SPKMIXL */
+#define WM8994_MIXINL_TO_SPKMIXL_SHIFT 7 /* MIXINL_TO_SPKMIXL */
+#define WM8994_MIXINL_TO_SPKMIXL_WIDTH 1 /* MIXINL_TO_SPKMIXL */
+#define WM8994_MIXINR_TO_SPKMIXR 0x0040 /* MIXINR_TO_SPKMIXR */
+#define WM8994_MIXINR_TO_SPKMIXR_MASK 0x0040 /* MIXINR_TO_SPKMIXR */
+#define WM8994_MIXINR_TO_SPKMIXR_SHIFT 6 /* MIXINR_TO_SPKMIXR */
+#define WM8994_MIXINR_TO_SPKMIXR_WIDTH 1 /* MIXINR_TO_SPKMIXR */
+#define WM8994_IN1LP_TO_SPKMIXL 0x0020 /* IN1LP_TO_SPKMIXL */
+#define WM8994_IN1LP_TO_SPKMIXL_MASK 0x0020 /* IN1LP_TO_SPKMIXL */
+#define WM8994_IN1LP_TO_SPKMIXL_SHIFT 5 /* IN1LP_TO_SPKMIXL */
+#define WM8994_IN1LP_TO_SPKMIXL_WIDTH 1 /* IN1LP_TO_SPKMIXL */
+#define WM8994_IN1RP_TO_SPKMIXR 0x0010 /* IN1RP_TO_SPKMIXR */
+#define WM8994_IN1RP_TO_SPKMIXR_MASK 0x0010 /* IN1RP_TO_SPKMIXR */
+#define WM8994_IN1RP_TO_SPKMIXR_SHIFT 4 /* IN1RP_TO_SPKMIXR */
+#define WM8994_IN1RP_TO_SPKMIXR_WIDTH 1 /* IN1RP_TO_SPKMIXR */
+#define WM8994_MIXOUTL_TO_SPKMIXL 0x0008 /* MIXOUTL_TO_SPKMIXL */
+#define WM8994_MIXOUTL_TO_SPKMIXL_MASK 0x0008 /* MIXOUTL_TO_SPKMIXL */
+#define WM8994_MIXOUTL_TO_SPKMIXL_SHIFT 3 /* MIXOUTL_TO_SPKMIXL */
+#define WM8994_MIXOUTL_TO_SPKMIXL_WIDTH 1 /* MIXOUTL_TO_SPKMIXL */
+#define WM8994_MIXOUTR_TO_SPKMIXR 0x0004 /* MIXOUTR_TO_SPKMIXR */
+#define WM8994_MIXOUTR_TO_SPKMIXR_MASK 0x0004 /* MIXOUTR_TO_SPKMIXR */
+#define WM8994_MIXOUTR_TO_SPKMIXR_SHIFT 2 /* MIXOUTR_TO_SPKMIXR */
+#define WM8994_MIXOUTR_TO_SPKMIXR_WIDTH 1 /* MIXOUTR_TO_SPKMIXR */
+#define WM8994_DAC1L_TO_SPKMIXL 0x0002 /* DAC1L_TO_SPKMIXL */
+#define WM8994_DAC1L_TO_SPKMIXL_MASK 0x0002 /* DAC1L_TO_SPKMIXL */
+#define WM8994_DAC1L_TO_SPKMIXL_SHIFT 1 /* DAC1L_TO_SPKMIXL */
+#define WM8994_DAC1L_TO_SPKMIXL_WIDTH 1 /* DAC1L_TO_SPKMIXL */
+#define WM8994_DAC1R_TO_SPKMIXR 0x0001 /* DAC1R_TO_SPKMIXR */
+#define WM8994_DAC1R_TO_SPKMIXR_MASK 0x0001 /* DAC1R_TO_SPKMIXR */
+#define WM8994_DAC1R_TO_SPKMIXR_SHIFT 0 /* DAC1R_TO_SPKMIXR */
+#define WM8994_DAC1R_TO_SPKMIXR_WIDTH 1 /* DAC1R_TO_SPKMIXR */
+
+/*
+ * R55 (0x37) - Additional Control
+ */
+#define WM8994_LINEOUT1_FB 0x0080 /* LINEOUT1_FB */
+#define WM8994_LINEOUT1_FB_MASK 0x0080 /* LINEOUT1_FB */
+#define WM8994_LINEOUT1_FB_SHIFT 7 /* LINEOUT1_FB */
+#define WM8994_LINEOUT1_FB_WIDTH 1 /* LINEOUT1_FB */
+#define WM8994_LINEOUT2_FB 0x0040 /* LINEOUT2_FB */
+#define WM8994_LINEOUT2_FB_MASK 0x0040 /* LINEOUT2_FB */
+#define WM8994_LINEOUT2_FB_SHIFT 6 /* LINEOUT2_FB */
+#define WM8994_LINEOUT2_FB_WIDTH 1 /* LINEOUT2_FB */
+#define WM8994_VROI 0x0001 /* VROI */
+#define WM8994_VROI_MASK 0x0001 /* VROI */
+#define WM8994_VROI_SHIFT 0 /* VROI */
+#define WM8994_VROI_WIDTH 1 /* VROI */
+
+/*
+ * R56 (0x38) - AntiPOP (1)
+ */
+#define WM8994_LINEOUT_VMID_BUF_ENA 0x0080 /* LINEOUT_VMID_BUF_ENA */
+#define WM8994_LINEOUT_VMID_BUF_ENA_MASK 0x0080 /* LINEOUT_VMID_BUF_ENA */
+#define WM8994_LINEOUT_VMID_BUF_ENA_SHIFT 7 /* LINEOUT_VMID_BUF_ENA */
+#define WM8994_LINEOUT_VMID_BUF_ENA_WIDTH 1 /* LINEOUT_VMID_BUF_ENA */
+#define WM8994_HPOUT2_IN_ENA 0x0040 /* HPOUT2_IN_ENA */
+#define WM8994_HPOUT2_IN_ENA_MASK 0x0040 /* HPOUT2_IN_ENA */
+#define WM8994_HPOUT2_IN_ENA_SHIFT 6 /* HPOUT2_IN_ENA */
+#define WM8994_HPOUT2_IN_ENA_WIDTH 1 /* HPOUT2_IN_ENA */
+#define WM8994_LINEOUT1_DISCH 0x0020 /* LINEOUT1_DISCH */
+#define WM8994_LINEOUT1_DISCH_MASK 0x0020 /* LINEOUT1_DISCH */
+#define WM8994_LINEOUT1_DISCH_SHIFT 5 /* LINEOUT1_DISCH */
+#define WM8994_LINEOUT1_DISCH_WIDTH 1 /* LINEOUT1_DISCH */
+#define WM8994_LINEOUT2_DISCH 0x0010 /* LINEOUT2_DISCH */
+#define WM8994_LINEOUT2_DISCH_MASK 0x0010 /* LINEOUT2_DISCH */
+#define WM8994_LINEOUT2_DISCH_SHIFT 4 /* LINEOUT2_DISCH */
+#define WM8994_LINEOUT2_DISCH_WIDTH 1 /* LINEOUT2_DISCH */
+
+/*
+ * R57 (0x39) - AntiPOP (2)
+ */
+#define WM8994_MICB2_DISCH 0x0100 /* MICB2_DISCH */
+#define WM8994_MICB2_DISCH_MASK 0x0100 /* MICB2_DISCH */
+#define WM8994_MICB2_DISCH_SHIFT 8 /* MICB2_DISCH */
+#define WM8994_MICB2_DISCH_WIDTH 1 /* MICB2_DISCH */
+#define WM8994_MICB1_DISCH 0x0080 /* MICB1_DISCH */
+#define WM8994_MICB1_DISCH_MASK 0x0080 /* MICB1_DISCH */
+#define WM8994_MICB1_DISCH_SHIFT 7 /* MICB1_DISCH */
+#define WM8994_MICB1_DISCH_WIDTH 1 /* MICB1_DISCH */
+#define WM8994_VMID_RAMP_MASK 0x0060 /* VMID_RAMP - [6:5] */
+#define WM8994_VMID_RAMP_SHIFT 5 /* VMID_RAMP - [6:5] */
+#define WM8994_VMID_RAMP_WIDTH 2 /* VMID_RAMP - [6:5] */
+#define WM8994_VMID_BUF_ENA 0x0008 /* VMID_BUF_ENA */
+#define WM8994_VMID_BUF_ENA_MASK 0x0008 /* VMID_BUF_ENA */
+#define WM8994_VMID_BUF_ENA_SHIFT 3 /* VMID_BUF_ENA */
+#define WM8994_VMID_BUF_ENA_WIDTH 1 /* VMID_BUF_ENA */
+#define WM8994_STARTUP_BIAS_ENA 0x0004 /* STARTUP_BIAS_ENA */
+#define WM8994_STARTUP_BIAS_ENA_MASK 0x0004 /* STARTUP_BIAS_ENA */
+#define WM8994_STARTUP_BIAS_ENA_SHIFT 2 /* STARTUP_BIAS_ENA */
+#define WM8994_STARTUP_BIAS_ENA_WIDTH 1 /* STARTUP_BIAS_ENA */
+#define WM8994_BIAS_SRC 0x0002 /* BIAS_SRC */
+#define WM8994_BIAS_SRC_MASK 0x0002 /* BIAS_SRC */
+#define WM8994_BIAS_SRC_SHIFT 1 /* BIAS_SRC */
+#define WM8994_BIAS_SRC_WIDTH 1 /* BIAS_SRC */
+#define WM8994_VMID_DISCH 0x0001 /* VMID_DISCH */
+#define WM8994_VMID_DISCH_MASK 0x0001 /* VMID_DISCH */
+#define WM8994_VMID_DISCH_SHIFT 0 /* VMID_DISCH */
+#define WM8994_VMID_DISCH_WIDTH 1 /* VMID_DISCH */
+
+/*
+ * R58 (0x3A) - MICBIAS
+ */
+#define WM8994_MICD_SCTHR_MASK 0x00C0 /* MICD_SCTHR - [7:6] */
+#define WM8994_MICD_SCTHR_SHIFT 6 /* MICD_SCTHR - [7:6] */
+#define WM8994_MICD_SCTHR_WIDTH 2 /* MICD_SCTHR - [7:6] */
+#define WM8994_MICD_THR_MASK 0x0038 /* MICD_THR - [5:3] */
+#define WM8994_MICD_THR_SHIFT 3 /* MICD_THR - [5:3] */
+#define WM8994_MICD_THR_WIDTH 3 /* MICD_THR - [5:3] */
+#define WM8994_MICD_ENA 0x0004 /* MICD_ENA */
+#define WM8994_MICD_ENA_MASK 0x0004 /* MICD_ENA */
+#define WM8994_MICD_ENA_SHIFT 2 /* MICD_ENA */
+#define WM8994_MICD_ENA_WIDTH 1 /* MICD_ENA */
+#define WM8994_MICB2_LVL 0x0002 /* MICB2_LVL */
+#define WM8994_MICB2_LVL_MASK 0x0002 /* MICB2_LVL */
+#define WM8994_MICB2_LVL_SHIFT 1 /* MICB2_LVL */
+#define WM8994_MICB2_LVL_WIDTH 1 /* MICB2_LVL */
+#define WM8994_MICB1_LVL 0x0001 /* MICB1_LVL */
+#define WM8994_MICB1_LVL_MASK 0x0001 /* MICB1_LVL */
+#define WM8994_MICB1_LVL_SHIFT 0 /* MICB1_LVL */
+#define WM8994_MICB1_LVL_WIDTH 1 /* MICB1_LVL */
+
+/*
+ * R59 (0x3B) - LDO 1
+ */
+#define WM8994_LDO1_VSEL_MASK 0x000E /* LDO1_VSEL - [3:1] */
+#define WM8994_LDO1_VSEL_SHIFT 1 /* LDO1_VSEL - [3:1] */
+#define WM8994_LDO1_VSEL_WIDTH 3 /* LDO1_VSEL - [3:1] */
+#define WM8994_LDO1_DISCH 0x0001 /* LDO1_DISCH */
+#define WM8994_LDO1_DISCH_MASK 0x0001 /* LDO1_DISCH */
+#define WM8994_LDO1_DISCH_SHIFT 0 /* LDO1_DISCH */
+#define WM8994_LDO1_DISCH_WIDTH 1 /* LDO1_DISCH */
+
+/*
+ * R60 (0x3C) - LDO 2
+ */
+#define WM8994_LDO2_VSEL_MASK 0x0006 /* LDO2_VSEL - [2:1] */
+#define WM8994_LDO2_VSEL_SHIFT 1 /* LDO2_VSEL - [2:1] */
+#define WM8994_LDO2_VSEL_WIDTH 2 /* LDO2_VSEL - [2:1] */
+#define WM8994_LDO2_DISCH 0x0001 /* LDO2_DISCH */
+#define WM8994_LDO2_DISCH_MASK 0x0001 /* LDO2_DISCH */
+#define WM8994_LDO2_DISCH_SHIFT 0 /* LDO2_DISCH */
+#define WM8994_LDO2_DISCH_WIDTH 1 /* LDO2_DISCH */
+
+/*
+ * R76 (0x4C) - Charge Pump (1)
+ */
+#define WM8994_CP_ENA 0x8000 /* CP_ENA */
+#define WM8994_CP_ENA_MASK 0x8000 /* CP_ENA */
+#define WM8994_CP_ENA_SHIFT 15 /* CP_ENA */
+#define WM8994_CP_ENA_WIDTH 1 /* CP_ENA */
+
+/*
+ * R81 (0x51) - Class W (1)
+ */
+#define WM8994_CP_DYN_SRC_SEL_MASK 0x0300 /* CP_DYN_SRC_SEL - [9:8] */
+#define WM8994_CP_DYN_SRC_SEL_SHIFT 8 /* CP_DYN_SRC_SEL - [9:8] */
+#define WM8994_CP_DYN_SRC_SEL_WIDTH 2 /* CP_DYN_SRC_SEL - [9:8] */
+#define WM8994_CP_DYN_PWR 0x0001 /* CP_DYN_PWR */
+#define WM8994_CP_DYN_PWR_MASK 0x0001 /* CP_DYN_PWR */
+#define WM8994_CP_DYN_PWR_SHIFT 0 /* CP_DYN_PWR */
+#define WM8994_CP_DYN_PWR_WIDTH 1 /* CP_DYN_PWR */
+
+/*
+ * R84 (0x54) - DC Servo (1)
+ */
+#define WM8994_DCS_TRIG_SINGLE_1 0x2000 /* DCS_TRIG_SINGLE_1 */
+#define WM8994_DCS_TRIG_SINGLE_1_MASK 0x2000 /* DCS_TRIG_SINGLE_1 */
+#define WM8994_DCS_TRIG_SINGLE_1_SHIFT 13 /* DCS_TRIG_SINGLE_1 */
+#define WM8994_DCS_TRIG_SINGLE_1_WIDTH 1 /* DCS_TRIG_SINGLE_1 */
+#define WM8994_DCS_TRIG_SINGLE_0 0x1000 /* DCS_TRIG_SINGLE_0 */
+#define WM8994_DCS_TRIG_SINGLE_0_MASK 0x1000 /* DCS_TRIG_SINGLE_0 */
+#define WM8994_DCS_TRIG_SINGLE_0_SHIFT 12 /* DCS_TRIG_SINGLE_0 */
+#define WM8994_DCS_TRIG_SINGLE_0_WIDTH 1 /* DCS_TRIG_SINGLE_0 */
+#define WM8994_DCS_TRIG_SERIES_1 0x0200 /* DCS_TRIG_SERIES_1 */
+#define WM8994_DCS_TRIG_SERIES_1_MASK 0x0200 /* DCS_TRIG_SERIES_1 */
+#define WM8994_DCS_TRIG_SERIES_1_SHIFT 9 /* DCS_TRIG_SERIES_1 */
+#define WM8994_DCS_TRIG_SERIES_1_WIDTH 1 /* DCS_TRIG_SERIES_1 */
+#define WM8994_DCS_TRIG_SERIES_0 0x0100 /* DCS_TRIG_SERIES_0 */
+#define WM8994_DCS_TRIG_SERIES_0_MASK 0x0100 /* DCS_TRIG_SERIES_0 */
+#define WM8994_DCS_TRIG_SERIES_0_SHIFT 8 /* DCS_TRIG_SERIES_0 */
+#define WM8994_DCS_TRIG_SERIES_0_WIDTH 1 /* DCS_TRIG_SERIES_0 */
+#define WM8994_DCS_TRIG_STARTUP_1 0x0020 /* DCS_TRIG_STARTUP_1 */
+#define WM8994_DCS_TRIG_STARTUP_1_MASK 0x0020 /* DCS_TRIG_STARTUP_1 */
+#define WM8994_DCS_TRIG_STARTUP_1_SHIFT 5 /* DCS_TRIG_STARTUP_1 */
+#define WM8994_DCS_TRIG_STARTUP_1_WIDTH 1 /* DCS_TRIG_STARTUP_1 */
+#define WM8994_DCS_TRIG_STARTUP_0 0x0010 /* DCS_TRIG_STARTUP_0 */
+#define WM8994_DCS_TRIG_STARTUP_0_MASK 0x0010 /* DCS_TRIG_STARTUP_0 */
+#define WM8994_DCS_TRIG_STARTUP_0_SHIFT 4 /* DCS_TRIG_STARTUP_0 */
+#define WM8994_DCS_TRIG_STARTUP_0_WIDTH 1 /* DCS_TRIG_STARTUP_0 */
+#define WM8994_DCS_TRIG_DAC_WR_1 0x0008 /* DCS_TRIG_DAC_WR_1 */
+#define WM8994_DCS_TRIG_DAC_WR_1_MASK 0x0008 /* DCS_TRIG_DAC_WR_1 */
+#define WM8994_DCS_TRIG_DAC_WR_1_SHIFT 3 /* DCS_TRIG_DAC_WR_1 */
+#define WM8994_DCS_TRIG_DAC_WR_1_WIDTH 1 /* DCS_TRIG_DAC_WR_1 */
+#define WM8994_DCS_TRIG_DAC_WR_0 0x0004 /* DCS_TRIG_DAC_WR_0 */
+#define WM8994_DCS_TRIG_DAC_WR_0_MASK 0x0004 /* DCS_TRIG_DAC_WR_0 */
+#define WM8994_DCS_TRIG_DAC_WR_0_SHIFT 2 /* DCS_TRIG_DAC_WR_0 */
+#define WM8994_DCS_TRIG_DAC_WR_0_WIDTH 1 /* DCS_TRIG_DAC_WR_0 */
+#define WM8994_DCS_ENA_CHAN_1 0x0002 /* DCS_ENA_CHAN_1 */
+#define WM8994_DCS_ENA_CHAN_1_MASK 0x0002 /* DCS_ENA_CHAN_1 */
+#define WM8994_DCS_ENA_CHAN_1_SHIFT 1 /* DCS_ENA_CHAN_1 */
+#define WM8994_DCS_ENA_CHAN_1_WIDTH 1 /* DCS_ENA_CHAN_1 */
+#define WM8994_DCS_ENA_CHAN_0 0x0001 /* DCS_ENA_CHAN_0 */
+#define WM8994_DCS_ENA_CHAN_0_MASK 0x0001 /* DCS_ENA_CHAN_0 */
+#define WM8994_DCS_ENA_CHAN_0_SHIFT 0 /* DCS_ENA_CHAN_0 */
+#define WM8994_DCS_ENA_CHAN_0_WIDTH 1 /* DCS_ENA_CHAN_0 */
+
+/*
+ * R85 (0x55) - DC Servo (2)
+ */
+#define WM8994_DCS_SERIES_NO_01_MASK 0x0FE0 /* DCS_SERIES_NO_01 - [11:5] */
+#define WM8994_DCS_SERIES_NO_01_SHIFT 5 /* DCS_SERIES_NO_01 - [11:5] */
+#define WM8994_DCS_SERIES_NO_01_WIDTH 7 /* DCS_SERIES_NO_01 - [11:5] */
+#define WM8994_DCS_TIMER_PERIOD_01_MASK 0x000F /* DCS_TIMER_PERIOD_01 - [3:0] */
+#define WM8994_DCS_TIMER_PERIOD_01_SHIFT 0 /* DCS_TIMER_PERIOD_01 - [3:0] */
+#define WM8994_DCS_TIMER_PERIOD_01_WIDTH 4 /* DCS_TIMER_PERIOD_01 - [3:0] */
+
+/*
+ * R87 (0x57) - DC Servo (4)
+ */
+#define WM8994_DCS_DAC_WR_VAL_1_MASK 0xFF00 /* DCS_DAC_WR_VAL_1 - [15:8] */
+#define WM8994_DCS_DAC_WR_VAL_1_SHIFT 8 /* DCS_DAC_WR_VAL_1 - [15:8] */
+#define WM8994_DCS_DAC_WR_VAL_1_WIDTH 8 /* DCS_DAC_WR_VAL_1 - [15:8] */
+#define WM8994_DCS_DAC_WR_VAL_0_MASK 0x00FF /* DCS_DAC_WR_VAL_0 - [7:0] */
+#define WM8994_DCS_DAC_WR_VAL_0_SHIFT 0 /* DCS_DAC_WR_VAL_0 - [7:0] */
+#define WM8994_DCS_DAC_WR_VAL_0_WIDTH 8 /* DCS_DAC_WR_VAL_0 - [7:0] */
+
+/*
+ * R88 (0x58) - DC Servo Readback
+ */
+#define WM8994_DCS_CAL_COMPLETE_MASK 0x0300 /* DCS_CAL_COMPLETE - [9:8] */
+#define WM8994_DCS_CAL_COMPLETE_SHIFT 8 /* DCS_CAL_COMPLETE - [9:8] */
+#define WM8994_DCS_CAL_COMPLETE_WIDTH 2 /* DCS_CAL_COMPLETE - [9:8] */
+#define WM8994_DCS_DAC_WR_COMPLETE_MASK 0x0030 /* DCS_DAC_WR_COMPLETE - [5:4] */
+#define WM8994_DCS_DAC_WR_COMPLETE_SHIFT 4 /* DCS_DAC_WR_COMPLETE - [5:4] */
+#define WM8994_DCS_DAC_WR_COMPLETE_WIDTH 2 /* DCS_DAC_WR_COMPLETE - [5:4] */
+#define WM8994_DCS_STARTUP_COMPLETE_MASK 0x0003 /* DCS_STARTUP_COMPLETE - [1:0] */
+#define WM8994_DCS_STARTUP_COMPLETE_SHIFT 0 /* DCS_STARTUP_COMPLETE - [1:0] */
+#define WM8994_DCS_STARTUP_COMPLETE_WIDTH 2 /* DCS_STARTUP_COMPLETE - [1:0] */
+
+/*
+ * R96 (0x60) - Analogue HP (1)
+ */
+#define WM8994_HPOUT1L_RMV_SHORT 0x0080 /* HPOUT1L_RMV_SHORT */
+#define WM8994_HPOUT1L_RMV_SHORT_MASK 0x0080 /* HPOUT1L_RMV_SHORT */
+#define WM8994_HPOUT1L_RMV_SHORT_SHIFT 7 /* HPOUT1L_RMV_SHORT */
+#define WM8994_HPOUT1L_RMV_SHORT_WIDTH 1 /* HPOUT1L_RMV_SHORT */
+#define WM8994_HPOUT1L_OUTP 0x0040 /* HPOUT1L_OUTP */
+#define WM8994_HPOUT1L_OUTP_MASK 0x0040 /* HPOUT1L_OUTP */
+#define WM8994_HPOUT1L_OUTP_SHIFT 6 /* HPOUT1L_OUTP */
+#define WM8994_HPOUT1L_OUTP_WIDTH 1 /* HPOUT1L_OUTP */
+#define WM8994_HPOUT1L_DLY 0x0020 /* HPOUT1L_DLY */
+#define WM8994_HPOUT1L_DLY_MASK 0x0020 /* HPOUT1L_DLY */
+#define WM8994_HPOUT1L_DLY_SHIFT 5 /* HPOUT1L_DLY */
+#define WM8994_HPOUT1L_DLY_WIDTH 1 /* HPOUT1L_DLY */
+#define WM8994_HPOUT1R_RMV_SHORT 0x0008 /* HPOUT1R_RMV_SHORT */
+#define WM8994_HPOUT1R_RMV_SHORT_MASK 0x0008 /* HPOUT1R_RMV_SHORT */
+#define WM8994_HPOUT1R_RMV_SHORT_SHIFT 3 /* HPOUT1R_RMV_SHORT */
+#define WM8994_HPOUT1R_RMV_SHORT_WIDTH 1 /* HPOUT1R_RMV_SHORT */
+#define WM8994_HPOUT1R_OUTP 0x0004 /* HPOUT1R_OUTP */
+#define WM8994_HPOUT1R_OUTP_MASK 0x0004 /* HPOUT1R_OUTP */
+#define WM8994_HPOUT1R_OUTP_SHIFT 2 /* HPOUT1R_OUTP */
+#define WM8994_HPOUT1R_OUTP_WIDTH 1 /* HPOUT1R_OUTP */
+#define WM8994_HPOUT1R_DLY 0x0002 /* HPOUT1R_DLY */
+#define WM8994_HPOUT1R_DLY_MASK 0x0002 /* HPOUT1R_DLY */
+#define WM8994_HPOUT1R_DLY_SHIFT 1 /* HPOUT1R_DLY */
+#define WM8994_HPOUT1R_DLY_WIDTH 1 /* HPOUT1R_DLY */
+
+/*
+ * R256 (0x100) - Chip Revision
+ */
+#define WM8994_CHIP_REV_MASK 0x000F /* CHIP_REV - [3:0] */
+#define WM8994_CHIP_REV_SHIFT 0 /* CHIP_REV - [3:0] */
+#define WM8994_CHIP_REV_WIDTH 4 /* CHIP_REV - [3:0] */
+
+/*
+ * R257 (0x101) - Control Interface
+ */
+#define WM8994_SPI_CONTRD 0x0040 /* SPI_CONTRD */
+#define WM8994_SPI_CONTRD_MASK 0x0040 /* SPI_CONTRD */
+#define WM8994_SPI_CONTRD_SHIFT 6 /* SPI_CONTRD */
+#define WM8994_SPI_CONTRD_WIDTH 1 /* SPI_CONTRD */
+#define WM8994_SPI_4WIRE 0x0020 /* SPI_4WIRE */
+#define WM8994_SPI_4WIRE_MASK 0x0020 /* SPI_4WIRE */
+#define WM8994_SPI_4WIRE_SHIFT 5 /* SPI_4WIRE */
+#define WM8994_SPI_4WIRE_WIDTH 1 /* SPI_4WIRE */
+#define WM8994_SPI_CFG 0x0010 /* SPI_CFG */
+#define WM8994_SPI_CFG_MASK 0x0010 /* SPI_CFG */
+#define WM8994_SPI_CFG_SHIFT 4 /* SPI_CFG */
+#define WM8994_SPI_CFG_WIDTH 1 /* SPI_CFG */
+#define WM8994_AUTO_INC 0x0004 /* AUTO_INC */
+#define WM8994_AUTO_INC_MASK 0x0004 /* AUTO_INC */
+#define WM8994_AUTO_INC_SHIFT 2 /* AUTO_INC */
+#define WM8994_AUTO_INC_WIDTH 1 /* AUTO_INC */
+
+/*
+ * R272 (0x110) - Write Sequencer Ctrl (1)
+ */
+#define WM8994_WSEQ_ENA 0x8000 /* WSEQ_ENA */
+#define WM8994_WSEQ_ENA_MASK 0x8000 /* WSEQ_ENA */
+#define WM8994_WSEQ_ENA_SHIFT 15 /* WSEQ_ENA */
+#define WM8994_WSEQ_ENA_WIDTH 1 /* WSEQ_ENA */
+#define WM8994_WSEQ_ABORT 0x0200 /* WSEQ_ABORT */
+#define WM8994_WSEQ_ABORT_MASK 0x0200 /* WSEQ_ABORT */
+#define WM8994_WSEQ_ABORT_SHIFT 9 /* WSEQ_ABORT */
+#define WM8994_WSEQ_ABORT_WIDTH 1 /* WSEQ_ABORT */
+#define WM8994_WSEQ_START 0x0100 /* WSEQ_START */
+#define WM8994_WSEQ_START_MASK 0x0100 /* WSEQ_START */
+#define WM8994_WSEQ_START_SHIFT 8 /* WSEQ_START */
+#define WM8994_WSEQ_START_WIDTH 1 /* WSEQ_START */
+#define WM8994_WSEQ_START_INDEX_MASK 0x007F /* WSEQ_START_INDEX - [6:0] */
+#define WM8994_WSEQ_START_INDEX_SHIFT 0 /* WSEQ_START_INDEX - [6:0] */
+#define WM8994_WSEQ_START_INDEX_WIDTH 7 /* WSEQ_START_INDEX - [6:0] */
+
+/*
+ * R273 (0x111) - Write Sequencer Ctrl (2)
+ */
+#define WM8994_WSEQ_BUSY 0x0100 /* WSEQ_BUSY */
+#define WM8994_WSEQ_BUSY_MASK 0x0100 /* WSEQ_BUSY */
+#define WM8994_WSEQ_BUSY_SHIFT 8 /* WSEQ_BUSY */
+#define WM8994_WSEQ_BUSY_WIDTH 1 /* WSEQ_BUSY */
+#define WM8994_WSEQ_CURRENT_INDEX_MASK 0x007F /* WSEQ_CURRENT_INDEX - [6:0] */
+#define WM8994_WSEQ_CURRENT_INDEX_SHIFT 0 /* WSEQ_CURRENT_INDEX - [6:0] */
+#define WM8994_WSEQ_CURRENT_INDEX_WIDTH 7 /* WSEQ_CURRENT_INDEX - [6:0] */
+
+/*
+ * R512 (0x200) - AIF1 Clocking (1)
+ */
+#define WM8994_AIF1CLK_SRC_MASK 0x0018 /* AIF1CLK_SRC - [4:3] */
+#define WM8994_AIF1CLK_SRC_SHIFT 3 /* AIF1CLK_SRC - [4:3] */
+#define WM8994_AIF1CLK_SRC_WIDTH 2 /* AIF1CLK_SRC - [4:3] */
+#define WM8994_AIF1CLK_INV 0x0004 /* AIF1CLK_INV */
+#define WM8994_AIF1CLK_INV_MASK 0x0004 /* AIF1CLK_INV */
+#define WM8994_AIF1CLK_INV_SHIFT 2 /* AIF1CLK_INV */
+#define WM8994_AIF1CLK_INV_WIDTH 1 /* AIF1CLK_INV */
+#define WM8994_AIF1CLK_DIV 0x0002 /* AIF1CLK_DIV */
+#define WM8994_AIF1CLK_DIV_MASK 0x0002 /* AIF1CLK_DIV */
+#define WM8994_AIF1CLK_DIV_SHIFT 1 /* AIF1CLK_DIV */
+#define WM8994_AIF1CLK_DIV_WIDTH 1 /* AIF1CLK_DIV */
+#define WM8994_AIF1CLK_ENA 0x0001 /* AIF1CLK_ENA */
+#define WM8994_AIF1CLK_ENA_MASK 0x0001 /* AIF1CLK_ENA */
+#define WM8994_AIF1CLK_ENA_SHIFT 0 /* AIF1CLK_ENA */
+#define WM8994_AIF1CLK_ENA_WIDTH 1 /* AIF1CLK_ENA */
+
+/*
+ * R513 (0x201) - AIF1 Clocking (2)
+ */
+#define WM8994_AIF1DAC_DIV_MASK 0x0038 /* AIF1DAC_DIV - [5:3] */
+#define WM8994_AIF1DAC_DIV_SHIFT 3 /* AIF1DAC_DIV - [5:3] */
+#define WM8994_AIF1DAC_DIV_WIDTH 3 /* AIF1DAC_DIV - [5:3] */
+#define WM8994_AIF1ADC_DIV_MASK 0x0007 /* AIF1ADC_DIV - [2:0] */
+#define WM8994_AIF1ADC_DIV_SHIFT 0 /* AIF1ADC_DIV - [2:0] */
+#define WM8994_AIF1ADC_DIV_WIDTH 3 /* AIF1ADC_DIV - [2:0] */
+
+/*
+ * R516 (0x204) - AIF2 Clocking (1)
+ */
+#define WM8994_AIF2CLK_SRC_MASK 0x0018 /* AIF2CLK_SRC - [4:3] */
+#define WM8994_AIF2CLK_SRC_SHIFT 3 /* AIF2CLK_SRC - [4:3] */
+#define WM8994_AIF2CLK_SRC_WIDTH 2 /* AIF2CLK_SRC - [4:3] */
+#define WM8994_AIF2CLK_INV 0x0004 /* AIF2CLK_INV */
+#define WM8994_AIF2CLK_INV_MASK 0x0004 /* AIF2CLK_INV */
+#define WM8994_AIF2CLK_INV_SHIFT 2 /* AIF2CLK_INV */
+#define WM8994_AIF2CLK_INV_WIDTH 1 /* AIF2CLK_INV */
+#define WM8994_AIF2CLK_DIV 0x0002 /* AIF2CLK_DIV */
+#define WM8994_AIF2CLK_DIV_MASK 0x0002 /* AIF2CLK_DIV */
+#define WM8994_AIF2CLK_DIV_SHIFT 1 /* AIF2CLK_DIV */
+#define WM8994_AIF2CLK_DIV_WIDTH 1 /* AIF2CLK_DIV */
+#define WM8994_AIF2CLK_ENA 0x0001 /* AIF2CLK_ENA */
+#define WM8994_AIF2CLK_ENA_MASK 0x0001 /* AIF2CLK_ENA */
+#define WM8994_AIF2CLK_ENA_SHIFT 0 /* AIF2CLK_ENA */
+#define WM8994_AIF2CLK_ENA_WIDTH 1 /* AIF2CLK_ENA */
+
+/*
+ * R517 (0x205) - AIF2 Clocking (2)
+ */
+#define WM8994_AIF2DAC_DIV_MASK 0x0038 /* AIF2DAC_DIV - [5:3] */
+#define WM8994_AIF2DAC_DIV_SHIFT 3 /* AIF2DAC_DIV - [5:3] */
+#define WM8994_AIF2DAC_DIV_WIDTH 3 /* AIF2DAC_DIV - [5:3] */
+#define WM8994_AIF2ADC_DIV_MASK 0x0007 /* AIF2ADC_DIV - [2:0] */
+#define WM8994_AIF2ADC_DIV_SHIFT 0 /* AIF2ADC_DIV - [2:0] */
+#define WM8994_AIF2ADC_DIV_WIDTH 3 /* AIF2ADC_DIV - [2:0] */
+
+/*
+ * R520 (0x208) - Clocking (1)
+ */
+#define WM8994_TOCLK_ENA 0x0010 /* TOCLK_ENA */
+#define WM8994_TOCLK_ENA_MASK 0x0010 /* TOCLK_ENA */
+#define WM8994_TOCLK_ENA_SHIFT 4 /* TOCLK_ENA */
+#define WM8994_TOCLK_ENA_WIDTH 1 /* TOCLK_ENA */
+#define WM8994_AIF1DSPCLK_ENA 0x0008 /* AIF1DSPCLK_ENA */
+#define WM8994_AIF1DSPCLK_ENA_MASK 0x0008 /* AIF1DSPCLK_ENA */
+#define WM8994_AIF1DSPCLK_ENA_SHIFT 3 /* AIF1DSPCLK_ENA */
+#define WM8994_AIF1DSPCLK_ENA_WIDTH 1 /* AIF1DSPCLK_ENA */
+#define WM8994_AIF2DSPCLK_ENA 0x0004 /* AIF2DSPCLK_ENA */
+#define WM8994_AIF2DSPCLK_ENA_MASK 0x0004 /* AIF2DSPCLK_ENA */
+#define WM8994_AIF2DSPCLK_ENA_SHIFT 2 /* AIF2DSPCLK_ENA */
+#define WM8994_AIF2DSPCLK_ENA_WIDTH 1 /* AIF2DSPCLK_ENA */
+#define WM8994_SYSDSPCLK_ENA 0x0002 /* SYSDSPCLK_ENA */
+#define WM8994_SYSDSPCLK_ENA_MASK 0x0002 /* SYSDSPCLK_ENA */
+#define WM8994_SYSDSPCLK_ENA_SHIFT 1 /* SYSDSPCLK_ENA */
+#define WM8994_SYSDSPCLK_ENA_WIDTH 1 /* SYSDSPCLK_ENA */
+#define WM8994_SYSCLK_SRC 0x0001 /* SYSCLK_SRC */
+#define WM8994_SYSCLK_SRC_MASK 0x0001 /* SYSCLK_SRC */
+#define WM8994_SYSCLK_SRC_SHIFT 0 /* SYSCLK_SRC */
+#define WM8994_SYSCLK_SRC_WIDTH 1 /* SYSCLK_SRC */
+
+/*
+ * R521 (0x209) - Clocking (2)
+ */
+#define WM8994_TOCLK_DIV_MASK 0x0700 /* TOCLK_DIV - [10:8] */
+#define WM8994_TOCLK_DIV_SHIFT 8 /* TOCLK_DIV - [10:8] */
+#define WM8994_TOCLK_DIV_WIDTH 3 /* TOCLK_DIV - [10:8] */
+#define WM8994_DBCLK_DIV_MASK 0x0070 /* DBCLK_DIV - [6:4] */
+#define WM8994_DBCLK_DIV_SHIFT 4 /* DBCLK_DIV - [6:4] */
+#define WM8994_DBCLK_DIV_WIDTH 3 /* DBCLK_DIV - [6:4] */
+#define WM8994_OPCLK_DIV_MASK 0x0007 /* OPCLK_DIV - [2:0] */
+#define WM8994_OPCLK_DIV_SHIFT 0 /* OPCLK_DIV - [2:0] */
+#define WM8994_OPCLK_DIV_WIDTH 3 /* OPCLK_DIV - [2:0] */
+
+/*
+ * R528 (0x210) - AIF1 Rate
+ */
+#define WM8994_AIF1_SR_MASK 0x00F0 /* AIF1_SR - [7:4] */
+#define WM8994_AIF1_SR_SHIFT 4 /* AIF1_SR - [7:4] */
+#define WM8994_AIF1_SR_WIDTH 4 /* AIF1_SR - [7:4] */
+#define WM8994_AIF1CLK_RATE_MASK 0x000F /* AIF1CLK_RATE - [3:0] */
+#define WM8994_AIF1CLK_RATE_SHIFT 0 /* AIF1CLK_RATE - [3:0] */
+#define WM8994_AIF1CLK_RATE_WIDTH 4 /* AIF1CLK_RATE - [3:0] */
+
+/*
+ * R529 (0x211) - AIF2 Rate
+ */
+#define WM8994_AIF2_SR_MASK 0x00F0 /* AIF2_SR - [7:4] */
+#define WM8994_AIF2_SR_SHIFT 4 /* AIF2_SR - [7:4] */
+#define WM8994_AIF2_SR_WIDTH 4 /* AIF2_SR - [7:4] */
+#define WM8994_AIF2CLK_RATE_MASK 0x000F /* AIF2CLK_RATE - [3:0] */
+#define WM8994_AIF2CLK_RATE_SHIFT 0 /* AIF2CLK_RATE - [3:0] */
+#define WM8994_AIF2CLK_RATE_WIDTH 4 /* AIF2CLK_RATE - [3:0] */
+
+/*
+ * R530 (0x212) - Rate Status
+ */
+#define WM8994_SR_ERROR_MASK 0x000F /* SR_ERROR - [3:0] */
+#define WM8994_SR_ERROR_SHIFT 0 /* SR_ERROR - [3:0] */
+#define WM8994_SR_ERROR_WIDTH 4 /* SR_ERROR - [3:0] */
+
+/*
+ * R544 (0x220) - FLL1 Control (1)
+ */
+#define WM8994_FLL1_FRAC 0x0004 /* FLL1_FRAC */
+#define WM8994_FLL1_FRAC_MASK 0x0004 /* FLL1_FRAC */
+#define WM8994_FLL1_FRAC_SHIFT 2 /* FLL1_FRAC */
+#define WM8994_FLL1_FRAC_WIDTH 1 /* FLL1_FRAC */
+#define WM8994_FLL1_OSC_ENA 0x0002 /* FLL1_OSC_ENA */
+#define WM8994_FLL1_OSC_ENA_MASK 0x0002 /* FLL1_OSC_ENA */
+#define WM8994_FLL1_OSC_ENA_SHIFT 1 /* FLL1_OSC_ENA */
+#define WM8994_FLL1_OSC_ENA_WIDTH 1 /* FLL1_OSC_ENA */
+#define WM8994_FLL1_ENA 0x0001 /* FLL1_ENA */
+#define WM8994_FLL1_ENA_MASK 0x0001 /* FLL1_ENA */
+#define WM8994_FLL1_ENA_SHIFT 0 /* FLL1_ENA */
+#define WM8994_FLL1_ENA_WIDTH 1 /* FLL1_ENA */
+
+/*
+ * R545 (0x221) - FLL1 Control (2)
+ */
+#define WM8994_FLL1_OUTDIV_MASK 0x3F00 /* FLL1_OUTDIV - [13:8] */
+#define WM8994_FLL1_OUTDIV_SHIFT 8 /* FLL1_OUTDIV - [13:8] */
+#define WM8994_FLL1_OUTDIV_WIDTH 6 /* FLL1_OUTDIV - [13:8] */
+#define WM8994_FLL1_CTRL_RATE_MASK 0x0070 /* FLL1_CTRL_RATE - [6:4] */
+#define WM8994_FLL1_CTRL_RATE_SHIFT 4 /* FLL1_CTRL_RATE - [6:4] */
+#define WM8994_FLL1_CTRL_RATE_WIDTH 3 /* FLL1_CTRL_RATE - [6:4] */
+#define WM8994_FLL1_FRATIO_MASK 0x0007 /* FLL1_FRATIO - [2:0] */
+#define WM8994_FLL1_FRATIO_SHIFT 0 /* FLL1_FRATIO - [2:0] */
+#define WM8994_FLL1_FRATIO_WIDTH 3 /* FLL1_FRATIO - [2:0] */
+
+/*
+ * R546 (0x222) - FLL1 Control (3)
+ */
+#define WM8994_FLL1_K_MASK 0xFFFF /* FLL1_K - [15:0] */
+#define WM8994_FLL1_K_SHIFT 0 /* FLL1_K - [15:0] */
+#define WM8994_FLL1_K_WIDTH 16 /* FLL1_K - [15:0] */
+
+/*
+ * R547 (0x223) - FLL1 Control (4)
+ */
+#define WM8994_FLL1_N_MASK 0x7FE0 /* FLL1_N - [14:5] */
+#define WM8994_FLL1_N_SHIFT 5 /* FLL1_N - [14:5] */
+#define WM8994_FLL1_N_WIDTH 10 /* FLL1_N - [14:5] */
+#define WM8994_FLL1_LOOP_GAIN_MASK 0x000F /* FLL1_LOOP_GAIN - [3:0] */
+#define WM8994_FLL1_LOOP_GAIN_SHIFT 0 /* FLL1_LOOP_GAIN - [3:0] */
+#define WM8994_FLL1_LOOP_GAIN_WIDTH 4 /* FLL1_LOOP_GAIN - [3:0] */
+
+/*
+ * R548 (0x224) - FLL1 Control (5)
+ */
+#define WM8994_FLL1_FRC_NCO_VAL_MASK 0x1F80 /* FLL1_FRC_NCO_VAL - [12:7] */
+#define WM8994_FLL1_FRC_NCO_VAL_SHIFT 7 /* FLL1_FRC_NCO_VAL - [12:7] */
+#define WM8994_FLL1_FRC_NCO_VAL_WIDTH 6 /* FLL1_FRC_NCO_VAL - [12:7] */
+#define WM8994_FLL1_FRC_NCO 0x0040 /* FLL1_FRC_NCO */
+#define WM8994_FLL1_FRC_NCO_MASK 0x0040 /* FLL1_FRC_NCO */
+#define WM8994_FLL1_FRC_NCO_SHIFT 6 /* FLL1_FRC_NCO */
+#define WM8994_FLL1_FRC_NCO_WIDTH 1 /* FLL1_FRC_NCO */
+#define WM8994_FLL1_REFCLK_DIV_MASK 0x0018 /* FLL1_REFCLK_DIV - [4:3] */
+#define WM8994_FLL1_REFCLK_DIV_SHIFT 3 /* FLL1_REFCLK_DIV - [4:3] */
+#define WM8994_FLL1_REFCLK_DIV_WIDTH 2 /* FLL1_REFCLK_DIV - [4:3] */
+#define WM8994_FLL1_REFCLK_SRC_MASK 0x0003 /* FLL1_REFCLK_SRC - [1:0] */
+#define WM8994_FLL1_REFCLK_SRC_SHIFT 0 /* FLL1_REFCLK_SRC - [1:0] */
+#define WM8994_FLL1_REFCLK_SRC_WIDTH 2 /* FLL1_REFCLK_SRC - [1:0] */
+
+/*
+ * R576 (0x240) - FLL2 Control (1)
+ */
+#define WM8994_FLL2_FRAC 0x0004 /* FLL2_FRAC */
+#define WM8994_FLL2_FRAC_MASK 0x0004 /* FLL2_FRAC */
+#define WM8994_FLL2_FRAC_SHIFT 2 /* FLL2_FRAC */
+#define WM8994_FLL2_FRAC_WIDTH 1 /* FLL2_FRAC */
+#define WM8994_FLL2_OSC_ENA 0x0002 /* FLL2_OSC_ENA */
+#define WM8994_FLL2_OSC_ENA_MASK 0x0002 /* FLL2_OSC_ENA */
+#define WM8994_FLL2_OSC_ENA_SHIFT 1 /* FLL2_OSC_ENA */
+#define WM8994_FLL2_OSC_ENA_WIDTH 1 /* FLL2_OSC_ENA */
+#define WM8994_FLL2_ENA 0x0001 /* FLL2_ENA */
+#define WM8994_FLL2_ENA_MASK 0x0001 /* FLL2_ENA */
+#define WM8994_FLL2_ENA_SHIFT 0 /* FLL2_ENA */
+#define WM8994_FLL2_ENA_WIDTH 1 /* FLL2_ENA */
+
+/*
+ * R577 (0x241) - FLL2 Control (2)
+ */
+#define WM8994_FLL2_OUTDIV_MASK 0x3F00 /* FLL2_OUTDIV - [13:8] */
+#define WM8994_FLL2_OUTDIV_SHIFT 8 /* FLL2_OUTDIV - [13:8] */
+#define WM8994_FLL2_OUTDIV_WIDTH 6 /* FLL2_OUTDIV - [13:8] */
+#define WM8994_FLL2_CTRL_RATE_MASK 0x0070 /* FLL2_CTRL_RATE - [6:4] */
+#define WM8994_FLL2_CTRL_RATE_SHIFT 4 /* FLL2_CTRL_RATE - [6:4] */
+#define WM8994_FLL2_CTRL_RATE_WIDTH 3 /* FLL2_CTRL_RATE - [6:4] */
+#define WM8994_FLL2_FRATIO_MASK 0x0007 /* FLL2_FRATIO - [2:0] */
+#define WM8994_FLL2_FRATIO_SHIFT 0 /* FLL2_FRATIO - [2:0] */
+#define WM8994_FLL2_FRATIO_WIDTH 3 /* FLL2_FRATIO - [2:0] */
+
+/*
+ * R578 (0x242) - FLL2 Control (3)
+ */
+#define WM8994_FLL2_K_MASK 0xFFFF /* FLL2_K - [15:0] */
+#define WM8994_FLL2_K_SHIFT 0 /* FLL2_K - [15:0] */
+#define WM8994_FLL2_K_WIDTH 16 /* FLL2_K - [15:0] */
+
+/*
+ * R579 (0x243) - FLL2 Control (4)
+ */
+#define WM8994_FLL2_N_MASK 0x7FE0 /* FLL2_N - [14:5] */
+#define WM8994_FLL2_N_SHIFT 5 /* FLL2_N - [14:5] */
+#define WM8994_FLL2_N_WIDTH 10 /* FLL2_N - [14:5] */
+#define WM8994_FLL2_LOOP_GAIN_MASK 0x000F /* FLL2_LOOP_GAIN - [3:0] */
+#define WM8994_FLL2_LOOP_GAIN_SHIFT 0 /* FLL2_LOOP_GAIN - [3:0] */
+#define WM8994_FLL2_LOOP_GAIN_WIDTH 4 /* FLL2_LOOP_GAIN - [3:0] */
+
+/*
+ * R580 (0x244) - FLL2 Control (5)
+ */
+#define WM8994_FLL2_FRC_NCO_VAL_MASK 0x1F80 /* FLL2_FRC_NCO_VAL - [12:7] */
+#define WM8994_FLL2_FRC_NCO_VAL_SHIFT 7 /* FLL2_FRC_NCO_VAL - [12:7] */
+#define WM8994_FLL2_FRC_NCO_VAL_WIDTH 6 /* FLL2_FRC_NCO_VAL - [12:7] */
+#define WM8994_FLL2_FRC_NCO 0x0040 /* FLL2_FRC_NCO */
+#define WM8994_FLL2_FRC_NCO_MASK 0x0040 /* FLL2_FRC_NCO */
+#define WM8994_FLL2_FRC_NCO_SHIFT 6 /* FLL2_FRC_NCO */
+#define WM8994_FLL2_FRC_NCO_WIDTH 1 /* FLL2_FRC_NCO */
+#define WM8994_FLL2_REFCLK_DIV_MASK 0x0018 /* FLL2_REFCLK_DIV - [4:3] */
+#define WM8994_FLL2_REFCLK_DIV_SHIFT 3 /* FLL2_REFCLK_DIV - [4:3] */
+#define WM8994_FLL2_REFCLK_DIV_WIDTH 2 /* FLL2_REFCLK_DIV - [4:3] */
+#define WM8994_FLL2_REFCLK_SRC_MASK 0x0003 /* FLL2_REFCLK_SRC - [1:0] */
+#define WM8994_FLL2_REFCLK_SRC_SHIFT 0 /* FLL2_REFCLK_SRC - [1:0] */
+#define WM8994_FLL2_REFCLK_SRC_WIDTH 2 /* FLL2_REFCLK_SRC - [1:0] */
+
+/*
+ * R768 (0x300) - AIF1 Control (1)
+ */
+#define WM8994_AIF1ADCL_SRC 0x8000 /* AIF1ADCL_SRC */
+#define WM8994_AIF1ADCL_SRC_MASK 0x8000 /* AIF1ADCL_SRC */
+#define WM8994_AIF1ADCL_SRC_SHIFT 15 /* AIF1ADCL_SRC */
+#define WM8994_AIF1ADCL_SRC_WIDTH 1 /* AIF1ADCL_SRC */
+#define WM8994_AIF1ADCR_SRC 0x4000 /* AIF1ADCR_SRC */
+#define WM8994_AIF1ADCR_SRC_MASK 0x4000 /* AIF1ADCR_SRC */
+#define WM8994_AIF1ADCR_SRC_SHIFT 14 /* AIF1ADCR_SRC */
+#define WM8994_AIF1ADCR_SRC_WIDTH 1 /* AIF1ADCR_SRC */
+#define WM8994_AIF1ADC_TDM 0x2000 /* AIF1ADC_TDM */
+#define WM8994_AIF1ADC_TDM_MASK 0x2000 /* AIF1ADC_TDM */
+#define WM8994_AIF1ADC_TDM_SHIFT 13 /* AIF1ADC_TDM */
+#define WM8994_AIF1ADC_TDM_WIDTH 1 /* AIF1ADC_TDM */
+#define WM8994_AIF1_BCLK_INV 0x0100 /* AIF1_BCLK_INV */
+#define WM8994_AIF1_BCLK_INV_MASK 0x0100 /* AIF1_BCLK_INV */
+#define WM8994_AIF1_BCLK_INV_SHIFT 8 /* AIF1_BCLK_INV */
+#define WM8994_AIF1_BCLK_INV_WIDTH 1 /* AIF1_BCLK_INV */
+#define WM8994_AIF1_LRCLK_INV 0x0080 /* AIF1_LRCLK_INV */
+#define WM8994_AIF1_LRCLK_INV_MASK 0x0080 /* AIF1_LRCLK_INV */
+#define WM8994_AIF1_LRCLK_INV_SHIFT 7 /* AIF1_LRCLK_INV */
+#define WM8994_AIF1_LRCLK_INV_WIDTH 1 /* AIF1_LRCLK_INV */
+#define WM8994_AIF1_WL_MASK 0x0060 /* AIF1_WL - [6:5] */
+#define WM8994_AIF1_WL_SHIFT 5 /* AIF1_WL - [6:5] */
+#define WM8994_AIF1_WL_WIDTH 2 /* AIF1_WL - [6:5] */
+#define WM8994_AIF1_FMT_MASK 0x0018 /* AIF1_FMT - [4:3] */
+#define WM8994_AIF1_FMT_SHIFT 3 /* AIF1_FMT - [4:3] */
+#define WM8994_AIF1_FMT_WIDTH 2 /* AIF1_FMT - [4:3] */
+
+/*
+ * R769 (0x301) - AIF1 Control (2)
+ */
+#define WM8994_AIF1DACL_SRC 0x8000 /* AIF1DACL_SRC */
+#define WM8994_AIF1DACL_SRC_MASK 0x8000 /* AIF1DACL_SRC */
+#define WM8994_AIF1DACL_SRC_SHIFT 15 /* AIF1DACL_SRC */
+#define WM8994_AIF1DACL_SRC_WIDTH 1 /* AIF1DACL_SRC */
+#define WM8994_AIF1DACR_SRC 0x4000 /* AIF1DACR_SRC */
+#define WM8994_AIF1DACR_SRC_MASK 0x4000 /* AIF1DACR_SRC */
+#define WM8994_AIF1DACR_SRC_SHIFT 14 /* AIF1DACR_SRC */
+#define WM8994_AIF1DACR_SRC_WIDTH 1 /* AIF1DACR_SRC */
+#define WM8994_AIF1DAC_BOOST_MASK 0x0C00 /* AIF1DAC_BOOST - [11:10] */
+#define WM8994_AIF1DAC_BOOST_SHIFT 10 /* AIF1DAC_BOOST - [11:10] */
+#define WM8994_AIF1DAC_BOOST_WIDTH 2 /* AIF1DAC_BOOST - [11:10] */
+#define WM8994_AIF1_MONO 0x0100 /* AIF1_MONO */
+#define WM8994_AIF1_MONO_MASK 0x0100 /* AIF1_MONO */
+#define WM8994_AIF1_MONO_SHIFT 8 /* AIF1_MONO */
+#define WM8994_AIF1_MONO_WIDTH 1 /* AIF1_MONO */
+#define WM8994_AIF1DAC_COMP 0x0010 /* AIF1DAC_COMP */
+#define WM8994_AIF1DAC_COMP_MASK 0x0010 /* AIF1DAC_COMP */
+#define WM8994_AIF1DAC_COMP_SHIFT 4 /* AIF1DAC_COMP */
+#define WM8994_AIF1DAC_COMP_WIDTH 1 /* AIF1DAC_COMP */
+#define WM8994_AIF1DAC_COMPMODE 0x0008 /* AIF1DAC_COMPMODE */
+#define WM8994_AIF1DAC_COMPMODE_MASK 0x0008 /* AIF1DAC_COMPMODE */
+#define WM8994_AIF1DAC_COMPMODE_SHIFT 3 /* AIF1DAC_COMPMODE */
+#define WM8994_AIF1DAC_COMPMODE_WIDTH 1 /* AIF1DAC_COMPMODE */
+#define WM8994_AIF1ADC_COMP 0x0004 /* AIF1ADC_COMP */
+#define WM8994_AIF1ADC_COMP_MASK 0x0004 /* AIF1ADC_COMP */
+#define WM8994_AIF1ADC_COMP_SHIFT 2 /* AIF1ADC_COMP */
+#define WM8994_AIF1ADC_COMP_WIDTH 1 /* AIF1ADC_COMP */
+#define WM8994_AIF1ADC_COMPMODE 0x0002 /* AIF1ADC_COMPMODE */
+#define WM8994_AIF1ADC_COMPMODE_MASK 0x0002 /* AIF1ADC_COMPMODE */
+#define WM8994_AIF1ADC_COMPMODE_SHIFT 1 /* AIF1ADC_COMPMODE */
+#define WM8994_AIF1ADC_COMPMODE_WIDTH 1 /* AIF1ADC_COMPMODE */
+#define WM8994_AIF1_LOOPBACK 0x0001 /* AIF1_LOOPBACK */
+#define WM8994_AIF1_LOOPBACK_MASK 0x0001 /* AIF1_LOOPBACK */
+#define WM8994_AIF1_LOOPBACK_SHIFT 0 /* AIF1_LOOPBACK */
+#define WM8994_AIF1_LOOPBACK_WIDTH 1 /* AIF1_LOOPBACK */
+
+/*
+ * R770 (0x302) - AIF1 Master/Slave
+ */
+#define WM8994_AIF1_TRI 0x8000 /* AIF1_TRI */
+#define WM8994_AIF1_TRI_MASK 0x8000 /* AIF1_TRI */
+#define WM8994_AIF1_TRI_SHIFT 15 /* AIF1_TRI */
+#define WM8994_AIF1_TRI_WIDTH 1 /* AIF1_TRI */
+#define WM8994_AIF1_MSTR 0x4000 /* AIF1_MSTR */
+#define WM8994_AIF1_MSTR_MASK 0x4000 /* AIF1_MSTR */
+#define WM8994_AIF1_MSTR_SHIFT 14 /* AIF1_MSTR */
+#define WM8994_AIF1_MSTR_WIDTH 1 /* AIF1_MSTR */
+#define WM8994_AIF1_CLK_FRC 0x2000 /* AIF1_CLK_FRC */
+#define WM8994_AIF1_CLK_FRC_MASK 0x2000 /* AIF1_CLK_FRC */
+#define WM8994_AIF1_CLK_FRC_SHIFT 13 /* AIF1_CLK_FRC */
+#define WM8994_AIF1_CLK_FRC_WIDTH 1 /* AIF1_CLK_FRC */
+#define WM8994_AIF1_LRCLK_FRC 0x1000 /* AIF1_LRCLK_FRC */
+#define WM8994_AIF1_LRCLK_FRC_MASK 0x1000 /* AIF1_LRCLK_FRC */
+#define WM8994_AIF1_LRCLK_FRC_SHIFT 12 /* AIF1_LRCLK_FRC */
+#define WM8994_AIF1_LRCLK_FRC_WIDTH 1 /* AIF1_LRCLK_FRC */
+
+/*
+ * R771 (0x303) - AIF1 BCLK
+ */
+#define WM8994_AIF1_BCLK_DIV_MASK 0x01F0 /* AIF1_BCLK_DIV - [8:4] */
+#define WM8994_AIF1_BCLK_DIV_SHIFT 4 /* AIF1_BCLK_DIV - [8:4] */
+#define WM8994_AIF1_BCLK_DIV_WIDTH 5 /* AIF1_BCLK_DIV - [8:4] */
+
+/*
+ * R772 (0x304) - AIF1ADC LRCLK
+ */
+#define WM8994_AIF1ADC_LRCLK_DIR 0x0800 /* AIF1ADC_LRCLK_DIR */
+#define WM8994_AIF1ADC_LRCLK_DIR_MASK 0x0800 /* AIF1ADC_LRCLK_DIR */
+#define WM8994_AIF1ADC_LRCLK_DIR_SHIFT 11 /* AIF1ADC_LRCLK_DIR */
+#define WM8994_AIF1ADC_LRCLK_DIR_WIDTH 1 /* AIF1ADC_LRCLK_DIR */
+#define WM8994_AIF1ADC_RATE_MASK 0x07FF /* AIF1ADC_RATE - [10:0] */
+#define WM8994_AIF1ADC_RATE_SHIFT 0 /* AIF1ADC_RATE - [10:0] */
+#define WM8994_AIF1ADC_RATE_WIDTH 11 /* AIF1ADC_RATE - [10:0] */
+
+/*
+ * R773 (0x305) - AIF1DAC LRCLK
+ */
+#define WM8994_AIF1DAC_LRCLK_DIR 0x0800 /* AIF1DAC_LRCLK_DIR */
+#define WM8994_AIF1DAC_LRCLK_DIR_MASK 0x0800 /* AIF1DAC_LRCLK_DIR */
+#define WM8994_AIF1DAC_LRCLK_DIR_SHIFT 11 /* AIF1DAC_LRCLK_DIR */
+#define WM8994_AIF1DAC_LRCLK_DIR_WIDTH 1 /* AIF1DAC_LRCLK_DIR */
+#define WM8994_AIF1DAC_RATE_MASK 0x07FF /* AIF1DAC_RATE - [10:0] */
+#define WM8994_AIF1DAC_RATE_SHIFT 0 /* AIF1DAC_RATE - [10:0] */
+#define WM8994_AIF1DAC_RATE_WIDTH 11 /* AIF1DAC_RATE - [10:0] */
+
+/*
+ * R774 (0x306) - AIF1DAC Data
+ */
+#define WM8994_AIF1DACL_DAT_INV 0x0002 /* AIF1DACL_DAT_INV */
+#define WM8994_AIF1DACL_DAT_INV_MASK 0x0002 /* AIF1DACL_DAT_INV */
+#define WM8994_AIF1DACL_DAT_INV_SHIFT 1 /* AIF1DACL_DAT_INV */
+#define WM8994_AIF1DACL_DAT_INV_WIDTH 1 /* AIF1DACL_DAT_INV */
+#define WM8994_AIF1DACR_DAT_INV 0x0001 /* AIF1DACR_DAT_INV */
+#define WM8994_AIF1DACR_DAT_INV_MASK 0x0001 /* AIF1DACR_DAT_INV */
+#define WM8994_AIF1DACR_DAT_INV_SHIFT 0 /* AIF1DACR_DAT_INV */
+#define WM8994_AIF1DACR_DAT_INV_WIDTH 1 /* AIF1DACR_DAT_INV */
+
+/*
+ * R775 (0x307) - AIF1ADC Data
+ */
+#define WM8994_AIF1ADCL_DAT_INV 0x0002 /* AIF1ADCL_DAT_INV */
+#define WM8994_AIF1ADCL_DAT_INV_MASK 0x0002 /* AIF1ADCL_DAT_INV */
+#define WM8994_AIF1ADCL_DAT_INV_SHIFT 1 /* AIF1ADCL_DAT_INV */
+#define WM8994_AIF1ADCL_DAT_INV_WIDTH 1 /* AIF1ADCL_DAT_INV */
+#define WM8994_AIF1ADCR_DAT_INV 0x0001 /* AIF1ADCR_DAT_INV */
+#define WM8994_AIF1ADCR_DAT_INV_MASK 0x0001 /* AIF1ADCR_DAT_INV */
+#define WM8994_AIF1ADCR_DAT_INV_SHIFT 0 /* AIF1ADCR_DAT_INV */
+#define WM8994_AIF1ADCR_DAT_INV_WIDTH 1 /* AIF1ADCR_DAT_INV */
+
+/*
+ * R784 (0x310) - AIF2 Control (1)
+ */
+#define WM8994_AIF2ADCL_SRC 0x8000 /* AIF2ADCL_SRC */
+#define WM8994_AIF2ADCL_SRC_MASK 0x8000 /* AIF2ADCL_SRC */
+#define WM8994_AIF2ADCL_SRC_SHIFT 15 /* AIF2ADCL_SRC */
+#define WM8994_AIF2ADCL_SRC_WIDTH 1 /* AIF2ADCL_SRC */
+#define WM8994_AIF2ADCR_SRC 0x4000 /* AIF2ADCR_SRC */
+#define WM8994_AIF2ADCR_SRC_MASK 0x4000 /* AIF2ADCR_SRC */
+#define WM8994_AIF2ADCR_SRC_SHIFT 14 /* AIF2ADCR_SRC */
+#define WM8994_AIF2ADCR_SRC_WIDTH 1 /* AIF2ADCR_SRC */
+#define WM8994_AIF2ADC_TDM 0x2000 /* AIF2ADC_TDM */
+#define WM8994_AIF2ADC_TDM_MASK 0x2000 /* AIF2ADC_TDM */
+#define WM8994_AIF2ADC_TDM_SHIFT 13 /* AIF2ADC_TDM */
+#define WM8994_AIF2ADC_TDM_WIDTH 1 /* AIF2ADC_TDM */
+#define WM8994_AIF2ADC_TDM_CHAN 0x1000 /* AIF2ADC_TDM_CHAN */
+#define WM8994_AIF2ADC_TDM_CHAN_MASK 0x1000 /* AIF2ADC_TDM_CHAN */
+#define WM8994_AIF2ADC_TDM_CHAN_SHIFT 12 /* AIF2ADC_TDM_CHAN */
+#define WM8994_AIF2ADC_TDM_CHAN_WIDTH 1 /* AIF2ADC_TDM_CHAN */
+#define WM8994_AIF2_BCLK_INV 0x0100 /* AIF2_BCLK_INV */
+#define WM8994_AIF2_BCLK_INV_MASK 0x0100 /* AIF2_BCLK_INV */
+#define WM8994_AIF2_BCLK_INV_SHIFT 8 /* AIF2_BCLK_INV */
+#define WM8994_AIF2_BCLK_INV_WIDTH 1 /* AIF2_BCLK_INV */
+#define WM8994_AIF2_LRCLK_INV 0x0080 /* AIF2_LRCLK_INV */
+#define WM8994_AIF2_LRCLK_INV_MASK 0x0080 /* AIF2_LRCLK_INV */
+#define WM8994_AIF2_LRCLK_INV_SHIFT 7 /* AIF2_LRCLK_INV */
+#define WM8994_AIF2_LRCLK_INV_WIDTH 1 /* AIF2_LRCLK_INV */
+#define WM8994_AIF2_WL_MASK 0x0060 /* AIF2_WL - [6:5] */
+#define WM8994_AIF2_WL_SHIFT 5 /* AIF2_WL - [6:5] */
+#define WM8994_AIF2_WL_WIDTH 2 /* AIF2_WL - [6:5] */
+#define WM8994_AIF2_FMT_MASK 0x0018 /* AIF2_FMT - [4:3] */
+#define WM8994_AIF2_FMT_SHIFT 3 /* AIF2_FMT - [4:3] */
+#define WM8994_AIF2_FMT_WIDTH 2 /* AIF2_FMT - [4:3] */
+
+/*
+ * R785 (0x311) - AIF2 Control (2)
+ */
+#define WM8994_AIF2DACL_SRC 0x8000 /* AIF2DACL_SRC */
+#define WM8994_AIF2DACL_SRC_MASK 0x8000 /* AIF2DACL_SRC */
+#define WM8994_AIF2DACL_SRC_SHIFT 15 /* AIF2DACL_SRC */
+#define WM8994_AIF2DACL_SRC_WIDTH 1 /* AIF2DACL_SRC */
+#define WM8994_AIF2DACR_SRC 0x4000 /* AIF2DACR_SRC */
+#define WM8994_AIF2DACR_SRC_MASK 0x4000 /* AIF2DACR_SRC */
+#define WM8994_AIF2DACR_SRC_SHIFT 14 /* AIF2DACR_SRC */
+#define WM8994_AIF2DACR_SRC_WIDTH 1 /* AIF2DACR_SRC */
+#define WM8994_AIF2DAC_TDM 0x2000 /* AIF2DAC_TDM */
+#define WM8994_AIF2DAC_TDM_MASK 0x2000 /* AIF2DAC_TDM */
+#define WM8994_AIF2DAC_TDM_SHIFT 13 /* AIF2DAC_TDM */
+#define WM8994_AIF2DAC_TDM_WIDTH 1 /* AIF2DAC_TDM */
+#define WM8994_AIF2DAC_TDM_CHAN 0x1000 /* AIF2DAC_TDM_CHAN */
+#define WM8994_AIF2DAC_TDM_CHAN_MASK 0x1000 /* AIF2DAC_TDM_CHAN */
+#define WM8994_AIF2DAC_TDM_CHAN_SHIFT 12 /* AIF2DAC_TDM_CHAN */
+#define WM8994_AIF2DAC_TDM_CHAN_WIDTH 1 /* AIF2DAC_TDM_CHAN */
+#define WM8994_AIF2DAC_BOOST_MASK 0x0C00 /* AIF2DAC_BOOST - [11:10] */
+#define WM8994_AIF2DAC_BOOST_SHIFT 10 /* AIF2DAC_BOOST - [11:10] */
+#define WM8994_AIF2DAC_BOOST_WIDTH 2 /* AIF2DAC_BOOST - [11:10] */
+#define WM8994_AIF2_MONO 0x0100 /* AIF2_MONO */
+#define WM8994_AIF2_MONO_MASK 0x0100 /* AIF2_MONO */
+#define WM8994_AIF2_MONO_SHIFT 8 /* AIF2_MONO */
+#define WM8994_AIF2_MONO_WIDTH 1 /* AIF2_MONO */
+#define WM8994_AIF2DAC_COMP 0x0010 /* AIF2DAC_COMP */
+#define WM8994_AIF2DAC_COMP_MASK 0x0010 /* AIF2DAC_COMP */
+#define WM8994_AIF2DAC_COMP_SHIFT 4 /* AIF2DAC_COMP */
+#define WM8994_AIF2DAC_COMP_WIDTH 1 /* AIF2DAC_COMP */
+#define WM8994_AIF2DAC_COMPMODE 0x0008 /* AIF2DAC_COMPMODE */
+#define WM8994_AIF2DAC_COMPMODE_MASK 0x0008 /* AIF2DAC_COMPMODE */
+#define WM8994_AIF2DAC_COMPMODE_SHIFT 3 /* AIF2DAC_COMPMODE */
+#define WM8994_AIF2DAC_COMPMODE_WIDTH 1 /* AIF2DAC_COMPMODE */
+#define WM8994_AIF2ADC_COMP 0x0004 /* AIF2ADC_COMP */
+#define WM8994_AIF2ADC_COMP_MASK 0x0004 /* AIF2ADC_COMP */
+#define WM8994_AIF2ADC_COMP_SHIFT 2 /* AIF2ADC_COMP */
+#define WM8994_AIF2ADC_COMP_WIDTH 1 /* AIF2ADC_COMP */
+#define WM8994_AIF2ADC_COMPMODE 0x0002 /* AIF2ADC_COMPMODE */
+#define WM8994_AIF2ADC_COMPMODE_MASK 0x0002 /* AIF2ADC_COMPMODE */
+#define WM8994_AIF2ADC_COMPMODE_SHIFT 1 /* AIF2ADC_COMPMODE */
+#define WM8994_AIF2ADC_COMPMODE_WIDTH 1 /* AIF2ADC_COMPMODE */
+#define WM8994_AIF2_LOOPBACK 0x0001 /* AIF2_LOOPBACK */
+#define WM8994_AIF2_LOOPBACK_MASK 0x0001 /* AIF2_LOOPBACK */
+#define WM8994_AIF2_LOOPBACK_SHIFT 0 /* AIF2_LOOPBACK */
+#define WM8994_AIF2_LOOPBACK_WIDTH 1 /* AIF2_LOOPBACK */
+
+/*
+ * R786 (0x312) - AIF2 Master/Slave
+ */
+#define WM8994_AIF2_TRI 0x8000 /* AIF2_TRI */
+#define WM8994_AIF2_TRI_MASK 0x8000 /* AIF2_TRI */
+#define WM8994_AIF2_TRI_SHIFT 15 /* AIF2_TRI */
+#define WM8994_AIF2_TRI_WIDTH 1 /* AIF2_TRI */
+#define WM8994_AIF2_MSTR 0x4000 /* AIF2_MSTR */
+#define WM8994_AIF2_MSTR_MASK 0x4000 /* AIF2_MSTR */
+#define WM8994_AIF2_MSTR_SHIFT 14 /* AIF2_MSTR */
+#define WM8994_AIF2_MSTR_WIDTH 1 /* AIF2_MSTR */
+#define WM8994_AIF2_CLK_FRC 0x2000 /* AIF2_CLK_FRC */
+#define WM8994_AIF2_CLK_FRC_MASK 0x2000 /* AIF2_CLK_FRC */
+#define WM8994_AIF2_CLK_FRC_SHIFT 13 /* AIF2_CLK_FRC */
+#define WM8994_AIF2_CLK_FRC_WIDTH 1 /* AIF2_CLK_FRC */
+#define WM8994_AIF2_LRCLK_FRC 0x1000 /* AIF2_LRCLK_FRC */
+#define WM8994_AIF2_LRCLK_FRC_MASK 0x1000 /* AIF2_LRCLK_FRC */
+#define WM8994_AIF2_LRCLK_FRC_SHIFT 12 /* AIF2_LRCLK_FRC */
+#define WM8994_AIF2_LRCLK_FRC_WIDTH 1 /* AIF2_LRCLK_FRC */
+
+/*
+ * R787 (0x313) - AIF2 BCLK
+ */
+#define WM8994_AIF2_BCLK_DIV_MASK 0x01F0 /* AIF2_BCLK_DIV - [8:4] */
+#define WM8994_AIF2_BCLK_DIV_SHIFT 4 /* AIF2_BCLK_DIV - [8:4] */
+#define WM8994_AIF2_BCLK_DIV_WIDTH 5 /* AIF2_BCLK_DIV - [8:4] */
+
+/*
+ * R788 (0x314) - AIF2ADC LRCLK
+ */
+#define WM8994_AIF2ADC_LRCLK_DIR 0x0800 /* AIF2ADC_LRCLK_DIR */
+#define WM8994_AIF2ADC_LRCLK_DIR_MASK 0x0800 /* AIF2ADC_LRCLK_DIR */
+#define WM8994_AIF2ADC_LRCLK_DIR_SHIFT 11 /* AIF2ADC_LRCLK_DIR */
+#define WM8994_AIF2ADC_LRCLK_DIR_WIDTH 1 /* AIF2ADC_LRCLK_DIR */
+#define WM8994_AIF2ADC_RATE_MASK 0x07FF /* AIF2ADC_RATE - [10:0] */
+#define WM8994_AIF2ADC_RATE_SHIFT 0 /* AIF2ADC_RATE - [10:0] */
+#define WM8994_AIF2ADC_RATE_WIDTH 11 /* AIF2ADC_RATE - [10:0] */
+
+/*
+ * R789 (0x315) - AIF2DAC LRCLK
+ */
+#define WM8994_AIF2DAC_LRCLK_DIR 0x0800 /* AIF2DAC_LRCLK_DIR */
+#define WM8994_AIF2DAC_LRCLK_DIR_MASK 0x0800 /* AIF2DAC_LRCLK_DIR */
+#define WM8994_AIF2DAC_LRCLK_DIR_SHIFT 11 /* AIF2DAC_LRCLK_DIR */
+#define WM8994_AIF2DAC_LRCLK_DIR_WIDTH 1 /* AIF2DAC_LRCLK_DIR */
+#define WM8994_AIF2DAC_RATE_MASK 0x07FF /* AIF2DAC_RATE - [10:0] */
+#define WM8994_AIF2DAC_RATE_SHIFT 0 /* AIF2DAC_RATE - [10:0] */
+#define WM8994_AIF2DAC_RATE_WIDTH 11 /* AIF2DAC_RATE - [10:0] */
+
+/*
+ * R790 (0x316) - AIF2DAC Data
+ */
+#define WM8994_AIF2DACL_DAT_INV 0x0002 /* AIF2DACL_DAT_INV */
+#define WM8994_AIF2DACL_DAT_INV_MASK 0x0002 /* AIF2DACL_DAT_INV */
+#define WM8994_AIF2DACL_DAT_INV_SHIFT 1 /* AIF2DACL_DAT_INV */
+#define WM8994_AIF2DACL_DAT_INV_WIDTH 1 /* AIF2DACL_DAT_INV */
+#define WM8994_AIF2DACR_DAT_INV 0x0001 /* AIF2DACR_DAT_INV */
+#define WM8994_AIF2DACR_DAT_INV_MASK 0x0001 /* AIF2DACR_DAT_INV */
+#define WM8994_AIF2DACR_DAT_INV_SHIFT 0 /* AIF2DACR_DAT_INV */
+#define WM8994_AIF2DACR_DAT_INV_WIDTH 1 /* AIF2DACR_DAT_INV */
+
+/*
+ * R791 (0x317) - AIF2ADC Data
+ */
+#define WM8994_AIF2ADCL_DAT_INV 0x0002 /* AIF2ADCL_DAT_INV */
+#define WM8994_AIF2ADCL_DAT_INV_MASK 0x0002 /* AIF2ADCL_DAT_INV */
+#define WM8994_AIF2ADCL_DAT_INV_SHIFT 1 /* AIF2ADCL_DAT_INV */
+#define WM8994_AIF2ADCL_DAT_INV_WIDTH 1 /* AIF2ADCL_DAT_INV */
+#define WM8994_AIF2ADCR_DAT_INV 0x0001 /* AIF2ADCR_DAT_INV */
+#define WM8994_AIF2ADCR_DAT_INV_MASK 0x0001 /* AIF2ADCR_DAT_INV */
+#define WM8994_AIF2ADCR_DAT_INV_SHIFT 0 /* AIF2ADCR_DAT_INV */
+#define WM8994_AIF2ADCR_DAT_INV_WIDTH 1 /* AIF2ADCR_DAT_INV */
+
+/*
+ * R1024 (0x400) - AIF1 ADC1 Left Volume
+ */
+#define WM8994_AIF1ADC1_VU 0x0100 /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1_VU_MASK 0x0100 /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1_VU_SHIFT 8 /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1_VU_WIDTH 1 /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1L_VOL_MASK 0x00FF /* AIF1ADC1L_VOL - [7:0] */
+#define WM8994_AIF1ADC1L_VOL_SHIFT 0 /* AIF1ADC1L_VOL - [7:0] */
+#define WM8994_AIF1ADC1L_VOL_WIDTH 8 /* AIF1ADC1L_VOL - [7:0] */
+
+/*
+ * R1025 (0x401) - AIF1 ADC1 Right Volume
+ */
+#define WM8994_AIF1ADC1_VU 0x0100 /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1_VU_MASK 0x0100 /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1_VU_SHIFT 8 /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1_VU_WIDTH 1 /* AIF1ADC1_VU */
+#define WM8994_AIF1ADC1R_VOL_MASK 0x00FF /* AIF1ADC1R_VOL - [7:0] */
+#define WM8994_AIF1ADC1R_VOL_SHIFT 0 /* AIF1ADC1R_VOL - [7:0] */
+#define WM8994_AIF1ADC1R_VOL_WIDTH 8 /* AIF1ADC1R_VOL - [7:0] */
+
+/*
+ * R1026 (0x402) - AIF1 DAC1 Left Volume
+ */
+#define WM8994_AIF1DAC1_VU 0x0100 /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1_VU_MASK 0x0100 /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1_VU_SHIFT 8 /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1_VU_WIDTH 1 /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1L_VOL_MASK 0x00FF /* AIF1DAC1L_VOL - [7:0] */
+#define WM8994_AIF1DAC1L_VOL_SHIFT 0 /* AIF1DAC1L_VOL - [7:0] */
+#define WM8994_AIF1DAC1L_VOL_WIDTH 8 /* AIF1DAC1L_VOL - [7:0] */
+
+/*
+ * R1027 (0x403) - AIF1 DAC1 Right Volume
+ */
+#define WM8994_AIF1DAC1_VU 0x0100 /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1_VU_MASK 0x0100 /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1_VU_SHIFT 8 /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1_VU_WIDTH 1 /* AIF1DAC1_VU */
+#define WM8994_AIF1DAC1R_VOL_MASK 0x00FF /* AIF1DAC1R_VOL - [7:0] */
+#define WM8994_AIF1DAC1R_VOL_SHIFT 0 /* AIF1DAC1R_VOL - [7:0] */
+#define WM8994_AIF1DAC1R_VOL_WIDTH 8 /* AIF1DAC1R_VOL - [7:0] */
+
+/*
+ * R1028 (0x404) - AIF1 ADC2 Left Volume
+ */
+#define WM8994_AIF1ADC2_VU 0x0100 /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2_VU_MASK 0x0100 /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2_VU_SHIFT 8 /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2_VU_WIDTH 1 /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2L_VOL_MASK 0x00FF /* AIF1ADC2L_VOL - [7:0] */
+#define WM8994_AIF1ADC2L_VOL_SHIFT 0 /* AIF1ADC2L_VOL - [7:0] */
+#define WM8994_AIF1ADC2L_VOL_WIDTH 8 /* AIF1ADC2L_VOL - [7:0] */
+
+/*
+ * R1029 (0x405) - AIF1 ADC2 Right Volume
+ */
+#define WM8994_AIF1ADC2_VU 0x0100 /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2_VU_MASK 0x0100 /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2_VU_SHIFT 8 /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2_VU_WIDTH 1 /* AIF1ADC2_VU */
+#define WM8994_AIF1ADC2R_VOL_MASK 0x00FF /* AIF1ADC2R_VOL - [7:0] */
+#define WM8994_AIF1ADC2R_VOL_SHIFT 0 /* AIF1ADC2R_VOL - [7:0] */
+#define WM8994_AIF1ADC2R_VOL_WIDTH 8 /* AIF1ADC2R_VOL - [7:0] */
+
+/*
+ * R1030 (0x406) - AIF1 DAC2 Left Volume
+ */
+#define WM8994_AIF1DAC2_VU 0x0100 /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2_VU_MASK 0x0100 /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2_VU_SHIFT 8 /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2_VU_WIDTH 1 /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2L_VOL_MASK 0x00FF /* AIF1DAC2L_VOL - [7:0] */
+#define WM8994_AIF1DAC2L_VOL_SHIFT 0 /* AIF1DAC2L_VOL - [7:0] */
+#define WM8994_AIF1DAC2L_VOL_WIDTH 8 /* AIF1DAC2L_VOL - [7:0] */
+
+/*
+ * R1031 (0x407) - AIF1 DAC2 Right Volume
+ */
+#define WM8994_AIF1DAC2_VU 0x0100 /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2_VU_MASK 0x0100 /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2_VU_SHIFT 8 /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2_VU_WIDTH 1 /* AIF1DAC2_VU */
+#define WM8994_AIF1DAC2R_VOL_MASK 0x00FF /* AIF1DAC2R_VOL - [7:0] */
+#define WM8994_AIF1DAC2R_VOL_SHIFT 0 /* AIF1DAC2R_VOL - [7:0] */
+#define WM8994_AIF1DAC2R_VOL_WIDTH 8 /* AIF1DAC2R_VOL - [7:0] */
+
+/*
+ * R1040 (0x410) - AIF1 ADC1 Filters
+ */
+#define WM8994_AIF1ADC_4FS 0x8000 /* AIF1ADC_4FS */
+#define WM8994_AIF1ADC_4FS_MASK 0x8000 /* AIF1ADC_4FS */
+#define WM8994_AIF1ADC_4FS_SHIFT 15 /* AIF1ADC_4FS */
+#define WM8994_AIF1ADC_4FS_WIDTH 1 /* AIF1ADC_4FS */
+#define WM8994_AIF1ADC1_HPF_CUT_MASK 0x6000 /* AIF1ADC1_HPF_CUT - [14:13] */
+#define WM8994_AIF1ADC1_HPF_CUT_SHIFT 13 /* AIF1ADC1_HPF_CUT - [14:13] */
+#define WM8994_AIF1ADC1_HPF_CUT_WIDTH 2 /* AIF1ADC1_HPF_CUT - [14:13] */
+#define WM8994_AIF1ADC1L_HPF 0x1000 /* AIF1ADC1L_HPF */
+#define WM8994_AIF1ADC1L_HPF_MASK 0x1000 /* AIF1ADC1L_HPF */
+#define WM8994_AIF1ADC1L_HPF_SHIFT 12 /* AIF1ADC1L_HPF */
+#define WM8994_AIF1ADC1L_HPF_WIDTH 1 /* AIF1ADC1L_HPF */
+#define WM8994_AIF1ADC1R_HPF 0x0800 /* AIF1ADC1R_HPF */
+#define WM8994_AIF1ADC1R_HPF_MASK 0x0800 /* AIF1ADC1R_HPF */
+#define WM8994_AIF1ADC1R_HPF_SHIFT 11 /* AIF1ADC1R_HPF */
+#define WM8994_AIF1ADC1R_HPF_WIDTH 1 /* AIF1ADC1R_HPF */
+
+/*
+ * R1041 (0x411) - AIF1 ADC2 Filters
+ */
+#define WM8994_AIF1ADC2_HPF_CUT_MASK 0x6000 /* AIF1ADC2_HPF_CUT - [14:13] */
+#define WM8994_AIF1ADC2_HPF_CUT_SHIFT 13 /* AIF1ADC2_HPF_CUT - [14:13] */
+#define WM8994_AIF1ADC2_HPF_CUT_WIDTH 2 /* AIF1ADC2_HPF_CUT - [14:13] */
+#define WM8994_AIF1ADC2L_HPF 0x1000 /* AIF1ADC2L_HPF */
+#define WM8994_AIF1ADC2L_HPF_MASK 0x1000 /* AIF1ADC2L_HPF */
+#define WM8994_AIF1ADC2L_HPF_SHIFT 12 /* AIF1ADC2L_HPF */
+#define WM8994_AIF1ADC2L_HPF_WIDTH 1 /* AIF1ADC2L_HPF */
+#define WM8994_AIF1ADC2R_HPF 0x0800 /* AIF1ADC2R_HPF */
+#define WM8994_AIF1ADC2R_HPF_MASK 0x0800 /* AIF1ADC2R_HPF */
+#define WM8994_AIF1ADC2R_HPF_SHIFT 11 /* AIF1ADC2R_HPF */
+#define WM8994_AIF1ADC2R_HPF_WIDTH 1 /* AIF1ADC2R_HPF */
+
+/*
+ * R1056 (0x420) - AIF1 DAC1 Filters (1)
+ */
+#define WM8994_AIF1DAC1_MUTE 0x0200 /* AIF1DAC1_MUTE */
+#define WM8994_AIF1DAC1_MUTE_MASK 0x0200 /* AIF1DAC1_MUTE */
+#define WM8994_AIF1DAC1_MUTE_SHIFT 9 /* AIF1DAC1_MUTE */
+#define WM8994_AIF1DAC1_MUTE_WIDTH 1 /* AIF1DAC1_MUTE */
+#define WM8994_AIF1DAC1_MONO 0x0080 /* AIF1DAC1_MONO */
+#define WM8994_AIF1DAC1_MONO_MASK 0x0080 /* AIF1DAC1_MONO */
+#define WM8994_AIF1DAC1_MONO_SHIFT 7 /* AIF1DAC1_MONO */
+#define WM8994_AIF1DAC1_MONO_WIDTH 1 /* AIF1DAC1_MONO */
+#define WM8994_AIF1DAC1_MUTERATE 0x0020 /* AIF1DAC1_MUTERATE */
+#define WM8994_AIF1DAC1_MUTERATE_MASK 0x0020 /* AIF1DAC1_MUTERATE */
+#define WM8994_AIF1DAC1_MUTERATE_SHIFT 5 /* AIF1DAC1_MUTERATE */
+#define WM8994_AIF1DAC1_MUTERATE_WIDTH 1 /* AIF1DAC1_MUTERATE */
+#define WM8994_AIF1DAC1_UNMUTE_RAMP 0x0010 /* AIF1DAC1_UNMUTE_RAMP */
+#define WM8994_AIF1DAC1_UNMUTE_RAMP_MASK 0x0010 /* AIF1DAC1_UNMUTE_RAMP */
+#define WM8994_AIF1DAC1_UNMUTE_RAMP_SHIFT 4 /* AIF1DAC1_UNMUTE_RAMP */
+#define WM8994_AIF1DAC1_UNMUTE_RAMP_WIDTH 1 /* AIF1DAC1_UNMUTE_RAMP */
+#define WM8994_AIF1DAC1_DEEMP_MASK 0x0006 /* AIF1DAC1_DEEMP - [2:1] */
+#define WM8994_AIF1DAC1_DEEMP_SHIFT 1 /* AIF1DAC1_DEEMP - [2:1] */
+#define WM8994_AIF1DAC1_DEEMP_WIDTH 2 /* AIF1DAC1_DEEMP - [2:1] */
+
+/*
+ * R1057 (0x421) - AIF1 DAC1 Filters (2)
+ */
+#define WM8994_AIF1DAC1_3D_GAIN_MASK 0x3E00 /* AIF1DAC1_3D_GAIN - [13:9] */
+#define WM8994_AIF1DAC1_3D_GAIN_SHIFT 9 /* AIF1DAC1_3D_GAIN - [13:9] */
+#define WM8994_AIF1DAC1_3D_GAIN_WIDTH 5 /* AIF1DAC1_3D_GAIN - [13:9] */
+#define WM8994_AIF1DAC1_3D_ENA 0x0100 /* AIF1DAC1_3D_ENA */
+#define WM8994_AIF1DAC1_3D_ENA_MASK 0x0100 /* AIF1DAC1_3D_ENA */
+#define WM8994_AIF1DAC1_3D_ENA_SHIFT 8 /* AIF1DAC1_3D_ENA */
+#define WM8994_AIF1DAC1_3D_ENA_WIDTH 1 /* AIF1DAC1_3D_ENA */
+
+/*
+ * R1058 (0x422) - AIF1 DAC2 Filters (1)
+ */
+#define WM8994_AIF1DAC2_MUTE 0x0200 /* AIF1DAC2_MUTE */
+#define WM8994_AIF1DAC2_MUTE_MASK 0x0200 /* AIF1DAC2_MUTE */
+#define WM8994_AIF1DAC2_MUTE_SHIFT 9 /* AIF1DAC2_MUTE */
+#define WM8994_AIF1DAC2_MUTE_WIDTH 1 /* AIF1DAC2_MUTE */
+#define WM8994_AIF1DAC2_MONO 0x0080 /* AIF1DAC2_MONO */
+#define WM8994_AIF1DAC2_MONO_MASK 0x0080 /* AIF1DAC2_MONO */
+#define WM8994_AIF1DAC2_MONO_SHIFT 7 /* AIF1DAC2_MONO */
+#define WM8994_AIF1DAC2_MONO_WIDTH 1 /* AIF1DAC2_MONO */
+#define WM8994_AIF1DAC2_MUTERATE 0x0020 /* AIF1DAC2_MUTERATE */
+#define WM8994_AIF1DAC2_MUTERATE_MASK 0x0020 /* AIF1DAC2_MUTERATE */
+#define WM8994_AIF1DAC2_MUTERATE_SHIFT 5 /* AIF1DAC2_MUTERATE */
+#define WM8994_AIF1DAC2_MUTERATE_WIDTH 1 /* AIF1DAC2_MUTERATE */
+#define WM8994_AIF1DAC2_UNMUTE_RAMP 0x0010 /* AIF1DAC2_UNMUTE_RAMP */
+#define WM8994_AIF1DAC2_UNMUTE_RAMP_MASK 0x0010 /* AIF1DAC2_UNMUTE_RAMP */
+#define WM8994_AIF1DAC2_UNMUTE_RAMP_SHIFT 4 /* AIF1DAC2_UNMUTE_RAMP */
+#define WM8994_AIF1DAC2_UNMUTE_RAMP_WIDTH 1 /* AIF1DAC2_UNMUTE_RAMP */
+#define WM8994_AIF1DAC2_DEEMP_MASK 0x0006 /* AIF1DAC2_DEEMP - [2:1] */
+#define WM8994_AIF1DAC2_DEEMP_SHIFT 1 /* AIF1DAC2_DEEMP - [2:1] */
+#define WM8994_AIF1DAC2_DEEMP_WIDTH 2 /* AIF1DAC2_DEEMP - [2:1] */
+
+/*
+ * R1059 (0x423) - AIF1 DAC2 Filters (2)
+ */
+#define WM8994_AIF1DAC2_3D_GAIN_MASK 0x3E00 /* AIF1DAC2_3D_GAIN - [13:9] */
+#define WM8994_AIF1DAC2_3D_GAIN_SHIFT 9 /* AIF1DAC2_3D_GAIN - [13:9] */
+#define WM8994_AIF1DAC2_3D_GAIN_WIDTH 5 /* AIF1DAC2_3D_GAIN - [13:9] */
+#define WM8994_AIF1DAC2_3D_ENA 0x0100 /* AIF1DAC2_3D_ENA */
+#define WM8994_AIF1DAC2_3D_ENA_MASK 0x0100 /* AIF1DAC2_3D_ENA */
+#define WM8994_AIF1DAC2_3D_ENA_SHIFT 8 /* AIF1DAC2_3D_ENA */
+#define WM8994_AIF1DAC2_3D_ENA_WIDTH 1 /* AIF1DAC2_3D_ENA */
+
+/*
+ * R1088 (0x440) - AIF1 DRC1 (1)
+ */
+#define WM8994_AIF1DRC1_SIG_DET_RMS_MASK 0xF800 /* AIF1DRC1_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF1DRC1_SIG_DET_RMS_SHIFT 11 /* AIF1DRC1_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF1DRC1_SIG_DET_RMS_WIDTH 5 /* AIF1DRC1_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF1DRC1_SIG_DET_PK_MASK 0x0600 /* AIF1DRC1_SIG_DET_PK - [10:9] */
+#define WM8994_AIF1DRC1_SIG_DET_PK_SHIFT 9 /* AIF1DRC1_SIG_DET_PK - [10:9] */
+#define WM8994_AIF1DRC1_SIG_DET_PK_WIDTH 2 /* AIF1DRC1_SIG_DET_PK - [10:9] */
+#define WM8994_AIF1DRC1_NG_ENA 0x0100 /* AIF1DRC1_NG_ENA */
+#define WM8994_AIF1DRC1_NG_ENA_MASK 0x0100 /* AIF1DRC1_NG_ENA */
+#define WM8994_AIF1DRC1_NG_ENA_SHIFT 8 /* AIF1DRC1_NG_ENA */
+#define WM8994_AIF1DRC1_NG_ENA_WIDTH 1 /* AIF1DRC1_NG_ENA */
+#define WM8994_AIF1DRC1_SIG_DET_MODE 0x0080 /* AIF1DRC1_SIG_DET_MODE */
+#define WM8994_AIF1DRC1_SIG_DET_MODE_MASK 0x0080 /* AIF1DRC1_SIG_DET_MODE */
+#define WM8994_AIF1DRC1_SIG_DET_MODE_SHIFT 7 /* AIF1DRC1_SIG_DET_MODE */
+#define WM8994_AIF1DRC1_SIG_DET_MODE_WIDTH 1 /* AIF1DRC1_SIG_DET_MODE */
+#define WM8994_AIF1DRC1_SIG_DET 0x0040 /* AIF1DRC1_SIG_DET */
+#define WM8994_AIF1DRC1_SIG_DET_MASK 0x0040 /* AIF1DRC1_SIG_DET */
+#define WM8994_AIF1DRC1_SIG_DET_SHIFT 6 /* AIF1DRC1_SIG_DET */
+#define WM8994_AIF1DRC1_SIG_DET_WIDTH 1 /* AIF1DRC1_SIG_DET */
+#define WM8994_AIF1DRC1_KNEE2_OP_ENA 0x0020 /* AIF1DRC1_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC1_KNEE2_OP_ENA_MASK 0x0020 /* AIF1DRC1_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC1_KNEE2_OP_ENA_SHIFT 5 /* AIF1DRC1_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC1_KNEE2_OP_ENA_WIDTH 1 /* AIF1DRC1_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC1_QR 0x0010 /* AIF1DRC1_QR */
+#define WM8994_AIF1DRC1_QR_MASK 0x0010 /* AIF1DRC1_QR */
+#define WM8994_AIF1DRC1_QR_SHIFT 4 /* AIF1DRC1_QR */
+#define WM8994_AIF1DRC1_QR_WIDTH 1 /* AIF1DRC1_QR */
+#define WM8994_AIF1DRC1_ANTICLIP 0x0008 /* AIF1DRC1_ANTICLIP */
+#define WM8994_AIF1DRC1_ANTICLIP_MASK 0x0008 /* AIF1DRC1_ANTICLIP */
+#define WM8994_AIF1DRC1_ANTICLIP_SHIFT 3 /* AIF1DRC1_ANTICLIP */
+#define WM8994_AIF1DRC1_ANTICLIP_WIDTH 1 /* AIF1DRC1_ANTICLIP */
+#define WM8994_AIF1DAC1_DRC_ENA 0x0004 /* AIF1DAC1_DRC_ENA */
+#define WM8994_AIF1DAC1_DRC_ENA_MASK 0x0004 /* AIF1DAC1_DRC_ENA */
+#define WM8994_AIF1DAC1_DRC_ENA_SHIFT 2 /* AIF1DAC1_DRC_ENA */
+#define WM8994_AIF1DAC1_DRC_ENA_WIDTH 1 /* AIF1DAC1_DRC_ENA */
+#define WM8994_AIF1ADC1L_DRC_ENA 0x0002 /* AIF1ADC1L_DRC_ENA */
+#define WM8994_AIF1ADC1L_DRC_ENA_MASK 0x0002 /* AIF1ADC1L_DRC_ENA */
+#define WM8994_AIF1ADC1L_DRC_ENA_SHIFT 1 /* AIF1ADC1L_DRC_ENA */
+#define WM8994_AIF1ADC1L_DRC_ENA_WIDTH 1 /* AIF1ADC1L_DRC_ENA */
+#define WM8994_AIF1ADC1R_DRC_ENA 0x0001 /* AIF1ADC1R_DRC_ENA */
+#define WM8994_AIF1ADC1R_DRC_ENA_MASK 0x0001 /* AIF1ADC1R_DRC_ENA */
+#define WM8994_AIF1ADC1R_DRC_ENA_SHIFT 0 /* AIF1ADC1R_DRC_ENA */
+#define WM8994_AIF1ADC1R_DRC_ENA_WIDTH 1 /* AIF1ADC1R_DRC_ENA */
+
+/*
+ * R1089 (0x441) - AIF1 DRC1 (2)
+ */
+#define WM8994_AIF1DRC1_ATK_MASK 0x1E00 /* AIF1DRC1_ATK - [12:9] */
+#define WM8994_AIF1DRC1_ATK_SHIFT 9 /* AIF1DRC1_ATK - [12:9] */
+#define WM8994_AIF1DRC1_ATK_WIDTH 4 /* AIF1DRC1_ATK - [12:9] */
+#define WM8994_AIF1DRC1_DCY_MASK 0x01E0 /* AIF1DRC1_DCY - [8:5] */
+#define WM8994_AIF1DRC1_DCY_SHIFT 5 /* AIF1DRC1_DCY - [8:5] */
+#define WM8994_AIF1DRC1_DCY_WIDTH 4 /* AIF1DRC1_DCY - [8:5] */
+#define WM8994_AIF1DRC1_MINGAIN_MASK 0x001C /* AIF1DRC1_MINGAIN - [4:2] */
+#define WM8994_AIF1DRC1_MINGAIN_SHIFT 2 /* AIF1DRC1_MINGAIN - [4:2] */
+#define WM8994_AIF1DRC1_MINGAIN_WIDTH 3 /* AIF1DRC1_MINGAIN - [4:2] */
+#define WM8994_AIF1DRC1_MAXGAIN_MASK 0x0003 /* AIF1DRC1_MAXGAIN - [1:0] */
+#define WM8994_AIF1DRC1_MAXGAIN_SHIFT 0 /* AIF1DRC1_MAXGAIN - [1:0] */
+#define WM8994_AIF1DRC1_MAXGAIN_WIDTH 2 /* AIF1DRC1_MAXGAIN - [1:0] */
+
+/*
+ * R1090 (0x442) - AIF1 DRC1 (3)
+ */
+#define WM8994_AIF1DRC1_NG_MINGAIN_MASK 0xF000 /* AIF1DRC1_NG_MINGAIN - [15:12] */
+#define WM8994_AIF1DRC1_NG_MINGAIN_SHIFT 12 /* AIF1DRC1_NG_MINGAIN - [15:12] */
+#define WM8994_AIF1DRC1_NG_MINGAIN_WIDTH 4 /* AIF1DRC1_NG_MINGAIN - [15:12] */
+#define WM8994_AIF1DRC1_NG_EXP_MASK 0x0C00 /* AIF1DRC1_NG_EXP - [11:10] */
+#define WM8994_AIF1DRC1_NG_EXP_SHIFT 10 /* AIF1DRC1_NG_EXP - [11:10] */
+#define WM8994_AIF1DRC1_NG_EXP_WIDTH 2 /* AIF1DRC1_NG_EXP - [11:10] */
+#define WM8994_AIF1DRC1_QR_THR_MASK 0x0300 /* AIF1DRC1_QR_THR - [9:8] */
+#define WM8994_AIF1DRC1_QR_THR_SHIFT 8 /* AIF1DRC1_QR_THR - [9:8] */
+#define WM8994_AIF1DRC1_QR_THR_WIDTH 2 /* AIF1DRC1_QR_THR - [9:8] */
+#define WM8994_AIF1DRC1_QR_DCY_MASK 0x00C0 /* AIF1DRC1_QR_DCY - [7:6] */
+#define WM8994_AIF1DRC1_QR_DCY_SHIFT 6 /* AIF1DRC1_QR_DCY - [7:6] */
+#define WM8994_AIF1DRC1_QR_DCY_WIDTH 2 /* AIF1DRC1_QR_DCY - [7:6] */
+#define WM8994_AIF1DRC1_HI_COMP_MASK 0x0038 /* AIF1DRC1_HI_COMP - [5:3] */
+#define WM8994_AIF1DRC1_HI_COMP_SHIFT 3 /* AIF1DRC1_HI_COMP - [5:3] */
+#define WM8994_AIF1DRC1_HI_COMP_WIDTH 3 /* AIF1DRC1_HI_COMP - [5:3] */
+#define WM8994_AIF1DRC1_LO_COMP_MASK 0x0007 /* AIF1DRC1_LO_COMP - [2:0] */
+#define WM8994_AIF1DRC1_LO_COMP_SHIFT 0 /* AIF1DRC1_LO_COMP - [2:0] */
+#define WM8994_AIF1DRC1_LO_COMP_WIDTH 3 /* AIF1DRC1_LO_COMP - [2:0] */
+
+/*
+ * R1091 (0x443) - AIF1 DRC1 (4)
+ */
+#define WM8994_AIF1DRC1_KNEE_IP_MASK 0x07E0 /* AIF1DRC1_KNEE_IP - [10:5] */
+#define WM8994_AIF1DRC1_KNEE_IP_SHIFT 5 /* AIF1DRC1_KNEE_IP - [10:5] */
+#define WM8994_AIF1DRC1_KNEE_IP_WIDTH 6 /* AIF1DRC1_KNEE_IP - [10:5] */
+#define WM8994_AIF1DRC1_KNEE_OP_MASK 0x001F /* AIF1DRC1_KNEE_OP - [4:0] */
+#define WM8994_AIF1DRC1_KNEE_OP_SHIFT 0 /* AIF1DRC1_KNEE_OP - [4:0] */
+#define WM8994_AIF1DRC1_KNEE_OP_WIDTH 5 /* AIF1DRC1_KNEE_OP - [4:0] */
+
+/*
+ * R1092 (0x444) - AIF1 DRC1 (5)
+ */
+#define WM8994_AIF1DRC1_KNEE2_IP_MASK 0x03E0 /* AIF1DRC1_KNEE2_IP - [9:5] */
+#define WM8994_AIF1DRC1_KNEE2_IP_SHIFT 5 /* AIF1DRC1_KNEE2_IP - [9:5] */
+#define WM8994_AIF1DRC1_KNEE2_IP_WIDTH 5 /* AIF1DRC1_KNEE2_IP - [9:5] */
+#define WM8994_AIF1DRC1_KNEE2_OP_MASK 0x001F /* AIF1DRC1_KNEE2_OP - [4:0] */
+#define WM8994_AIF1DRC1_KNEE2_OP_SHIFT 0 /* AIF1DRC1_KNEE2_OP - [4:0] */
+#define WM8994_AIF1DRC1_KNEE2_OP_WIDTH 5 /* AIF1DRC1_KNEE2_OP - [4:0] */
+
+/*
+ * R1104 (0x450) - AIF1 DRC2 (1)
+ */
+#define WM8994_AIF1DRC2_SIG_DET_RMS_MASK 0xF800 /* AIF1DRC2_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF1DRC2_SIG_DET_RMS_SHIFT 11 /* AIF1DRC2_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF1DRC2_SIG_DET_RMS_WIDTH 5 /* AIF1DRC2_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF1DRC2_SIG_DET_PK_MASK 0x0600 /* AIF1DRC2_SIG_DET_PK - [10:9] */
+#define WM8994_AIF1DRC2_SIG_DET_PK_SHIFT 9 /* AIF1DRC2_SIG_DET_PK - [10:9] */
+#define WM8994_AIF1DRC2_SIG_DET_PK_WIDTH 2 /* AIF1DRC2_SIG_DET_PK - [10:9] */
+#define WM8994_AIF1DRC2_NG_ENA 0x0100 /* AIF1DRC2_NG_ENA */
+#define WM8994_AIF1DRC2_NG_ENA_MASK 0x0100 /* AIF1DRC2_NG_ENA */
+#define WM8994_AIF1DRC2_NG_ENA_SHIFT 8 /* AIF1DRC2_NG_ENA */
+#define WM8994_AIF1DRC2_NG_ENA_WIDTH 1 /* AIF1DRC2_NG_ENA */
+#define WM8994_AIF1DRC2_SIG_DET_MODE 0x0080 /* AIF1DRC2_SIG_DET_MODE */
+#define WM8994_AIF1DRC2_SIG_DET_MODE_MASK 0x0080 /* AIF1DRC2_SIG_DET_MODE */
+#define WM8994_AIF1DRC2_SIG_DET_MODE_SHIFT 7 /* AIF1DRC2_SIG_DET_MODE */
+#define WM8994_AIF1DRC2_SIG_DET_MODE_WIDTH 1 /* AIF1DRC2_SIG_DET_MODE */
+#define WM8994_AIF1DRC2_SIG_DET 0x0040 /* AIF1DRC2_SIG_DET */
+#define WM8994_AIF1DRC2_SIG_DET_MASK 0x0040 /* AIF1DRC2_SIG_DET */
+#define WM8994_AIF1DRC2_SIG_DET_SHIFT 6 /* AIF1DRC2_SIG_DET */
+#define WM8994_AIF1DRC2_SIG_DET_WIDTH 1 /* AIF1DRC2_SIG_DET */
+#define WM8994_AIF1DRC2_KNEE2_OP_ENA 0x0020 /* AIF1DRC2_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC2_KNEE2_OP_ENA_MASK 0x0020 /* AIF1DRC2_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC2_KNEE2_OP_ENA_SHIFT 5 /* AIF1DRC2_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC2_KNEE2_OP_ENA_WIDTH 1 /* AIF1DRC2_KNEE2_OP_ENA */
+#define WM8994_AIF1DRC2_QR 0x0010 /* AIF1DRC2_QR */
+#define WM8994_AIF1DRC2_QR_MASK 0x0010 /* AIF1DRC2_QR */
+#define WM8994_AIF1DRC2_QR_SHIFT 4 /* AIF1DRC2_QR */
+#define WM8994_AIF1DRC2_QR_WIDTH 1 /* AIF1DRC2_QR */
+#define WM8994_AIF1DRC2_ANTICLIP 0x0008 /* AIF1DRC2_ANTICLIP */
+#define WM8994_AIF1DRC2_ANTICLIP_MASK 0x0008 /* AIF1DRC2_ANTICLIP */
+#define WM8994_AIF1DRC2_ANTICLIP_SHIFT 3 /* AIF1DRC2_ANTICLIP */
+#define WM8994_AIF1DRC2_ANTICLIP_WIDTH 1 /* AIF1DRC2_ANTICLIP */
+#define WM8994_AIF1DAC2_DRC_ENA 0x0004 /* AIF1DAC2_DRC_ENA */
+#define WM8994_AIF1DAC2_DRC_ENA_MASK 0x0004 /* AIF1DAC2_DRC_ENA */
+#define WM8994_AIF1DAC2_DRC_ENA_SHIFT 2 /* AIF1DAC2_DRC_ENA */
+#define WM8994_AIF1DAC2_DRC_ENA_WIDTH 1 /* AIF1DAC2_DRC_ENA */
+#define WM8994_AIF1ADC2L_DRC_ENA 0x0002 /* AIF1ADC2L_DRC_ENA */
+#define WM8994_AIF1ADC2L_DRC_ENA_MASK 0x0002 /* AIF1ADC2L_DRC_ENA */
+#define WM8994_AIF1ADC2L_DRC_ENA_SHIFT 1 /* AIF1ADC2L_DRC_ENA */
+#define WM8994_AIF1ADC2L_DRC_ENA_WIDTH 1 /* AIF1ADC2L_DRC_ENA */
+#define WM8994_AIF1ADC2R_DRC_ENA 0x0001 /* AIF1ADC2R_DRC_ENA */
+#define WM8994_AIF1ADC2R_DRC_ENA_MASK 0x0001 /* AIF1ADC2R_DRC_ENA */
+#define WM8994_AIF1ADC2R_DRC_ENA_SHIFT 0 /* AIF1ADC2R_DRC_ENA */
+#define WM8994_AIF1ADC2R_DRC_ENA_WIDTH 1 /* AIF1ADC2R_DRC_ENA */
+
+/*
+ * R1105 (0x451) - AIF1 DRC2 (2)
+ */
+#define WM8994_AIF1DRC2_ATK_MASK 0x1E00 /* AIF1DRC2_ATK - [12:9] */
+#define WM8994_AIF1DRC2_ATK_SHIFT 9 /* AIF1DRC2_ATK - [12:9] */
+#define WM8994_AIF1DRC2_ATK_WIDTH 4 /* AIF1DRC2_ATK - [12:9] */
+#define WM8994_AIF1DRC2_DCY_MASK 0x01E0 /* AIF1DRC2_DCY - [8:5] */
+#define WM8994_AIF1DRC2_DCY_SHIFT 5 /* AIF1DRC2_DCY - [8:5] */
+#define WM8994_AIF1DRC2_DCY_WIDTH 4 /* AIF1DRC2_DCY - [8:5] */
+#define WM8994_AIF1DRC2_MINGAIN_MASK 0x001C /* AIF1DRC2_MINGAIN - [4:2] */
+#define WM8994_AIF1DRC2_MINGAIN_SHIFT 2 /* AIF1DRC2_MINGAIN - [4:2] */
+#define WM8994_AIF1DRC2_MINGAIN_WIDTH 3 /* AIF1DRC2_MINGAIN - [4:2] */
+#define WM8994_AIF1DRC2_MAXGAIN_MASK 0x0003 /* AIF1DRC2_MAXGAIN - [1:0] */
+#define WM8994_AIF1DRC2_MAXGAIN_SHIFT 0 /* AIF1DRC2_MAXGAIN - [1:0] */
+#define WM8994_AIF1DRC2_MAXGAIN_WIDTH 2 /* AIF1DRC2_MAXGAIN - [1:0] */
+
+/*
+ * R1106 (0x452) - AIF1 DRC2 (3)
+ */
+#define WM8994_AIF1DRC2_NG_MINGAIN_MASK 0xF000 /* AIF1DRC2_NG_MINGAIN - [15:12] */
+#define WM8994_AIF1DRC2_NG_MINGAIN_SHIFT 12 /* AIF1DRC2_NG_MINGAIN - [15:12] */
+#define WM8994_AIF1DRC2_NG_MINGAIN_WIDTH 4 /* AIF1DRC2_NG_MINGAIN - [15:12] */
+#define WM8994_AIF1DRC2_NG_EXP_MASK 0x0C00 /* AIF1DRC2_NG_EXP - [11:10] */
+#define WM8994_AIF1DRC2_NG_EXP_SHIFT 10 /* AIF1DRC2_NG_EXP - [11:10] */
+#define WM8994_AIF1DRC2_NG_EXP_WIDTH 2 /* AIF1DRC2_NG_EXP - [11:10] */
+#define WM8994_AIF1DRC2_QR_THR_MASK 0x0300 /* AIF1DRC2_QR_THR - [9:8] */
+#define WM8994_AIF1DRC2_QR_THR_SHIFT 8 /* AIF1DRC2_QR_THR - [9:8] */
+#define WM8994_AIF1DRC2_QR_THR_WIDTH 2 /* AIF1DRC2_QR_THR - [9:8] */
+#define WM8994_AIF1DRC2_QR_DCY_MASK 0x00C0 /* AIF1DRC2_QR_DCY - [7:6] */
+#define WM8994_AIF1DRC2_QR_DCY_SHIFT 6 /* AIF1DRC2_QR_DCY - [7:6] */
+#define WM8994_AIF1DRC2_QR_DCY_WIDTH 2 /* AIF1DRC2_QR_DCY - [7:6] */
+#define WM8994_AIF1DRC2_HI_COMP_MASK 0x0038 /* AIF1DRC2_HI_COMP - [5:3] */
+#define WM8994_AIF1DRC2_HI_COMP_SHIFT 3 /* AIF1DRC2_HI_COMP - [5:3] */
+#define WM8994_AIF1DRC2_HI_COMP_WIDTH 3 /* AIF1DRC2_HI_COMP - [5:3] */
+#define WM8994_AIF1DRC2_LO_COMP_MASK 0x0007 /* AIF1DRC2_LO_COMP - [2:0] */
+#define WM8994_AIF1DRC2_LO_COMP_SHIFT 0 /* AIF1DRC2_LO_COMP - [2:0] */
+#define WM8994_AIF1DRC2_LO_COMP_WIDTH 3 /* AIF1DRC2_LO_COMP - [2:0] */
+
+/*
+ * R1107 (0x453) - AIF1 DRC2 (4)
+ */
+#define WM8994_AIF1DRC2_KNEE_IP_MASK 0x07E0 /* AIF1DRC2_KNEE_IP - [10:5] */
+#define WM8994_AIF1DRC2_KNEE_IP_SHIFT 5 /* AIF1DRC2_KNEE_IP - [10:5] */
+#define WM8994_AIF1DRC2_KNEE_IP_WIDTH 6 /* AIF1DRC2_KNEE_IP - [10:5] */
+#define WM8994_AIF1DRC2_KNEE_OP_MASK 0x001F /* AIF1DRC2_KNEE_OP - [4:0] */
+#define WM8994_AIF1DRC2_KNEE_OP_SHIFT 0 /* AIF1DRC2_KNEE_OP - [4:0] */
+#define WM8994_AIF1DRC2_KNEE_OP_WIDTH 5 /* AIF1DRC2_KNEE_OP - [4:0] */
+
+/*
+ * R1108 (0x454) - AIF1 DRC2 (5)
+ */
+#define WM8994_AIF1DRC2_KNEE2_IP_MASK 0x03E0 /* AIF1DRC2_KNEE2_IP - [9:5] */
+#define WM8994_AIF1DRC2_KNEE2_IP_SHIFT 5 /* AIF1DRC2_KNEE2_IP - [9:5] */
+#define WM8994_AIF1DRC2_KNEE2_IP_WIDTH 5 /* AIF1DRC2_KNEE2_IP - [9:5] */
+#define WM8994_AIF1DRC2_KNEE2_OP_MASK 0x001F /* AIF1DRC2_KNEE2_OP - [4:0] */
+#define WM8994_AIF1DRC2_KNEE2_OP_SHIFT 0 /* AIF1DRC2_KNEE2_OP - [4:0] */
+#define WM8994_AIF1DRC2_KNEE2_OP_WIDTH 5 /* AIF1DRC2_KNEE2_OP - [4:0] */
+
+/*
+ * R1152 (0x480) - AIF1 DAC1 EQ Gains (1)
+ */
+#define WM8994_AIF1DAC1_EQ_B1_GAIN_MASK 0xF800 /* AIF1DAC1_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF1DAC1_EQ_B1_GAIN_SHIFT 11 /* AIF1DAC1_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF1DAC1_EQ_B1_GAIN_WIDTH 5 /* AIF1DAC1_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF1DAC1_EQ_B2_GAIN_MASK 0x07C0 /* AIF1DAC1_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF1DAC1_EQ_B2_GAIN_SHIFT 6 /* AIF1DAC1_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF1DAC1_EQ_B2_GAIN_WIDTH 5 /* AIF1DAC1_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF1DAC1_EQ_B3_GAIN_MASK 0x003E /* AIF1DAC1_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF1DAC1_EQ_B3_GAIN_SHIFT 1 /* AIF1DAC1_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF1DAC1_EQ_B3_GAIN_WIDTH 5 /* AIF1DAC1_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF1DAC1_EQ_ENA 0x0001 /* AIF1DAC1_EQ_ENA */
+#define WM8994_AIF1DAC1_EQ_ENA_MASK 0x0001 /* AIF1DAC1_EQ_ENA */
+#define WM8994_AIF1DAC1_EQ_ENA_SHIFT 0 /* AIF1DAC1_EQ_ENA */
+#define WM8994_AIF1DAC1_EQ_ENA_WIDTH 1 /* AIF1DAC1_EQ_ENA */
+
+/*
+ * R1153 (0x481) - AIF1 DAC1 EQ Gains (2)
+ */
+#define WM8994_AIF1DAC1_EQ_B4_GAIN_MASK 0xF800 /* AIF1DAC1_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF1DAC1_EQ_B4_GAIN_SHIFT 11 /* AIF1DAC1_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF1DAC1_EQ_B4_GAIN_WIDTH 5 /* AIF1DAC1_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF1DAC1_EQ_B5_GAIN_MASK 0x07C0 /* AIF1DAC1_EQ_B5_GAIN - [10:6] */
+#define WM8994_AIF1DAC1_EQ_B5_GAIN_SHIFT 6 /* AIF1DAC1_EQ_B5_GAIN - [10:6] */
+#define WM8994_AIF1DAC1_EQ_B5_GAIN_WIDTH 5 /* AIF1DAC1_EQ_B5_GAIN - [10:6] */
+
+/*
+ * R1154 (0x482) - AIF1 DAC1 EQ Band 1 A
+ */
+#define WM8994_AIF1DAC1_EQ_B1_A_MASK 0xFFFF /* AIF1DAC1_EQ_B1_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B1_A_SHIFT 0 /* AIF1DAC1_EQ_B1_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B1_A_WIDTH 16 /* AIF1DAC1_EQ_B1_A - [15:0] */
+
+/*
+ * R1155 (0x483) - AIF1 DAC1 EQ Band 1 B
+ */
+#define WM8994_AIF1DAC1_EQ_B1_B_MASK 0xFFFF /* AIF1DAC1_EQ_B1_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B1_B_SHIFT 0 /* AIF1DAC1_EQ_B1_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B1_B_WIDTH 16 /* AIF1DAC1_EQ_B1_B - [15:0] */
+
+/*
+ * R1156 (0x484) - AIF1 DAC1 EQ Band 1 PG
+ */
+#define WM8994_AIF1DAC1_EQ_B1_PG_MASK 0xFFFF /* AIF1DAC1_EQ_B1_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B1_PG_SHIFT 0 /* AIF1DAC1_EQ_B1_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B1_PG_WIDTH 16 /* AIF1DAC1_EQ_B1_PG - [15:0] */
+
+/*
+ * R1157 (0x485) - AIF1 DAC1 EQ Band 2 A
+ */
+#define WM8994_AIF1DAC1_EQ_B2_A_MASK 0xFFFF /* AIF1DAC1_EQ_B2_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_A_SHIFT 0 /* AIF1DAC1_EQ_B2_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_A_WIDTH 16 /* AIF1DAC1_EQ_B2_A - [15:0] */
+
+/*
+ * R1158 (0x486) - AIF1 DAC1 EQ Band 2 B
+ */
+#define WM8994_AIF1DAC1_EQ_B2_B_MASK 0xFFFF /* AIF1DAC1_EQ_B2_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_B_SHIFT 0 /* AIF1DAC1_EQ_B2_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_B_WIDTH 16 /* AIF1DAC1_EQ_B2_B - [15:0] */
+
+/*
+ * R1159 (0x487) - AIF1 DAC1 EQ Band 2 C
+ */
+#define WM8994_AIF1DAC1_EQ_B2_C_MASK 0xFFFF /* AIF1DAC1_EQ_B2_C - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_C_SHIFT 0 /* AIF1DAC1_EQ_B2_C - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_C_WIDTH 16 /* AIF1DAC1_EQ_B2_C - [15:0] */
+
+/*
+ * R1160 (0x488) - AIF1 DAC1 EQ Band 2 PG
+ */
+#define WM8994_AIF1DAC1_EQ_B2_PG_MASK 0xFFFF /* AIF1DAC1_EQ_B2_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_PG_SHIFT 0 /* AIF1DAC1_EQ_B2_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B2_PG_WIDTH 16 /* AIF1DAC1_EQ_B2_PG - [15:0] */
+
+/*
+ * R1161 (0x489) - AIF1 DAC1 EQ Band 3 A
+ */
+#define WM8994_AIF1DAC1_EQ_B3_A_MASK 0xFFFF /* AIF1DAC1_EQ_B3_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_A_SHIFT 0 /* AIF1DAC1_EQ_B3_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_A_WIDTH 16 /* AIF1DAC1_EQ_B3_A - [15:0] */
+
+/*
+ * R1162 (0x48A) - AIF1 DAC1 EQ Band 3 B
+ */
+#define WM8994_AIF1DAC1_EQ_B3_B_MASK 0xFFFF /* AIF1DAC1_EQ_B3_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_B_SHIFT 0 /* AIF1DAC1_EQ_B3_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_B_WIDTH 16 /* AIF1DAC1_EQ_B3_B - [15:0] */
+
+/*
+ * R1163 (0x48B) - AIF1 DAC1 EQ Band 3 C
+ */
+#define WM8994_AIF1DAC1_EQ_B3_C_MASK 0xFFFF /* AIF1DAC1_EQ_B3_C - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_C_SHIFT 0 /* AIF1DAC1_EQ_B3_C - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_C_WIDTH 16 /* AIF1DAC1_EQ_B3_C - [15:0] */
+
+/*
+ * R1164 (0x48C) - AIF1 DAC1 EQ Band 3 PG
+ */
+#define WM8994_AIF1DAC1_EQ_B3_PG_MASK 0xFFFF /* AIF1DAC1_EQ_B3_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_PG_SHIFT 0 /* AIF1DAC1_EQ_B3_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B3_PG_WIDTH 16 /* AIF1DAC1_EQ_B3_PG - [15:0] */
+
+/*
+ * R1165 (0x48D) - AIF1 DAC1 EQ Band 4 A
+ */
+#define WM8994_AIF1DAC1_EQ_B4_A_MASK 0xFFFF /* AIF1DAC1_EQ_B4_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_A_SHIFT 0 /* AIF1DAC1_EQ_B4_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_A_WIDTH 16 /* AIF1DAC1_EQ_B4_A - [15:0] */
+
+/*
+ * R1166 (0x48E) - AIF1 DAC1 EQ Band 4 B
+ */
+#define WM8994_AIF1DAC1_EQ_B4_B_MASK 0xFFFF /* AIF1DAC1_EQ_B4_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_B_SHIFT 0 /* AIF1DAC1_EQ_B4_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_B_WIDTH 16 /* AIF1DAC1_EQ_B4_B - [15:0] */
+
+/*
+ * R1167 (0x48F) - AIF1 DAC1 EQ Band 4 C
+ */
+#define WM8994_AIF1DAC1_EQ_B4_C_MASK 0xFFFF /* AIF1DAC1_EQ_B4_C - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_C_SHIFT 0 /* AIF1DAC1_EQ_B4_C - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_C_WIDTH 16 /* AIF1DAC1_EQ_B4_C - [15:0] */
+
+/*
+ * R1168 (0x490) - AIF1 DAC1 EQ Band 4 PG
+ */
+#define WM8994_AIF1DAC1_EQ_B4_PG_MASK 0xFFFF /* AIF1DAC1_EQ_B4_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_PG_SHIFT 0 /* AIF1DAC1_EQ_B4_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B4_PG_WIDTH 16 /* AIF1DAC1_EQ_B4_PG - [15:0] */
+
+/*
+ * R1169 (0x491) - AIF1 DAC1 EQ Band 5 A
+ */
+#define WM8994_AIF1DAC1_EQ_B5_A_MASK 0xFFFF /* AIF1DAC1_EQ_B5_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B5_A_SHIFT 0 /* AIF1DAC1_EQ_B5_A - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B5_A_WIDTH 16 /* AIF1DAC1_EQ_B5_A - [15:0] */
+
+/*
+ * R1170 (0x492) - AIF1 DAC1 EQ Band 5 B
+ */
+#define WM8994_AIF1DAC1_EQ_B5_B_MASK 0xFFFF /* AIF1DAC1_EQ_B5_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B5_B_SHIFT 0 /* AIF1DAC1_EQ_B5_B - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B5_B_WIDTH 16 /* AIF1DAC1_EQ_B5_B - [15:0] */
+
+/*
+ * R1171 (0x493) - AIF1 DAC1 EQ Band 5 PG
+ */
+#define WM8994_AIF1DAC1_EQ_B5_PG_MASK 0xFFFF /* AIF1DAC1_EQ_B5_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B5_PG_SHIFT 0 /* AIF1DAC1_EQ_B5_PG - [15:0] */
+#define WM8994_AIF1DAC1_EQ_B5_PG_WIDTH 16 /* AIF1DAC1_EQ_B5_PG - [15:0] */
+
+/*
+ * R1184 (0x4A0) - AIF1 DAC2 EQ Gains (1)
+ */
+#define WM8994_AIF1DAC2_EQ_B1_GAIN_MASK 0xF800 /* AIF1DAC2_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF1DAC2_EQ_B1_GAIN_SHIFT 11 /* AIF1DAC2_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF1DAC2_EQ_B1_GAIN_WIDTH 5 /* AIF1DAC2_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF1DAC2_EQ_B2_GAIN_MASK 0x07C0 /* AIF1DAC2_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF1DAC2_EQ_B2_GAIN_SHIFT 6 /* AIF1DAC2_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF1DAC2_EQ_B2_GAIN_WIDTH 5 /* AIF1DAC2_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF1DAC2_EQ_B3_GAIN_MASK 0x003E /* AIF1DAC2_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF1DAC2_EQ_B3_GAIN_SHIFT 1 /* AIF1DAC2_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF1DAC2_EQ_B3_GAIN_WIDTH 5 /* AIF1DAC2_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF1DAC2_EQ_ENA 0x0001 /* AIF1DAC2_EQ_ENA */
+#define WM8994_AIF1DAC2_EQ_ENA_MASK 0x0001 /* AIF1DAC2_EQ_ENA */
+#define WM8994_AIF1DAC2_EQ_ENA_SHIFT 0 /* AIF1DAC2_EQ_ENA */
+#define WM8994_AIF1DAC2_EQ_ENA_WIDTH 1 /* AIF1DAC2_EQ_ENA */
+
+/*
+ * R1185 (0x4A1) - AIF1 DAC2 EQ Gains (2)
+ */
+#define WM8994_AIF1DAC2_EQ_B4_GAIN_MASK 0xF800 /* AIF1DAC2_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF1DAC2_EQ_B4_GAIN_SHIFT 11 /* AIF1DAC2_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF1DAC2_EQ_B4_GAIN_WIDTH 5 /* AIF1DAC2_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF1DAC2_EQ_B5_GAIN_MASK 0x07C0 /* AIF1DAC2_EQ_B5_GAIN - [10:6] */
+#define WM8994_AIF1DAC2_EQ_B5_GAIN_SHIFT 6 /* AIF1DAC2_EQ_B5_GAIN - [10:6] */
+#define WM8994_AIF1DAC2_EQ_B5_GAIN_WIDTH 5 /* AIF1DAC2_EQ_B5_GAIN - [10:6] */
+
+/*
+ * R1186 (0x4A2) - AIF1 DAC2 EQ Band 1 A
+ */
+#define WM8994_AIF1DAC2_EQ_B1_A_MASK 0xFFFF /* AIF1DAC2_EQ_B1_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B1_A_SHIFT 0 /* AIF1DAC2_EQ_B1_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B1_A_WIDTH 16 /* AIF1DAC2_EQ_B1_A - [15:0] */
+
+/*
+ * R1187 (0x4A3) - AIF1 DAC2 EQ Band 1 B
+ */
+#define WM8994_AIF1DAC2_EQ_B1_B_MASK 0xFFFF /* AIF1DAC2_EQ_B1_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B1_B_SHIFT 0 /* AIF1DAC2_EQ_B1_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B1_B_WIDTH 16 /* AIF1DAC2_EQ_B1_B - [15:0] */
+
+/*
+ * R1188 (0x4A4) - AIF1 DAC2 EQ Band 1 PG
+ */
+#define WM8994_AIF1DAC2_EQ_B1_PG_MASK 0xFFFF /* AIF1DAC2_EQ_B1_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B1_PG_SHIFT 0 /* AIF1DAC2_EQ_B1_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B1_PG_WIDTH 16 /* AIF1DAC2_EQ_B1_PG - [15:0] */
+
+/*
+ * R1189 (0x4A5) - AIF1 DAC2 EQ Band 2 A
+ */
+#define WM8994_AIF1DAC2_EQ_B2_A_MASK 0xFFFF /* AIF1DAC2_EQ_B2_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_A_SHIFT 0 /* AIF1DAC2_EQ_B2_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_A_WIDTH 16 /* AIF1DAC2_EQ_B2_A - [15:0] */
+
+/*
+ * R1190 (0x4A6) - AIF1 DAC2 EQ Band 2 B
+ */
+#define WM8994_AIF1DAC2_EQ_B2_B_MASK 0xFFFF /* AIF1DAC2_EQ_B2_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_B_SHIFT 0 /* AIF1DAC2_EQ_B2_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_B_WIDTH 16 /* AIF1DAC2_EQ_B2_B - [15:0] */
+
+/*
+ * R1191 (0x4A7) - AIF1 DAC2 EQ Band 2 C
+ */
+#define WM8994_AIF1DAC2_EQ_B2_C_MASK 0xFFFF /* AIF1DAC2_EQ_B2_C - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_C_SHIFT 0 /* AIF1DAC2_EQ_B2_C - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_C_WIDTH 16 /* AIF1DAC2_EQ_B2_C - [15:0] */
+
+/*
+ * R1192 (0x4A8) - AIF1 DAC2 EQ Band 2 PG
+ */
+#define WM8994_AIF1DAC2_EQ_B2_PG_MASK 0xFFFF /* AIF1DAC2_EQ_B2_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_PG_SHIFT 0 /* AIF1DAC2_EQ_B2_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B2_PG_WIDTH 16 /* AIF1DAC2_EQ_B2_PG - [15:0] */
+
+/*
+ * R1193 (0x4A9) - AIF1 DAC2 EQ Band 3 A
+ */
+#define WM8994_AIF1DAC2_EQ_B3_A_MASK 0xFFFF /* AIF1DAC2_EQ_B3_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_A_SHIFT 0 /* AIF1DAC2_EQ_B3_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_A_WIDTH 16 /* AIF1DAC2_EQ_B3_A - [15:0] */
+
+/*
+ * R1194 (0x4AA) - AIF1 DAC2 EQ Band 3 B
+ */
+#define WM8994_AIF1DAC2_EQ_B3_B_MASK 0xFFFF /* AIF1DAC2_EQ_B3_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_B_SHIFT 0 /* AIF1DAC2_EQ_B3_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_B_WIDTH 16 /* AIF1DAC2_EQ_B3_B - [15:0] */
+
+/*
+ * R1195 (0x4AB) - AIF1 DAC2 EQ Band 3 C
+ */
+#define WM8994_AIF1DAC2_EQ_B3_C_MASK 0xFFFF /* AIF1DAC2_EQ_B3_C - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_C_SHIFT 0 /* AIF1DAC2_EQ_B3_C - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_C_WIDTH 16 /* AIF1DAC2_EQ_B3_C - [15:0] */
+
+/*
+ * R1196 (0x4AC) - AIF1 DAC2 EQ Band 3 PG
+ */
+#define WM8994_AIF1DAC2_EQ_B3_PG_MASK 0xFFFF /* AIF1DAC2_EQ_B3_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_PG_SHIFT 0 /* AIF1DAC2_EQ_B3_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B3_PG_WIDTH 16 /* AIF1DAC2_EQ_B3_PG - [15:0] */
+
+/*
+ * R1197 (0x4AD) - AIF1 DAC2 EQ Band 4 A
+ */
+#define WM8994_AIF1DAC2_EQ_B4_A_MASK 0xFFFF /* AIF1DAC2_EQ_B4_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_A_SHIFT 0 /* AIF1DAC2_EQ_B4_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_A_WIDTH 16 /* AIF1DAC2_EQ_B4_A - [15:0] */
+
+/*
+ * R1198 (0x4AE) - AIF1 DAC2 EQ Band 4 B
+ */
+#define WM8994_AIF1DAC2_EQ_B4_B_MASK 0xFFFF /* AIF1DAC2_EQ_B4_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_B_SHIFT 0 /* AIF1DAC2_EQ_B4_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_B_WIDTH 16 /* AIF1DAC2_EQ_B4_B - [15:0] */
+
+/*
+ * R1199 (0x4AF) - AIF1 DAC2 EQ Band 4 C
+ */
+#define WM8994_AIF1DAC2_EQ_B4_C_MASK 0xFFFF /* AIF1DAC2_EQ_B4_C - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_C_SHIFT 0 /* AIF1DAC2_EQ_B4_C - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_C_WIDTH 16 /* AIF1DAC2_EQ_B4_C - [15:0] */
+
+/*
+ * R1200 (0x4B0) - AIF1 DAC2 EQ Band 4 PG
+ */
+#define WM8994_AIF1DAC2_EQ_B4_PG_MASK 0xFFFF /* AIF1DAC2_EQ_B4_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_PG_SHIFT 0 /* AIF1DAC2_EQ_B4_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B4_PG_WIDTH 16 /* AIF1DAC2_EQ_B4_PG - [15:0] */
+
+/*
+ * R1201 (0x4B1) - AIF1 DAC2 EQ Band 5 A
+ */
+#define WM8994_AIF1DAC2_EQ_B5_A_MASK 0xFFFF /* AIF1DAC2_EQ_B5_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B5_A_SHIFT 0 /* AIF1DAC2_EQ_B5_A - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B5_A_WIDTH 16 /* AIF1DAC2_EQ_B5_A - [15:0] */
+
+/*
+ * R1202 (0x4B2) - AIF1 DAC2 EQ Band 5 B
+ */
+#define WM8994_AIF1DAC2_EQ_B5_B_MASK 0xFFFF /* AIF1DAC2_EQ_B5_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B5_B_SHIFT 0 /* AIF1DAC2_EQ_B5_B - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B5_B_WIDTH 16 /* AIF1DAC2_EQ_B5_B - [15:0] */
+
+/*
+ * R1203 (0x4B3) - AIF1 DAC2 EQ Band 5 PG
+ */
+#define WM8994_AIF1DAC2_EQ_B5_PG_MASK 0xFFFF /* AIF1DAC2_EQ_B5_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B5_PG_SHIFT 0 /* AIF1DAC2_EQ_B5_PG - [15:0] */
+#define WM8994_AIF1DAC2_EQ_B5_PG_WIDTH 16 /* AIF1DAC2_EQ_B5_PG - [15:0] */
+
+/*
+ * R1280 (0x500) - AIF2 ADC Left Volume
+ */
+#define WM8994_AIF2ADC_VU 0x0100 /* AIF2ADC_VU */
+#define WM8994_AIF2ADC_VU_MASK 0x0100 /* AIF2ADC_VU */
+#define WM8994_AIF2ADC_VU_SHIFT 8 /* AIF2ADC_VU */
+#define WM8994_AIF2ADC_VU_WIDTH 1 /* AIF2ADC_VU */
+#define WM8994_AIF2ADCL_VOL_MASK 0x00FF /* AIF2ADCL_VOL - [7:0] */
+#define WM8994_AIF2ADCL_VOL_SHIFT 0 /* AIF2ADCL_VOL - [7:0] */
+#define WM8994_AIF2ADCL_VOL_WIDTH 8 /* AIF2ADCL_VOL - [7:0] */
+
+/*
+ * R1281 (0x501) - AIF2 ADC Right Volume
+ */
+#define WM8994_AIF2ADC_VU 0x0100 /* AIF2ADC_VU */
+#define WM8994_AIF2ADC_VU_MASK 0x0100 /* AIF2ADC_VU */
+#define WM8994_AIF2ADC_VU_SHIFT 8 /* AIF2ADC_VU */
+#define WM8994_AIF2ADC_VU_WIDTH 1 /* AIF2ADC_VU */
+#define WM8994_AIF2ADCR_VOL_MASK 0x00FF /* AIF2ADCR_VOL - [7:0] */
+#define WM8994_AIF2ADCR_VOL_SHIFT 0 /* AIF2ADCR_VOL - [7:0] */
+#define WM8994_AIF2ADCR_VOL_WIDTH 8 /* AIF2ADCR_VOL - [7:0] */
+
+/*
+ * R1282 (0x502) - AIF2 DAC Left Volume
+ */
+#define WM8994_AIF2DAC_VU 0x0100 /* AIF2DAC_VU */
+#define WM8994_AIF2DAC_VU_MASK 0x0100 /* AIF2DAC_VU */
+#define WM8994_AIF2DAC_VU_SHIFT 8 /* AIF2DAC_VU */
+#define WM8994_AIF2DAC_VU_WIDTH 1 /* AIF2DAC_VU */
+#define WM8994_AIF2DACL_VOL_MASK 0x00FF /* AIF2DACL_VOL - [7:0] */
+#define WM8994_AIF2DACL_VOL_SHIFT 0 /* AIF2DACL_VOL - [7:0] */
+#define WM8994_AIF2DACL_VOL_WIDTH 8 /* AIF2DACL_VOL - [7:0] */
+
+/*
+ * R1283 (0x503) - AIF2 DAC Right Volume
+ */
+#define WM8994_AIF2DAC_VU 0x0100 /* AIF2DAC_VU */
+#define WM8994_AIF2DAC_VU_MASK 0x0100 /* AIF2DAC_VU */
+#define WM8994_AIF2DAC_VU_SHIFT 8 /* AIF2DAC_VU */
+#define WM8994_AIF2DAC_VU_WIDTH 1 /* AIF2DAC_VU */
+#define WM8994_AIF2DACR_VOL_MASK 0x00FF /* AIF2DACR_VOL - [7:0] */
+#define WM8994_AIF2DACR_VOL_SHIFT 0 /* AIF2DACR_VOL - [7:0] */
+#define WM8994_AIF2DACR_VOL_WIDTH 8 /* AIF2DACR_VOL - [7:0] */
+
+/*
+ * R1296 (0x510) - AIF2 ADC Filters
+ */
+#define WM8994_AIF2ADC_4FS 0x8000 /* AIF2ADC_4FS */
+#define WM8994_AIF2ADC_4FS_MASK 0x8000 /* AIF2ADC_4FS */
+#define WM8994_AIF2ADC_4FS_SHIFT 15 /* AIF2ADC_4FS */
+#define WM8994_AIF2ADC_4FS_WIDTH 1 /* AIF2ADC_4FS */
+#define WM8994_AIF2ADC_HPF_CUT_MASK 0x6000 /* AIF2ADC_HPF_CUT - [14:13] */
+#define WM8994_AIF2ADC_HPF_CUT_SHIFT 13 /* AIF2ADC_HPF_CUT - [14:13] */
+#define WM8994_AIF2ADC_HPF_CUT_WIDTH 2 /* AIF2ADC_HPF_CUT - [14:13] */
+#define WM8994_AIF2ADCL_HPF 0x1000 /* AIF2ADCL_HPF */
+#define WM8994_AIF2ADCL_HPF_MASK 0x1000 /* AIF2ADCL_HPF */
+#define WM8994_AIF2ADCL_HPF_SHIFT 12 /* AIF2ADCL_HPF */
+#define WM8994_AIF2ADCL_HPF_WIDTH 1 /* AIF2ADCL_HPF */
+#define WM8994_AIF2ADCR_HPF 0x0800 /* AIF2ADCR_HPF */
+#define WM8994_AIF2ADCR_HPF_MASK 0x0800 /* AIF2ADCR_HPF */
+#define WM8994_AIF2ADCR_HPF_SHIFT 11 /* AIF2ADCR_HPF */
+#define WM8994_AIF2ADCR_HPF_WIDTH 1 /* AIF2ADCR_HPF */
+
+/*
+ * R1312 (0x520) - AIF2 DAC Filters (1)
+ */
+#define WM8994_AIF2DAC_MUTE 0x0200 /* AIF2DAC_MUTE */
+#define WM8994_AIF2DAC_MUTE_MASK 0x0200 /* AIF2DAC_MUTE */
+#define WM8994_AIF2DAC_MUTE_SHIFT 9 /* AIF2DAC_MUTE */
+#define WM8994_AIF2DAC_MUTE_WIDTH 1 /* AIF2DAC_MUTE */
+#define WM8994_AIF2DAC_MONO 0x0080 /* AIF2DAC_MONO */
+#define WM8994_AIF2DAC_MONO_MASK 0x0080 /* AIF2DAC_MONO */
+#define WM8994_AIF2DAC_MONO_SHIFT 7 /* AIF2DAC_MONO */
+#define WM8994_AIF2DAC_MONO_WIDTH 1 /* AIF2DAC_MONO */
+#define WM8994_AIF2DAC_MUTERATE 0x0020 /* AIF2DAC_MUTERATE */
+#define WM8994_AIF2DAC_MUTERATE_MASK 0x0020 /* AIF2DAC_MUTERATE */
+#define WM8994_AIF2DAC_MUTERATE_SHIFT 5 /* AIF2DAC_MUTERATE */
+#define WM8994_AIF2DAC_MUTERATE_WIDTH 1 /* AIF2DAC_MUTERATE */
+#define WM8994_AIF2DAC_UNMUTE_RAMP 0x0010 /* AIF2DAC_UNMUTE_RAMP */
+#define WM8994_AIF2DAC_UNMUTE_RAMP_MASK 0x0010 /* AIF2DAC_UNMUTE_RAMP */
+#define WM8994_AIF2DAC_UNMUTE_RAMP_SHIFT 4 /* AIF2DAC_UNMUTE_RAMP */
+#define WM8994_AIF2DAC_UNMUTE_RAMP_WIDTH 1 /* AIF2DAC_UNMUTE_RAMP */
+#define WM8994_AIF2DAC_DEEMP_MASK 0x0006 /* AIF2DAC_DEEMP - [2:1] */
+#define WM8994_AIF2DAC_DEEMP_SHIFT 1 /* AIF2DAC_DEEMP - [2:1] */
+#define WM8994_AIF2DAC_DEEMP_WIDTH 2 /* AIF2DAC_DEEMP - [2:1] */
+
+/*
+ * R1313 (0x521) - AIF2 DAC Filters (2)
+ */
+#define WM8994_AIF2DAC_3D_GAIN_MASK 0x3E00 /* AIF2DAC_3D_GAIN - [13:9] */
+#define WM8994_AIF2DAC_3D_GAIN_SHIFT 9 /* AIF2DAC_3D_GAIN - [13:9] */
+#define WM8994_AIF2DAC_3D_GAIN_WIDTH 5 /* AIF2DAC_3D_GAIN - [13:9] */
+#define WM8994_AIF2DAC_3D_ENA 0x0100 /* AIF2DAC_3D_ENA */
+#define WM8994_AIF2DAC_3D_ENA_MASK 0x0100 /* AIF2DAC_3D_ENA */
+#define WM8994_AIF2DAC_3D_ENA_SHIFT 8 /* AIF2DAC_3D_ENA */
+#define WM8994_AIF2DAC_3D_ENA_WIDTH 1 /* AIF2DAC_3D_ENA */
+
+/*
+ * R1344 (0x540) - AIF2 DRC (1)
+ */
+#define WM8994_AIF2DRC_SIG_DET_RMS_MASK 0xF800 /* AIF2DRC_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF2DRC_SIG_DET_RMS_SHIFT 11 /* AIF2DRC_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF2DRC_SIG_DET_RMS_WIDTH 5 /* AIF2DRC_SIG_DET_RMS - [15:11] */
+#define WM8994_AIF2DRC_SIG_DET_PK_MASK 0x0600 /* AIF2DRC_SIG_DET_PK - [10:9] */
+#define WM8994_AIF2DRC_SIG_DET_PK_SHIFT 9 /* AIF2DRC_SIG_DET_PK - [10:9] */
+#define WM8994_AIF2DRC_SIG_DET_PK_WIDTH 2 /* AIF2DRC_SIG_DET_PK - [10:9] */
+#define WM8994_AIF2DRC_NG_ENA 0x0100 /* AIF2DRC_NG_ENA */
+#define WM8994_AIF2DRC_NG_ENA_MASK 0x0100 /* AIF2DRC_NG_ENA */
+#define WM8994_AIF2DRC_NG_ENA_SHIFT 8 /* AIF2DRC_NG_ENA */
+#define WM8994_AIF2DRC_NG_ENA_WIDTH 1 /* AIF2DRC_NG_ENA */
+#define WM8994_AIF2DRC_SIG_DET_MODE 0x0080 /* AIF2DRC_SIG_DET_MODE */
+#define WM8994_AIF2DRC_SIG_DET_MODE_MASK 0x0080 /* AIF2DRC_SIG_DET_MODE */
+#define WM8994_AIF2DRC_SIG_DET_MODE_SHIFT 7 /* AIF2DRC_SIG_DET_MODE */
+#define WM8994_AIF2DRC_SIG_DET_MODE_WIDTH 1 /* AIF2DRC_SIG_DET_MODE */
+#define WM8994_AIF2DRC_SIG_DET 0x0040 /* AIF2DRC_SIG_DET */
+#define WM8994_AIF2DRC_SIG_DET_MASK 0x0040 /* AIF2DRC_SIG_DET */
+#define WM8994_AIF2DRC_SIG_DET_SHIFT 6 /* AIF2DRC_SIG_DET */
+#define WM8994_AIF2DRC_SIG_DET_WIDTH 1 /* AIF2DRC_SIG_DET */
+#define WM8994_AIF2DRC_KNEE2_OP_ENA 0x0020 /* AIF2DRC_KNEE2_OP_ENA */
+#define WM8994_AIF2DRC_KNEE2_OP_ENA_MASK 0x0020 /* AIF2DRC_KNEE2_OP_ENA */
+#define WM8994_AIF2DRC_KNEE2_OP_ENA_SHIFT 5 /* AIF2DRC_KNEE2_OP_ENA */
+#define WM8994_AIF2DRC_KNEE2_OP_ENA_WIDTH 1 /* AIF2DRC_KNEE2_OP_ENA */
+#define WM8994_AIF2DRC_QR 0x0010 /* AIF2DRC_QR */
+#define WM8994_AIF2DRC_QR_MASK 0x0010 /* AIF2DRC_QR */
+#define WM8994_AIF2DRC_QR_SHIFT 4 /* AIF2DRC_QR */
+#define WM8994_AIF2DRC_QR_WIDTH 1 /* AIF2DRC_QR */
+#define WM8994_AIF2DRC_ANTICLIP 0x0008 /* AIF2DRC_ANTICLIP */
+#define WM8994_AIF2DRC_ANTICLIP_MASK 0x0008 /* AIF2DRC_ANTICLIP */
+#define WM8994_AIF2DRC_ANTICLIP_SHIFT 3 /* AIF2DRC_ANTICLIP */
+#define WM8994_AIF2DRC_ANTICLIP_WIDTH 1 /* AIF2DRC_ANTICLIP */
+#define WM8994_AIF2DAC_DRC_ENA 0x0004 /* AIF2DAC_DRC_ENA */
+#define WM8994_AIF2DAC_DRC_ENA_MASK 0x0004 /* AIF2DAC_DRC_ENA */
+#define WM8994_AIF2DAC_DRC_ENA_SHIFT 2 /* AIF2DAC_DRC_ENA */
+#define WM8994_AIF2DAC_DRC_ENA_WIDTH 1 /* AIF2DAC_DRC_ENA */
+#define WM8994_AIF2ADCL_DRC_ENA 0x0002 /* AIF2ADCL_DRC_ENA */
+#define WM8994_AIF2ADCL_DRC_ENA_MASK 0x0002 /* AIF2ADCL_DRC_ENA */
+#define WM8994_AIF2ADCL_DRC_ENA_SHIFT 1 /* AIF2ADCL_DRC_ENA */
+#define WM8994_AIF2ADCL_DRC_ENA_WIDTH 1 /* AIF2ADCL_DRC_ENA */
+#define WM8994_AIF2ADCR_DRC_ENA 0x0001 /* AIF2ADCR_DRC_ENA */
+#define WM8994_AIF2ADCR_DRC_ENA_MASK 0x0001 /* AIF2ADCR_DRC_ENA */
+#define WM8994_AIF2ADCR_DRC_ENA_SHIFT 0 /* AIF2ADCR_DRC_ENA */
+#define WM8994_AIF2ADCR_DRC_ENA_WIDTH 1 /* AIF2ADCR_DRC_ENA */
+
+/*
+ * R1345 (0x541) - AIF2 DRC (2)
+ */
+#define WM8994_AIF2DRC_ATK_MASK 0x1E00 /* AIF2DRC_ATK - [12:9] */
+#define WM8994_AIF2DRC_ATK_SHIFT 9 /* AIF2DRC_ATK - [12:9] */
+#define WM8994_AIF2DRC_ATK_WIDTH 4 /* AIF2DRC_ATK - [12:9] */
+#define WM8994_AIF2DRC_DCY_MASK 0x01E0 /* AIF2DRC_DCY - [8:5] */
+#define WM8994_AIF2DRC_DCY_SHIFT 5 /* AIF2DRC_DCY - [8:5] */
+#define WM8994_AIF2DRC_DCY_WIDTH 4 /* AIF2DRC_DCY - [8:5] */
+#define WM8994_AIF2DRC_MINGAIN_MASK 0x001C /* AIF2DRC_MINGAIN - [4:2] */
+#define WM8994_AIF2DRC_MINGAIN_SHIFT 2 /* AIF2DRC_MINGAIN - [4:2] */
+#define WM8994_AIF2DRC_MINGAIN_WIDTH 3 /* AIF2DRC_MINGAIN - [4:2] */
+#define WM8994_AIF2DRC_MAXGAIN_MASK 0x0003 /* AIF2DRC_MAXGAIN - [1:0] */
+#define WM8994_AIF2DRC_MAXGAIN_SHIFT 0 /* AIF2DRC_MAXGAIN - [1:0] */
+#define WM8994_AIF2DRC_MAXGAIN_WIDTH 2 /* AIF2DRC_MAXGAIN - [1:0] */
+
+/*
+ * R1346 (0x542) - AIF2 DRC (3)
+ */
+#define WM8994_AIF2DRC_NG_MINGAIN_MASK 0xF000 /* AIF2DRC_NG_MINGAIN - [15:12] */
+#define WM8994_AIF2DRC_NG_MINGAIN_SHIFT 12 /* AIF2DRC_NG_MINGAIN - [15:12] */
+#define WM8994_AIF2DRC_NG_MINGAIN_WIDTH 4 /* AIF2DRC_NG_MINGAIN - [15:12] */
+#define WM8994_AIF2DRC_NG_EXP_MASK 0x0C00 /* AIF2DRC_NG_EXP - [11:10] */
+#define WM8994_AIF2DRC_NG_EXP_SHIFT 10 /* AIF2DRC_NG_EXP - [11:10] */
+#define WM8994_AIF2DRC_NG_EXP_WIDTH 2 /* AIF2DRC_NG_EXP - [11:10] */
+#define WM8994_AIF2DRC_QR_THR_MASK 0x0300 /* AIF2DRC_QR_THR - [9:8] */
+#define WM8994_AIF2DRC_QR_THR_SHIFT 8 /* AIF2DRC_QR_THR - [9:8] */
+#define WM8994_AIF2DRC_QR_THR_WIDTH 2 /* AIF2DRC_QR_THR - [9:8] */
+#define WM8994_AIF2DRC_QR_DCY_MASK 0x00C0 /* AIF2DRC_QR_DCY - [7:6] */
+#define WM8994_AIF2DRC_QR_DCY_SHIFT 6 /* AIF2DRC_QR_DCY - [7:6] */
+#define WM8994_AIF2DRC_QR_DCY_WIDTH 2 /* AIF2DRC_QR_DCY - [7:6] */
+#define WM8994_AIF2DRC_HI_COMP_MASK 0x0038 /* AIF2DRC_HI_COMP - [5:3] */
+#define WM8994_AIF2DRC_HI_COMP_SHIFT 3 /* AIF2DRC_HI_COMP - [5:3] */
+#define WM8994_AIF2DRC_HI_COMP_WIDTH 3 /* AIF2DRC_HI_COMP - [5:3] */
+#define WM8994_AIF2DRC_LO_COMP_MASK 0x0007 /* AIF2DRC_LO_COMP - [2:0] */
+#define WM8994_AIF2DRC_LO_COMP_SHIFT 0 /* AIF2DRC_LO_COMP - [2:0] */
+#define WM8994_AIF2DRC_LO_COMP_WIDTH 3 /* AIF2DRC_LO_COMP - [2:0] */
+
+/*
+ * R1347 (0x543) - AIF2 DRC (4)
+ */
+#define WM8994_AIF2DRC_KNEE_IP_MASK 0x07E0 /* AIF2DRC_KNEE_IP - [10:5] */
+#define WM8994_AIF2DRC_KNEE_IP_SHIFT 5 /* AIF2DRC_KNEE_IP - [10:5] */
+#define WM8994_AIF2DRC_KNEE_IP_WIDTH 6 /* AIF2DRC_KNEE_IP - [10:5] */
+#define WM8994_AIF2DRC_KNEE_OP_MASK 0x001F /* AIF2DRC_KNEE_OP - [4:0] */
+#define WM8994_AIF2DRC_KNEE_OP_SHIFT 0 /* AIF2DRC_KNEE_OP - [4:0] */
+#define WM8994_AIF2DRC_KNEE_OP_WIDTH 5 /* AIF2DRC_KNEE_OP - [4:0] */
+
+/*
+ * R1348 (0x544) - AIF2 DRC (5)
+ */
+#define WM8994_AIF2DRC_KNEE2_IP_MASK 0x03E0 /* AIF2DRC_KNEE2_IP - [9:5] */
+#define WM8994_AIF2DRC_KNEE2_IP_SHIFT 5 /* AIF2DRC_KNEE2_IP - [9:5] */
+#define WM8994_AIF2DRC_KNEE2_IP_WIDTH 5 /* AIF2DRC_KNEE2_IP - [9:5] */
+#define WM8994_AIF2DRC_KNEE2_OP_MASK 0x001F /* AIF2DRC_KNEE2_OP - [4:0] */
+#define WM8994_AIF2DRC_KNEE2_OP_SHIFT 0 /* AIF2DRC_KNEE2_OP - [4:0] */
+#define WM8994_AIF2DRC_KNEE2_OP_WIDTH 5 /* AIF2DRC_KNEE2_OP - [4:0] */
+
+/*
+ * R1408 (0x580) - AIF2 EQ Gains (1)
+ */
+#define WM8994_AIF2DAC_EQ_B1_GAIN_MASK 0xF800 /* AIF2DAC_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF2DAC_EQ_B1_GAIN_SHIFT 11 /* AIF2DAC_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF2DAC_EQ_B1_GAIN_WIDTH 5 /* AIF2DAC_EQ_B1_GAIN - [15:11] */
+#define WM8994_AIF2DAC_EQ_B2_GAIN_MASK 0x07C0 /* AIF2DAC_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF2DAC_EQ_B2_GAIN_SHIFT 6 /* AIF2DAC_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF2DAC_EQ_B2_GAIN_WIDTH 5 /* AIF2DAC_EQ_B2_GAIN - [10:6] */
+#define WM8994_AIF2DAC_EQ_B3_GAIN_MASK 0x003E /* AIF2DAC_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF2DAC_EQ_B3_GAIN_SHIFT 1 /* AIF2DAC_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF2DAC_EQ_B3_GAIN_WIDTH 5 /* AIF2DAC_EQ_B3_GAIN - [5:1] */
+#define WM8994_AIF2DAC_EQ_ENA 0x0001 /* AIF2DAC_EQ_ENA */
+#define WM8994_AIF2DAC_EQ_ENA_MASK 0x0001 /* AIF2DAC_EQ_ENA */
+#define WM8994_AIF2DAC_EQ_ENA_SHIFT 0 /* AIF2DAC_EQ_ENA */
+#define WM8994_AIF2DAC_EQ_ENA_WIDTH 1 /* AIF2DAC_EQ_ENA */
+
+/*
+ * R1409 (0x581) - AIF2 EQ Gains (2)
+ */
+#define WM8994_AIF2DAC_EQ_B4_GAIN_MASK 0xF800 /* AIF2DAC_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF2DAC_EQ_B4_GAIN_SHIFT 11 /* AIF2DAC_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF2DAC_EQ_B4_GAIN_WIDTH 5 /* AIF2DAC_EQ_B4_GAIN - [15:11] */
+#define WM8994_AIF2DAC_EQ_B5_GAIN_MASK 0x07C0 /* AIF2DAC_EQ_B5_GAIN - [10:6] */
+#define WM8994_AIF2DAC_EQ_B5_GAIN_SHIFT 6 /* AIF2DAC_EQ_B5_GAIN - [10:6] */
+#define WM8994_AIF2DAC_EQ_B5_GAIN_WIDTH 5 /* AIF2DAC_EQ_B5_GAIN - [10:6] */
+
+/*
+ * R1410 (0x582) - AIF2 EQ Band 1 A
+ */
+#define WM8994_AIF2DAC_EQ_B1_A_MASK 0xFFFF /* AIF2DAC_EQ_B1_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B1_A_SHIFT 0 /* AIF2DAC_EQ_B1_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B1_A_WIDTH 16 /* AIF2DAC_EQ_B1_A - [15:0] */
+
+/*
+ * R1411 (0x583) - AIF2 EQ Band 1 B
+ */
+#define WM8994_AIF2DAC_EQ_B1_B_MASK 0xFFFF /* AIF2DAC_EQ_B1_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B1_B_SHIFT 0 /* AIF2DAC_EQ_B1_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B1_B_WIDTH 16 /* AIF2DAC_EQ_B1_B - [15:0] */
+
+/*
+ * R1412 (0x584) - AIF2 EQ Band 1 PG
+ */
+#define WM8994_AIF2DAC_EQ_B1_PG_MASK 0xFFFF /* AIF2DAC_EQ_B1_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B1_PG_SHIFT 0 /* AIF2DAC_EQ_B1_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B1_PG_WIDTH 16 /* AIF2DAC_EQ_B1_PG - [15:0] */
+
+/*
+ * R1413 (0x585) - AIF2 EQ Band 2 A
+ */
+#define WM8994_AIF2DAC_EQ_B2_A_MASK 0xFFFF /* AIF2DAC_EQ_B2_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_A_SHIFT 0 /* AIF2DAC_EQ_B2_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_A_WIDTH 16 /* AIF2DAC_EQ_B2_A - [15:0] */
+
+/*
+ * R1414 (0x586) - AIF2 EQ Band 2 B
+ */
+#define WM8994_AIF2DAC_EQ_B2_B_MASK 0xFFFF /* AIF2DAC_EQ_B2_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_B_SHIFT 0 /* AIF2DAC_EQ_B2_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_B_WIDTH 16 /* AIF2DAC_EQ_B2_B - [15:0] */
+
+/*
+ * R1415 (0x587) - AIF2 EQ Band 2 C
+ */
+#define WM8994_AIF2DAC_EQ_B2_C_MASK 0xFFFF /* AIF2DAC_EQ_B2_C - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_C_SHIFT 0 /* AIF2DAC_EQ_B2_C - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_C_WIDTH 16 /* AIF2DAC_EQ_B2_C - [15:0] */
+
+/*
+ * R1416 (0x588) - AIF2 EQ Band 2 PG
+ */
+#define WM8994_AIF2DAC_EQ_B2_PG_MASK 0xFFFF /* AIF2DAC_EQ_B2_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_PG_SHIFT 0 /* AIF2DAC_EQ_B2_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B2_PG_WIDTH 16 /* AIF2DAC_EQ_B2_PG - [15:0] */
+
+/*
+ * R1417 (0x589) - AIF2 EQ Band 3 A
+ */
+#define WM8994_AIF2DAC_EQ_B3_A_MASK 0xFFFF /* AIF2DAC_EQ_B3_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_A_SHIFT 0 /* AIF2DAC_EQ_B3_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_A_WIDTH 16 /* AIF2DAC_EQ_B3_A - [15:0] */
+
+/*
+ * R1418 (0x58A) - AIF2 EQ Band 3 B
+ */
+#define WM8994_AIF2DAC_EQ_B3_B_MASK 0xFFFF /* AIF2DAC_EQ_B3_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_B_SHIFT 0 /* AIF2DAC_EQ_B3_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_B_WIDTH 16 /* AIF2DAC_EQ_B3_B - [15:0] */
+
+/*
+ * R1419 (0x58B) - AIF2 EQ Band 3 C
+ */
+#define WM8994_AIF2DAC_EQ_B3_C_MASK 0xFFFF /* AIF2DAC_EQ_B3_C - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_C_SHIFT 0 /* AIF2DAC_EQ_B3_C - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_C_WIDTH 16 /* AIF2DAC_EQ_B3_C - [15:0] */
+
+/*
+ * R1420 (0x58C) - AIF2 EQ Band 3 PG
+ */
+#define WM8994_AIF2DAC_EQ_B3_PG_MASK 0xFFFF /* AIF2DAC_EQ_B3_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_PG_SHIFT 0 /* AIF2DAC_EQ_B3_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B3_PG_WIDTH 16 /* AIF2DAC_EQ_B3_PG - [15:0] */
+
+/*
+ * R1421 (0x58D) - AIF2 EQ Band 4 A
+ */
+#define WM8994_AIF2DAC_EQ_B4_A_MASK 0xFFFF /* AIF2DAC_EQ_B4_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_A_SHIFT 0 /* AIF2DAC_EQ_B4_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_A_WIDTH 16 /* AIF2DAC_EQ_B4_A - [15:0] */
+
+/*
+ * R1422 (0x58E) - AIF2 EQ Band 4 B
+ */
+#define WM8994_AIF2DAC_EQ_B4_B_MASK 0xFFFF /* AIF2DAC_EQ_B4_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_B_SHIFT 0 /* AIF2DAC_EQ_B4_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_B_WIDTH 16 /* AIF2DAC_EQ_B4_B - [15:0] */
+
+/*
+ * R1423 (0x58F) - AIF2 EQ Band 4 C
+ */
+#define WM8994_AIF2DAC_EQ_B4_C_MASK 0xFFFF /* AIF2DAC_EQ_B4_C - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_C_SHIFT 0 /* AIF2DAC_EQ_B4_C - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_C_WIDTH 16 /* AIF2DAC_EQ_B4_C - [15:0] */
+
+/*
+ * R1424 (0x590) - AIF2 EQ Band 4 PG
+ */
+#define WM8994_AIF2DAC_EQ_B4_PG_MASK 0xFFFF /* AIF2DAC_EQ_B4_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_PG_SHIFT 0 /* AIF2DAC_EQ_B4_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B4_PG_WIDTH 16 /* AIF2DAC_EQ_B4_PG - [15:0] */
+
+/*
+ * R1425 (0x591) - AIF2 EQ Band 5 A
+ */
+#define WM8994_AIF2DAC_EQ_B5_A_MASK 0xFFFF /* AIF2DAC_EQ_B5_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B5_A_SHIFT 0 /* AIF2DAC_EQ_B5_A - [15:0] */
+#define WM8994_AIF2DAC_EQ_B5_A_WIDTH 16 /* AIF2DAC_EQ_B5_A - [15:0] */
+
+/*
+ * R1426 (0x592) - AIF2 EQ Band 5 B
+ */
+#define WM8994_AIF2DAC_EQ_B5_B_MASK 0xFFFF /* AIF2DAC_EQ_B5_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B5_B_SHIFT 0 /* AIF2DAC_EQ_B5_B - [15:0] */
+#define WM8994_AIF2DAC_EQ_B5_B_WIDTH 16 /* AIF2DAC_EQ_B5_B - [15:0] */
+
+/*
+ * R1427 (0x593) - AIF2 EQ Band 5 PG
+ */
+#define WM8994_AIF2DAC_EQ_B5_PG_MASK 0xFFFF /* AIF2DAC_EQ_B5_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B5_PG_SHIFT 0 /* AIF2DAC_EQ_B5_PG - [15:0] */
+#define WM8994_AIF2DAC_EQ_B5_PG_WIDTH 16 /* AIF2DAC_EQ_B5_PG - [15:0] */
+
+/*
+ * R1536 (0x600) - DAC1 Mixer Volumes
+ */
+#define WM8994_ADCR_DAC1_VOL_MASK 0x01E0 /* ADCR_DAC1_VOL - [8:5] */
+#define WM8994_ADCR_DAC1_VOL_SHIFT 5 /* ADCR_DAC1_VOL - [8:5] */
+#define WM8994_ADCR_DAC1_VOL_WIDTH 4 /* ADCR_DAC1_VOL - [8:5] */
+#define WM8994_ADCL_DAC1_VOL_MASK 0x000F /* ADCL_DAC1_VOL - [3:0] */
+#define WM8994_ADCL_DAC1_VOL_SHIFT 0 /* ADCL_DAC1_VOL - [3:0] */
+#define WM8994_ADCL_DAC1_VOL_WIDTH 4 /* ADCL_DAC1_VOL - [3:0] */
+
+/*
+ * R1537 (0x601) - DAC1 Left Mixer Routing
+ */
+#define WM8994_ADCR_TO_DAC1L 0x0020 /* ADCR_TO_DAC1L */
+#define WM8994_ADCR_TO_DAC1L_MASK 0x0020 /* ADCR_TO_DAC1L */
+#define WM8994_ADCR_TO_DAC1L_SHIFT 5 /* ADCR_TO_DAC1L */
+#define WM8994_ADCR_TO_DAC1L_WIDTH 1 /* ADCR_TO_DAC1L */
+#define WM8994_ADCL_TO_DAC1L 0x0010 /* ADCL_TO_DAC1L */
+#define WM8994_ADCL_TO_DAC1L_MASK 0x0010 /* ADCL_TO_DAC1L */
+#define WM8994_ADCL_TO_DAC1L_SHIFT 4 /* ADCL_TO_DAC1L */
+#define WM8994_ADCL_TO_DAC1L_WIDTH 1 /* ADCL_TO_DAC1L */
+#define WM8994_AIF2DACL_TO_DAC1L 0x0004 /* AIF2DACL_TO_DAC1L */
+#define WM8994_AIF2DACL_TO_DAC1L_MASK 0x0004 /* AIF2DACL_TO_DAC1L */
+#define WM8994_AIF2DACL_TO_DAC1L_SHIFT 2 /* AIF2DACL_TO_DAC1L */
+#define WM8994_AIF2DACL_TO_DAC1L_WIDTH 1 /* AIF2DACL_TO_DAC1L */
+#define WM8994_AIF1DAC2L_TO_DAC1L 0x0002 /* AIF1DAC2L_TO_DAC1L */
+#define WM8994_AIF1DAC2L_TO_DAC1L_MASK 0x0002 /* AIF1DAC2L_TO_DAC1L */
+#define WM8994_AIF1DAC2L_TO_DAC1L_SHIFT 1 /* AIF1DAC2L_TO_DAC1L */
+#define WM8994_AIF1DAC2L_TO_DAC1L_WIDTH 1 /* AIF1DAC2L_TO_DAC1L */
+#define WM8994_AIF1DAC1L_TO_DAC1L 0x0001 /* AIF1DAC1L_TO_DAC1L */
+#define WM8994_AIF1DAC1L_TO_DAC1L_MASK 0x0001 /* AIF1DAC1L_TO_DAC1L */
+#define WM8994_AIF1DAC1L_TO_DAC1L_SHIFT 0 /* AIF1DAC1L_TO_DAC1L */
+#define WM8994_AIF1DAC1L_TO_DAC1L_WIDTH 1 /* AIF1DAC1L_TO_DAC1L */
+
+/*
+ * R1538 (0x602) - DAC1 Right Mixer Routing
+ */
+#define WM8994_ADCR_TO_DAC1R 0x0020 /* ADCR_TO_DAC1R */
+#define WM8994_ADCR_TO_DAC1R_MASK 0x0020 /* ADCR_TO_DAC1R */
+#define WM8994_ADCR_TO_DAC1R_SHIFT 5 /* ADCR_TO_DAC1R */
+#define WM8994_ADCR_TO_DAC1R_WIDTH 1 /* ADCR_TO_DAC1R */
+#define WM8994_ADCL_TO_DAC1R 0x0010 /* ADCL_TO_DAC1R */
+#define WM8994_ADCL_TO_DAC1R_MASK 0x0010 /* ADCL_TO_DAC1R */
+#define WM8994_ADCL_TO_DAC1R_SHIFT 4 /* ADCL_TO_DAC1R */
+#define WM8994_ADCL_TO_DAC1R_WIDTH 1 /* ADCL_TO_DAC1R */
+#define WM8994_AIF2DACR_TO_DAC1R 0x0004 /* AIF2DACR_TO_DAC1R */
+#define WM8994_AIF2DACR_TO_DAC1R_MASK 0x0004 /* AIF2DACR_TO_DAC1R */
+#define WM8994_AIF2DACR_TO_DAC1R_SHIFT 2 /* AIF2DACR_TO_DAC1R */
+#define WM8994_AIF2DACR_TO_DAC1R_WIDTH 1 /* AIF2DACR_TO_DAC1R */
+#define WM8994_AIF1DAC2R_TO_DAC1R 0x0002 /* AIF1DAC2R_TO_DAC1R */
+#define WM8994_AIF1DAC2R_TO_DAC1R_MASK 0x0002 /* AIF1DAC2R_TO_DAC1R */
+#define WM8994_AIF1DAC2R_TO_DAC1R_SHIFT 1 /* AIF1DAC2R_TO_DAC1R */
+#define WM8994_AIF1DAC2R_TO_DAC1R_WIDTH 1 /* AIF1DAC2R_TO_DAC1R */
+#define WM8994_AIF1DAC1R_TO_DAC1R 0x0001 /* AIF1DAC1R_TO_DAC1R */
+#define WM8994_AIF1DAC1R_TO_DAC1R_MASK 0x0001 /* AIF1DAC1R_TO_DAC1R */
+#define WM8994_AIF1DAC1R_TO_DAC1R_SHIFT 0 /* AIF1DAC1R_TO_DAC1R */
+#define WM8994_AIF1DAC1R_TO_DAC1R_WIDTH 1 /* AIF1DAC1R_TO_DAC1R */
+
+/*
+ * R1539 (0x603) - DAC2 Mixer Volumes
+ */
+#define WM8994_ADCR_DAC2_VOL_MASK 0x01E0 /* ADCR_DAC2_VOL - [8:5] */
+#define WM8994_ADCR_DAC2_VOL_SHIFT 5 /* ADCR_DAC2_VOL - [8:5] */
+#define WM8994_ADCR_DAC2_VOL_WIDTH 4 /* ADCR_DAC2_VOL - [8:5] */
+#define WM8994_ADCL_DAC2_VOL_MASK 0x000F /* ADCL_DAC2_VOL - [3:0] */
+#define WM8994_ADCL_DAC2_VOL_SHIFT 0 /* ADCL_DAC2_VOL - [3:0] */
+#define WM8994_ADCL_DAC2_VOL_WIDTH 4 /* ADCL_DAC2_VOL - [3:0] */
+
+/*
+ * R1540 (0x604) - DAC2 Left Mixer Routing
+ */
+#define WM8994_ADCR_TO_DAC2L 0x0020 /* ADCR_TO_DAC2L */
+#define WM8994_ADCR_TO_DAC2L_MASK 0x0020 /* ADCR_TO_DAC2L */
+#define WM8994_ADCR_TO_DAC2L_SHIFT 5 /* ADCR_TO_DAC2L */
+#define WM8994_ADCR_TO_DAC2L_WIDTH 1 /* ADCR_TO_DAC2L */
+#define WM8994_ADCL_TO_DAC2L 0x0010 /* ADCL_TO_DAC2L */
+#define WM8994_ADCL_TO_DAC2L_MASK 0x0010 /* ADCL_TO_DAC2L */
+#define WM8994_ADCL_TO_DAC2L_SHIFT 4 /* ADCL_TO_DAC2L */
+#define WM8994_ADCL_TO_DAC2L_WIDTH 1 /* ADCL_TO_DAC2L */
+#define WM8994_AIF2DACL_TO_DAC2L 0x0004 /* AIF2DACL_TO_DAC2L */
+#define WM8994_AIF2DACL_TO_DAC2L_MASK 0x0004 /* AIF2DACL_TO_DAC2L */
+#define WM8994_AIF2DACL_TO_DAC2L_SHIFT 2 /* AIF2DACL_TO_DAC2L */
+#define WM8994_AIF2DACL_TO_DAC2L_WIDTH 1 /* AIF2DACL_TO_DAC2L */
+#define WM8994_AIF1DAC2L_TO_DAC2L 0x0002 /* AIF1DAC2L_TO_DAC2L */
+#define WM8994_AIF1DAC2L_TO_DAC2L_MASK 0x0002 /* AIF1DAC2L_TO_DAC2L */
+#define WM8994_AIF1DAC2L_TO_DAC2L_SHIFT 1 /* AIF1DAC2L_TO_DAC2L */
+#define WM8994_AIF1DAC2L_TO_DAC2L_WIDTH 1 /* AIF1DAC2L_TO_DAC2L */
+#define WM8994_AIF1DAC1L_TO_DAC2L 0x0001 /* AIF1DAC1L_TO_DAC2L */
+#define WM8994_AIF1DAC1L_TO_DAC2L_MASK 0x0001 /* AIF1DAC1L_TO_DAC2L */
+#define WM8994_AIF1DAC1L_TO_DAC2L_SHIFT 0 /* AIF1DAC1L_TO_DAC2L */
+#define WM8994_AIF1DAC1L_TO_DAC2L_WIDTH 1 /* AIF1DAC1L_TO_DAC2L */
+
+/*
+ * R1541 (0x605) - DAC2 Right Mixer Routing
+ */
+#define WM8994_ADCR_TO_DAC2R 0x0020 /* ADCR_TO_DAC2R */
+#define WM8994_ADCR_TO_DAC2R_MASK 0x0020 /* ADCR_TO_DAC2R */
+#define WM8994_ADCR_TO_DAC2R_SHIFT 5 /* ADCR_TO_DAC2R */
+#define WM8994_ADCR_TO_DAC2R_WIDTH 1 /* ADCR_TO_DAC2R */
+#define WM8994_ADCL_TO_DAC2R 0x0010 /* ADCL_TO_DAC2R */
+#define WM8994_ADCL_TO_DAC2R_MASK 0x0010 /* ADCL_TO_DAC2R */
+#define WM8994_ADCL_TO_DAC2R_SHIFT 4 /* ADCL_TO_DAC2R */
+#define WM8994_ADCL_TO_DAC2R_WIDTH 1 /* ADCL_TO_DAC2R */
+#define WM8994_AIF2DACR_TO_DAC2R 0x0004 /* AIF2DACR_TO_DAC2R */
+#define WM8994_AIF2DACR_TO_DAC2R_MASK 0x0004 /* AIF2DACR_TO_DAC2R */
+#define WM8994_AIF2DACR_TO_DAC2R_SHIFT 2 /* AIF2DACR_TO_DAC2R */
+#define WM8994_AIF2DACR_TO_DAC2R_WIDTH 1 /* AIF2DACR_TO_DAC2R */
+#define WM8994_AIF1DAC2R_TO_DAC2R 0x0002 /* AIF1DAC2R_TO_DAC2R */
+#define WM8994_AIF1DAC2R_TO_DAC2R_MASK 0x0002 /* AIF1DAC2R_TO_DAC2R */
+#define WM8994_AIF1DAC2R_TO_DAC2R_SHIFT 1 /* AIF1DAC2R_TO_DAC2R */
+#define WM8994_AIF1DAC2R_TO_DAC2R_WIDTH 1 /* AIF1DAC2R_TO_DAC2R */
+#define WM8994_AIF1DAC1R_TO_DAC2R 0x0001 /* AIF1DAC1R_TO_DAC2R */
+#define WM8994_AIF1DAC1R_TO_DAC2R_MASK 0x0001 /* AIF1DAC1R_TO_DAC2R */
+#define WM8994_AIF1DAC1R_TO_DAC2R_SHIFT 0 /* AIF1DAC1R_TO_DAC2R */
+#define WM8994_AIF1DAC1R_TO_DAC2R_WIDTH 1 /* AIF1DAC1R_TO_DAC2R */
+
+/*
+ * R1542 (0x606) - AIF1 ADC1 Left Mixer Routing
+ */
+#define WM8994_ADC1L_TO_AIF1ADC1L 0x0002 /* ADC1L_TO_AIF1ADC1L */
+#define WM8994_ADC1L_TO_AIF1ADC1L_MASK 0x0002 /* ADC1L_TO_AIF1ADC1L */
+#define WM8994_ADC1L_TO_AIF1ADC1L_SHIFT 1 /* ADC1L_TO_AIF1ADC1L */
+#define WM8994_ADC1L_TO_AIF1ADC1L_WIDTH 1 /* ADC1L_TO_AIF1ADC1L */
+#define WM8994_AIF2DACL_TO_AIF1ADC1L 0x0001 /* AIF2DACL_TO_AIF1ADC1L */
+#define WM8994_AIF2DACL_TO_AIF1ADC1L_MASK 0x0001 /* AIF2DACL_TO_AIF1ADC1L */
+#define WM8994_AIF2DACL_TO_AIF1ADC1L_SHIFT 0 /* AIF2DACL_TO_AIF1ADC1L */
+#define WM8994_AIF2DACL_TO_AIF1ADC1L_WIDTH 1 /* AIF2DACL_TO_AIF1ADC1L */
+
+/*
+ * R1543 (0x607) - AIF1 ADC1 Right Mixer Routing
+ */
+#define WM8994_ADC1R_TO_AIF1ADC1R 0x0002 /* ADC1R_TO_AIF1ADC1R */
+#define WM8994_ADC1R_TO_AIF1ADC1R_MASK 0x0002 /* ADC1R_TO_AIF1ADC1R */
+#define WM8994_ADC1R_TO_AIF1ADC1R_SHIFT 1 /* ADC1R_TO_AIF1ADC1R */
+#define WM8994_ADC1R_TO_AIF1ADC1R_WIDTH 1 /* ADC1R_TO_AIF1ADC1R */
+#define WM8994_AIF2DACR_TO_AIF1ADC1R 0x0001 /* AIF2DACR_TO_AIF1ADC1R */
+#define WM8994_AIF2DACR_TO_AIF1ADC1R_MASK 0x0001 /* AIF2DACR_TO_AIF1ADC1R */
+#define WM8994_AIF2DACR_TO_AIF1ADC1R_SHIFT 0 /* AIF2DACR_TO_AIF1ADC1R */
+#define WM8994_AIF2DACR_TO_AIF1ADC1R_WIDTH 1 /* AIF2DACR_TO_AIF1ADC1R */
+
+/*
+ * R1544 (0x608) - AIF1 ADC2 Left Mixer Routing
+ */
+#define WM8994_ADC2L_TO_AIF1ADC2L 0x0002 /* ADC2L_TO_AIF1ADC2L */
+#define WM8994_ADC2L_TO_AIF1ADC2L_MASK 0x0002 /* ADC2L_TO_AIF1ADC2L */
+#define WM8994_ADC2L_TO_AIF1ADC2L_SHIFT 1 /* ADC2L_TO_AIF1ADC2L */
+#define WM8994_ADC2L_TO_AIF1ADC2L_WIDTH 1 /* ADC2L_TO_AIF1ADC2L */
+#define WM8994_AIF2DACL_TO_AIF1ADC2L 0x0001 /* AIF2DACL_TO_AIF1ADC2L */
+#define WM8994_AIF2DACL_TO_AIF1ADC2L_MASK 0x0001 /* AIF2DACL_TO_AIF1ADC2L */
+#define WM8994_AIF2DACL_TO_AIF1ADC2L_SHIFT 0 /* AIF2DACL_TO_AIF1ADC2L */
+#define WM8994_AIF2DACL_TO_AIF1ADC2L_WIDTH 1 /* AIF2DACL_TO_AIF1ADC2L */
+
+/*
+ * R1545 (0x609) - AIF1 ADC2 Right mixer Routing
+ */
+#define WM8994_ADC2R_TO_AIF1ADC2R 0x0002 /* ADC2R_TO_AIF1ADC2R */
+#define WM8994_ADC2R_TO_AIF1ADC2R_MASK 0x0002 /* ADC2R_TO_AIF1ADC2R */
+#define WM8994_ADC2R_TO_AIF1ADC2R_SHIFT 1 /* ADC2R_TO_AIF1ADC2R */
+#define WM8994_ADC2R_TO_AIF1ADC2R_WIDTH 1 /* ADC2R_TO_AIF1ADC2R */
+#define WM8994_AIF2DACR_TO_AIF1ADC2R 0x0001 /* AIF2DACR_TO_AIF1ADC2R */
+#define WM8994_AIF2DACR_TO_AIF1ADC2R_MASK 0x0001 /* AIF2DACR_TO_AIF1ADC2R */
+#define WM8994_AIF2DACR_TO_AIF1ADC2R_SHIFT 0 /* AIF2DACR_TO_AIF1ADC2R */
+#define WM8994_AIF2DACR_TO_AIF1ADC2R_WIDTH 1 /* AIF2DACR_TO_AIF1ADC2R */
+
+/*
+ * R1552 (0x610) - DAC1 Left Volume
+ */
+#define WM8994_DAC1L_MUTE 0x0200 /* DAC1L_MUTE */
+#define WM8994_DAC1L_MUTE_MASK 0x0200 /* DAC1L_MUTE */
+#define WM8994_DAC1L_MUTE_SHIFT 9 /* DAC1L_MUTE */
+#define WM8994_DAC1L_MUTE_WIDTH 1 /* DAC1L_MUTE */
+#define WM8994_DAC1_VU 0x0100 /* DAC1_VU */
+#define WM8994_DAC1_VU_MASK 0x0100 /* DAC1_VU */
+#define WM8994_DAC1_VU_SHIFT 8 /* DAC1_VU */
+#define WM8994_DAC1_VU_WIDTH 1 /* DAC1_VU */
+#define WM8994_DAC1L_VOL_MASK 0x00FF /* DAC1L_VOL - [7:0] */
+#define WM8994_DAC1L_VOL_SHIFT 0 /* DAC1L_VOL - [7:0] */
+#define WM8994_DAC1L_VOL_WIDTH 8 /* DAC1L_VOL - [7:0] */
+
+/*
+ * R1553 (0x611) - DAC1 Right Volume
+ */
+#define WM8994_DAC1R_MUTE 0x0200 /* DAC1R_MUTE */
+#define WM8994_DAC1R_MUTE_MASK 0x0200 /* DAC1R_MUTE */
+#define WM8994_DAC1R_MUTE_SHIFT 9 /* DAC1R_MUTE */
+#define WM8994_DAC1R_MUTE_WIDTH 1 /* DAC1R_MUTE */
+#define WM8994_DAC1_VU 0x0100 /* DAC1_VU */
+#define WM8994_DAC1_VU_MASK 0x0100 /* DAC1_VU */
+#define WM8994_DAC1_VU_SHIFT 8 /* DAC1_VU */
+#define WM8994_DAC1_VU_WIDTH 1 /* DAC1_VU */
+#define WM8994_DAC1R_VOL_MASK 0x00FF /* DAC1R_VOL - [7:0] */
+#define WM8994_DAC1R_VOL_SHIFT 0 /* DAC1R_VOL - [7:0] */
+#define WM8994_DAC1R_VOL_WIDTH 8 /* DAC1R_VOL - [7:0] */
+
+/*
+ * R1554 (0x612) - DAC2 Left Volume
+ */
+#define WM8994_DAC2L_MUTE 0x0200 /* DAC2L_MUTE */
+#define WM8994_DAC2L_MUTE_MASK 0x0200 /* DAC2L_MUTE */
+#define WM8994_DAC2L_MUTE_SHIFT 9 /* DAC2L_MUTE */
+#define WM8994_DAC2L_MUTE_WIDTH 1 /* DAC2L_MUTE */
+#define WM8994_DAC2_VU 0x0100 /* DAC2_VU */
+#define WM8994_DAC2_VU_MASK 0x0100 /* DAC2_VU */
+#define WM8994_DAC2_VU_SHIFT 8 /* DAC2_VU */
+#define WM8994_DAC2_VU_WIDTH 1 /* DAC2_VU */
+#define WM8994_DAC2L_VOL_MASK 0x00FF /* DAC2L_VOL - [7:0] */
+#define WM8994_DAC2L_VOL_SHIFT 0 /* DAC2L_VOL - [7:0] */
+#define WM8994_DAC2L_VOL_WIDTH 8 /* DAC2L_VOL - [7:0] */
+
+/*
+ * R1555 (0x613) - DAC2 Right Volume
+ */
+#define WM8994_DAC2R_MUTE 0x0200 /* DAC2R_MUTE */
+#define WM8994_DAC2R_MUTE_MASK 0x0200 /* DAC2R_MUTE */
+#define WM8994_DAC2R_MUTE_SHIFT 9 /* DAC2R_MUTE */
+#define WM8994_DAC2R_MUTE_WIDTH 1 /* DAC2R_MUTE */
+#define WM8994_DAC2_VU 0x0100 /* DAC2_VU */
+#define WM8994_DAC2_VU_MASK 0x0100 /* DAC2_VU */
+#define WM8994_DAC2_VU_SHIFT 8 /* DAC2_VU */
+#define WM8994_DAC2_VU_WIDTH 1 /* DAC2_VU */
+#define WM8994_DAC2R_VOL_MASK 0x00FF /* DAC2R_VOL - [7:0] */
+#define WM8994_DAC2R_VOL_SHIFT 0 /* DAC2R_VOL - [7:0] */
+#define WM8994_DAC2R_VOL_WIDTH 8 /* DAC2R_VOL - [7:0] */
+
+/*
+ * R1556 (0x614) - DAC Softmute
+ */
+#define WM8994_DAC_SOFTMUTEMODE 0x0002 /* DAC_SOFTMUTEMODE */
+#define WM8994_DAC_SOFTMUTEMODE_MASK 0x0002 /* DAC_SOFTMUTEMODE */
+#define WM8994_DAC_SOFTMUTEMODE_SHIFT 1 /* DAC_SOFTMUTEMODE */
+#define WM8994_DAC_SOFTMUTEMODE_WIDTH 1 /* DAC_SOFTMUTEMODE */
+#define WM8994_DAC_MUTERATE 0x0001 /* DAC_MUTERATE */
+#define WM8994_DAC_MUTERATE_MASK 0x0001 /* DAC_MUTERATE */
+#define WM8994_DAC_MUTERATE_SHIFT 0 /* DAC_MUTERATE */
+#define WM8994_DAC_MUTERATE_WIDTH 1 /* DAC_MUTERATE */
+
+/*
+ * R1568 (0x620) - Oversampling
+ */
+#define WM8994_ADC_OSR128 0x0002 /* ADC_OSR128 */
+#define WM8994_ADC_OSR128_MASK 0x0002 /* ADC_OSR128 */
+#define WM8994_ADC_OSR128_SHIFT 1 /* ADC_OSR128 */
+#define WM8994_ADC_OSR128_WIDTH 1 /* ADC_OSR128 */
+#define WM8994_DAC_OSR128 0x0001 /* DAC_OSR128 */
+#define WM8994_DAC_OSR128_MASK 0x0001 /* DAC_OSR128 */
+#define WM8994_DAC_OSR128_SHIFT 0 /* DAC_OSR128 */
+#define WM8994_DAC_OSR128_WIDTH 1 /* DAC_OSR128 */
+
+/*
+ * R1569 (0x621) - Sidetone
+ */
+#define WM8994_ST_HPF_CUT_MASK 0x0380 /* ST_HPF_CUT - [9:7] */
+#define WM8994_ST_HPF_CUT_SHIFT 7 /* ST_HPF_CUT - [9:7] */
+#define WM8994_ST_HPF_CUT_WIDTH 3 /* ST_HPF_CUT - [9:7] */
+#define WM8994_ST_HPF 0x0040 /* ST_HPF */
+#define WM8994_ST_HPF_MASK 0x0040 /* ST_HPF */
+#define WM8994_ST_HPF_SHIFT 6 /* ST_HPF */
+#define WM8994_ST_HPF_WIDTH 1 /* ST_HPF */
+#define WM8994_STR_SEL 0x0002 /* STR_SEL */
+#define WM8994_STR_SEL_MASK 0x0002 /* STR_SEL */
+#define WM8994_STR_SEL_SHIFT 1 /* STR_SEL */
+#define WM8994_STR_SEL_WIDTH 1 /* STR_SEL */
+#define WM8994_STL_SEL 0x0001 /* STL_SEL */
+#define WM8994_STL_SEL_MASK 0x0001 /* STL_SEL */
+#define WM8994_STL_SEL_SHIFT 0 /* STL_SEL */
+#define WM8994_STL_SEL_WIDTH 1 /* STL_SEL */
+
+/*
+ * R1824 (0x720) - Pull Control (1)
+ */
+#define WM8994_DMICDAT2_PU 0x0800 /* DMICDAT2_PU */
+#define WM8994_DMICDAT2_PU_MASK 0x0800 /* DMICDAT2_PU */
+#define WM8994_DMICDAT2_PU_SHIFT 11 /* DMICDAT2_PU */
+#define WM8994_DMICDAT2_PU_WIDTH 1 /* DMICDAT2_PU */
+#define WM8994_DMICDAT2_PD 0x0400 /* DMICDAT2_PD */
+#define WM8994_DMICDAT2_PD_MASK 0x0400 /* DMICDAT2_PD */
+#define WM8994_DMICDAT2_PD_SHIFT 10 /* DMICDAT2_PD */
+#define WM8994_DMICDAT2_PD_WIDTH 1 /* DMICDAT2_PD */
+#define WM8994_DMICDAT1_PU 0x0200 /* DMICDAT1_PU */
+#define WM8994_DMICDAT1_PU_MASK 0x0200 /* DMICDAT1_PU */
+#define WM8994_DMICDAT1_PU_SHIFT 9 /* DMICDAT1_PU */
+#define WM8994_DMICDAT1_PU_WIDTH 1 /* DMICDAT1_PU */
+#define WM8994_DMICDAT1_PD 0x0100 /* DMICDAT1_PD */
+#define WM8994_DMICDAT1_PD_MASK 0x0100 /* DMICDAT1_PD */
+#define WM8994_DMICDAT1_PD_SHIFT 8 /* DMICDAT1_PD */
+#define WM8994_DMICDAT1_PD_WIDTH 1 /* DMICDAT1_PD */
+#define WM8994_MCLK1_PU 0x0080 /* MCLK1_PU */
+#define WM8994_MCLK1_PU_MASK 0x0080 /* MCLK1_PU */
+#define WM8994_MCLK1_PU_SHIFT 7 /* MCLK1_PU */
+#define WM8994_MCLK1_PU_WIDTH 1 /* MCLK1_PU */
+#define WM8994_MCLK1_PD 0x0040 /* MCLK1_PD */
+#define WM8994_MCLK1_PD_MASK 0x0040 /* MCLK1_PD */
+#define WM8994_MCLK1_PD_SHIFT 6 /* MCLK1_PD */
+#define WM8994_MCLK1_PD_WIDTH 1 /* MCLK1_PD */
+#define WM8994_DACDAT1_PU 0x0020 /* DACDAT1_PU */
+#define WM8994_DACDAT1_PU_MASK 0x0020 /* DACDAT1_PU */
+#define WM8994_DACDAT1_PU_SHIFT 5 /* DACDAT1_PU */
+#define WM8994_DACDAT1_PU_WIDTH 1 /* DACDAT1_PU */
+#define WM8994_DACDAT1_PD 0x0010 /* DACDAT1_PD */
+#define WM8994_DACDAT1_PD_MASK 0x0010 /* DACDAT1_PD */
+#define WM8994_DACDAT1_PD_SHIFT 4 /* DACDAT1_PD */
+#define WM8994_DACDAT1_PD_WIDTH 1 /* DACDAT1_PD */
+#define WM8994_DACLRCLK1_PU 0x0008 /* DACLRCLK1_PU */
+#define WM8994_DACLRCLK1_PU_MASK 0x0008 /* DACLRCLK1_PU */
+#define WM8994_DACLRCLK1_PU_SHIFT 3 /* DACLRCLK1_PU */
+#define WM8994_DACLRCLK1_PU_WIDTH 1 /* DACLRCLK1_PU */
+#define WM8994_DACLRCLK1_PD 0x0004 /* DACLRCLK1_PD */
+#define WM8994_DACLRCLK1_PD_MASK 0x0004 /* DACLRCLK1_PD */
+#define WM8994_DACLRCLK1_PD_SHIFT 2 /* DACLRCLK1_PD */
+#define WM8994_DACLRCLK1_PD_WIDTH 1 /* DACLRCLK1_PD */
+#define WM8994_BCLK1_PU 0x0002 /* BCLK1_PU */
+#define WM8994_BCLK1_PU_MASK 0x0002 /* BCLK1_PU */
+#define WM8994_BCLK1_PU_SHIFT 1 /* BCLK1_PU */
+#define WM8994_BCLK1_PU_WIDTH 1 /* BCLK1_PU */
+#define WM8994_BCLK1_PD 0x0001 /* BCLK1_PD */
+#define WM8994_BCLK1_PD_MASK 0x0001 /* BCLK1_PD */
+#define WM8994_BCLK1_PD_SHIFT 0 /* BCLK1_PD */
+#define WM8994_BCLK1_PD_WIDTH 1 /* BCLK1_PD */
+
+/*
+ * R1825 (0x721) - Pull Control (2)
+ */
+#define WM8994_CSNADDR_PD 0x0100 /* CSNADDR_PD */
+#define WM8994_CSNADDR_PD_MASK 0x0100 /* CSNADDR_PD */
+#define WM8994_CSNADDR_PD_SHIFT 8 /* CSNADDR_PD */
+#define WM8994_CSNADDR_PD_WIDTH 1 /* CSNADDR_PD */
+#define WM8994_LDO2ENA_PD 0x0040 /* LDO2ENA_PD */
+#define WM8994_LDO2ENA_PD_MASK 0x0040 /* LDO2ENA_PD */
+#define WM8994_LDO2ENA_PD_SHIFT 6 /* LDO2ENA_PD */
+#define WM8994_LDO2ENA_PD_WIDTH 1 /* LDO2ENA_PD */
+#define WM8994_LDO1ENA_PD 0x0010 /* LDO1ENA_PD */
+#define WM8994_LDO1ENA_PD_MASK 0x0010 /* LDO1ENA_PD */
+#define WM8994_LDO1ENA_PD_SHIFT 4 /* LDO1ENA_PD */
+#define WM8994_LDO1ENA_PD_WIDTH 1 /* LDO1ENA_PD */
+#define WM8994_CIFMODE_PD 0x0004 /* CIFMODE_PD */
+#define WM8994_CIFMODE_PD_MASK 0x0004 /* CIFMODE_PD */
+#define WM8994_CIFMODE_PD_SHIFT 2 /* CIFMODE_PD */
+#define WM8994_CIFMODE_PD_WIDTH 1 /* CIFMODE_PD */
+#define WM8994_SPKMODE_PU 0x0002 /* SPKMODE_PU */
+#define WM8994_SPKMODE_PU_MASK 0x0002 /* SPKMODE_PU */
+#define WM8994_SPKMODE_PU_SHIFT 1 /* SPKMODE_PU */
+#define WM8994_SPKMODE_PU_WIDTH 1 /* SPKMODE_PU */
+
+/*
+ * R1840 (0x730) - Interrupt Status 1
+ */
+#define WM8994_GP11_EINT 0x0400 /* GP11_EINT */
+#define WM8994_GP11_EINT_MASK 0x0400 /* GP11_EINT */
+#define WM8994_GP11_EINT_SHIFT 10 /* GP11_EINT */
+#define WM8994_GP11_EINT_WIDTH 1 /* GP11_EINT */
+#define WM8994_GP10_EINT 0x0200 /* GP10_EINT */
+#define WM8994_GP10_EINT_MASK 0x0200 /* GP10_EINT */
+#define WM8994_GP10_EINT_SHIFT 9 /* GP10_EINT */
+#define WM8994_GP10_EINT_WIDTH 1 /* GP10_EINT */
+#define WM8994_GP9_EINT 0x0100 /* GP9_EINT */
+#define WM8994_GP9_EINT_MASK 0x0100 /* GP9_EINT */
+#define WM8994_GP9_EINT_SHIFT 8 /* GP9_EINT */
+#define WM8994_GP9_EINT_WIDTH 1 /* GP9_EINT */
+#define WM8994_GP8_EINT 0x0080 /* GP8_EINT */
+#define WM8994_GP8_EINT_MASK 0x0080 /* GP8_EINT */
+#define WM8994_GP8_EINT_SHIFT 7 /* GP8_EINT */
+#define WM8994_GP8_EINT_WIDTH 1 /* GP8_EINT */
+#define WM8994_GP7_EINT 0x0040 /* GP7_EINT */
+#define WM8994_GP7_EINT_MASK 0x0040 /* GP7_EINT */
+#define WM8994_GP7_EINT_SHIFT 6 /* GP7_EINT */
+#define WM8994_GP7_EINT_WIDTH 1 /* GP7_EINT */
+#define WM8994_GP6_EINT 0x0020 /* GP6_EINT */
+#define WM8994_GP6_EINT_MASK 0x0020 /* GP6_EINT */
+#define WM8994_GP6_EINT_SHIFT 5 /* GP6_EINT */
+#define WM8994_GP6_EINT_WIDTH 1 /* GP6_EINT */
+#define WM8994_GP5_EINT 0x0010 /* GP5_EINT */
+#define WM8994_GP5_EINT_MASK 0x0010 /* GP5_EINT */
+#define WM8994_GP5_EINT_SHIFT 4 /* GP5_EINT */
+#define WM8994_GP5_EINT_WIDTH 1 /* GP5_EINT */
+#define WM8994_GP4_EINT 0x0008 /* GP4_EINT */
+#define WM8994_GP4_EINT_MASK 0x0008 /* GP4_EINT */
+#define WM8994_GP4_EINT_SHIFT 3 /* GP4_EINT */
+#define WM8994_GP4_EINT_WIDTH 1 /* GP4_EINT */
+#define WM8994_GP3_EINT 0x0004 /* GP3_EINT */
+#define WM8994_GP3_EINT_MASK 0x0004 /* GP3_EINT */
+#define WM8994_GP3_EINT_SHIFT 2 /* GP3_EINT */
+#define WM8994_GP3_EINT_WIDTH 1 /* GP3_EINT */
+#define WM8994_GP2_EINT 0x0002 /* GP2_EINT */
+#define WM8994_GP2_EINT_MASK 0x0002 /* GP2_EINT */
+#define WM8994_GP2_EINT_SHIFT 1 /* GP2_EINT */
+#define WM8994_GP2_EINT_WIDTH 1 /* GP2_EINT */
+#define WM8994_GP1_EINT 0x0001 /* GP1_EINT */
+#define WM8994_GP1_EINT_MASK 0x0001 /* GP1_EINT */
+#define WM8994_GP1_EINT_SHIFT 0 /* GP1_EINT */
+#define WM8994_GP1_EINT_WIDTH 1 /* GP1_EINT */
+
+/*
+ * R1841 (0x731) - Interrupt Status 2
+ */
+#define WM8994_TEMP_WARN_EINT 0x8000 /* TEMP_WARN_EINT */
+#define WM8994_TEMP_WARN_EINT_MASK 0x8000 /* TEMP_WARN_EINT */
+#define WM8994_TEMP_WARN_EINT_SHIFT 15 /* TEMP_WARN_EINT */
+#define WM8994_TEMP_WARN_EINT_WIDTH 1 /* TEMP_WARN_EINT */
+#define WM8994_DCS_DONE_EINT 0x4000 /* DCS_DONE_EINT */
+#define WM8994_DCS_DONE_EINT_MASK 0x4000 /* DCS_DONE_EINT */
+#define WM8994_DCS_DONE_EINT_SHIFT 14 /* DCS_DONE_EINT */
+#define WM8994_DCS_DONE_EINT_WIDTH 1 /* DCS_DONE_EINT */
+#define WM8994_WSEQ_DONE_EINT 0x2000 /* WSEQ_DONE_EINT */
+#define WM8994_WSEQ_DONE_EINT_MASK 0x2000 /* WSEQ_DONE_EINT */
+#define WM8994_WSEQ_DONE_EINT_SHIFT 13 /* WSEQ_DONE_EINT */
+#define WM8994_WSEQ_DONE_EINT_WIDTH 1 /* WSEQ_DONE_EINT */
+#define WM8994_FIFOS_ERR_EINT 0x1000 /* FIFOS_ERR_EINT */
+#define WM8994_FIFOS_ERR_EINT_MASK 0x1000 /* FIFOS_ERR_EINT */
+#define WM8994_FIFOS_ERR_EINT_SHIFT 12 /* FIFOS_ERR_EINT */
+#define WM8994_FIFOS_ERR_EINT_WIDTH 1 /* FIFOS_ERR_EINT */
+#define WM8994_AIF2DRC_SIG_DET_EINT 0x0800 /* AIF2DRC_SIG_DET_EINT */
+#define WM8994_AIF2DRC_SIG_DET_EINT_MASK 0x0800 /* AIF2DRC_SIG_DET_EINT */
+#define WM8994_AIF2DRC_SIG_DET_EINT_SHIFT 11 /* AIF2DRC_SIG_DET_EINT */
+#define WM8994_AIF2DRC_SIG_DET_EINT_WIDTH 1 /* AIF2DRC_SIG_DET_EINT */
+#define WM8994_AIF1DRC2_SIG_DET_EINT 0x0400 /* AIF1DRC2_SIG_DET_EINT */
+#define WM8994_AIF1DRC2_SIG_DET_EINT_MASK 0x0400 /* AIF1DRC2_SIG_DET_EINT */
+#define WM8994_AIF1DRC2_SIG_DET_EINT_SHIFT 10 /* AIF1DRC2_SIG_DET_EINT */
+#define WM8994_AIF1DRC2_SIG_DET_EINT_WIDTH 1 /* AIF1DRC2_SIG_DET_EINT */
+#define WM8994_AIF1DRC1_SIG_DET_EINT 0x0200 /* AIF1DRC1_SIG_DET_EINT */
+#define WM8994_AIF1DRC1_SIG_DET_EINT_MASK 0x0200 /* AIF1DRC1_SIG_DET_EINT */
+#define WM8994_AIF1DRC1_SIG_DET_EINT_SHIFT 9 /* AIF1DRC1_SIG_DET_EINT */
+#define WM8994_AIF1DRC1_SIG_DET_EINT_WIDTH 1 /* AIF1DRC1_SIG_DET_EINT */
+#define WM8994_SRC2_LOCK_EINT 0x0100 /* SRC2_LOCK_EINT */
+#define WM8994_SRC2_LOCK_EINT_MASK 0x0100 /* SRC2_LOCK_EINT */
+#define WM8994_SRC2_LOCK_EINT_SHIFT 8 /* SRC2_LOCK_EINT */
+#define WM8994_SRC2_LOCK_EINT_WIDTH 1 /* SRC2_LOCK_EINT */
+#define WM8994_SRC1_LOCK_EINT 0x0080 /* SRC1_LOCK_EINT */
+#define WM8994_SRC1_LOCK_EINT_MASK 0x0080 /* SRC1_LOCK_EINT */
+#define WM8994_SRC1_LOCK_EINT_SHIFT 7 /* SRC1_LOCK_EINT */
+#define WM8994_SRC1_LOCK_EINT_WIDTH 1 /* SRC1_LOCK_EINT */
+#define WM8994_FLL2_LOCK_EINT 0x0040 /* FLL2_LOCK_EINT */
+#define WM8994_FLL2_LOCK_EINT_MASK 0x0040 /* FLL2_LOCK_EINT */
+#define WM8994_FLL2_LOCK_EINT_SHIFT 6 /* FLL2_LOCK_EINT */
+#define WM8994_FLL2_LOCK_EINT_WIDTH 1 /* FLL2_LOCK_EINT */
+#define WM8994_FLL1_LOCK_EINT 0x0020 /* FLL1_LOCK_EINT */
+#define WM8994_FLL1_LOCK_EINT_MASK 0x0020 /* FLL1_LOCK_EINT */
+#define WM8994_FLL1_LOCK_EINT_SHIFT 5 /* FLL1_LOCK_EINT */
+#define WM8994_FLL1_LOCK_EINT_WIDTH 1 /* FLL1_LOCK_EINT */
+#define WM8994_MIC2_SHRT_EINT 0x0010 /* MIC2_SHRT_EINT */
+#define WM8994_MIC2_SHRT_EINT_MASK 0x0010 /* MIC2_SHRT_EINT */
+#define WM8994_MIC2_SHRT_EINT_SHIFT 4 /* MIC2_SHRT_EINT */
+#define WM8994_MIC2_SHRT_EINT_WIDTH 1 /* MIC2_SHRT_EINT */
+#define WM8994_MIC2_DET_EINT 0x0008 /* MIC2_DET_EINT */
+#define WM8994_MIC2_DET_EINT_MASK 0x0008 /* MIC2_DET_EINT */
+#define WM8994_MIC2_DET_EINT_SHIFT 3 /* MIC2_DET_EINT */
+#define WM8994_MIC2_DET_EINT_WIDTH 1 /* MIC2_DET_EINT */
+#define WM8994_MIC1_SHRT_EINT 0x0004 /* MIC1_SHRT_EINT */
+#define WM8994_MIC1_SHRT_EINT_MASK 0x0004 /* MIC1_SHRT_EINT */
+#define WM8994_MIC1_SHRT_EINT_SHIFT 2 /* MIC1_SHRT_EINT */
+#define WM8994_MIC1_SHRT_EINT_WIDTH 1 /* MIC1_SHRT_EINT */
+#define WM8994_MIC1_DET_EINT 0x0002 /* MIC1_DET_EINT */
+#define WM8994_MIC1_DET_EINT_MASK 0x0002 /* MIC1_DET_EINT */
+#define WM8994_MIC1_DET_EINT_SHIFT 1 /* MIC1_DET_EINT */
+#define WM8994_MIC1_DET_EINT_WIDTH 1 /* MIC1_DET_EINT */
+#define WM8994_TEMP_SHUT_EINT 0x0001 /* TEMP_SHUT_EINT */
+#define WM8994_TEMP_SHUT_EINT_MASK 0x0001 /* TEMP_SHUT_EINT */
+#define WM8994_TEMP_SHUT_EINT_SHIFT 0 /* TEMP_SHUT_EINT */
+#define WM8994_TEMP_SHUT_EINT_WIDTH 1 /* TEMP_SHUT_EINT */
+
+/*
+ * R1842 (0x732) - Interrupt Raw Status 2
+ */
+#define WM8994_TEMP_WARN_STS 0x8000 /* TEMP_WARN_STS */
+#define WM8994_TEMP_WARN_STS_MASK 0x8000 /* TEMP_WARN_STS */
+#define WM8994_TEMP_WARN_STS_SHIFT 15 /* TEMP_WARN_STS */
+#define WM8994_TEMP_WARN_STS_WIDTH 1 /* TEMP_WARN_STS */
+#define WM8994_DCS_DONE_STS 0x4000 /* DCS_DONE_STS */
+#define WM8994_DCS_DONE_STS_MASK 0x4000 /* DCS_DONE_STS */
+#define WM8994_DCS_DONE_STS_SHIFT 14 /* DCS_DONE_STS */
+#define WM8994_DCS_DONE_STS_WIDTH 1 /* DCS_DONE_STS */
+#define WM8994_WSEQ_DONE_STS 0x2000 /* WSEQ_DONE_STS */
+#define WM8994_WSEQ_DONE_STS_MASK 0x2000 /* WSEQ_DONE_STS */
+#define WM8994_WSEQ_DONE_STS_SHIFT 13 /* WSEQ_DONE_STS */
+#define WM8994_WSEQ_DONE_STS_WIDTH 1 /* WSEQ_DONE_STS */
+#define WM8994_FIFOS_ERR_STS 0x1000 /* FIFOS_ERR_STS */
+#define WM8994_FIFOS_ERR_STS_MASK 0x1000 /* FIFOS_ERR_STS */
+#define WM8994_FIFOS_ERR_STS_SHIFT 12 /* FIFOS_ERR_STS */
+#define WM8994_FIFOS_ERR_STS_WIDTH 1 /* FIFOS_ERR_STS */
+#define WM8994_AIF2DRC_SIG_DET_STS 0x0800 /* AIF2DRC_SIG_DET_STS */
+#define WM8994_AIF2DRC_SIG_DET_STS_MASK 0x0800 /* AIF2DRC_SIG_DET_STS */
+#define WM8994_AIF2DRC_SIG_DET_STS_SHIFT 11 /* AIF2DRC_SIG_DET_STS */
+#define WM8994_AIF2DRC_SIG_DET_STS_WIDTH 1 /* AIF2DRC_SIG_DET_STS */
+#define WM8994_AIF1DRC2_SIG_DET_STS 0x0400 /* AIF1DRC2_SIG_DET_STS */
+#define WM8994_AIF1DRC2_SIG_DET_STS_MASK 0x0400 /* AIF1DRC2_SIG_DET_STS */
+#define WM8994_AIF1DRC2_SIG_DET_STS_SHIFT 10 /* AIF1DRC2_SIG_DET_STS */
+#define WM8994_AIF1DRC2_SIG_DET_STS_WIDTH 1 /* AIF1DRC2_SIG_DET_STS */
+#define WM8994_AIF1DRC1_SIG_DET_STS 0x0200 /* AIF1DRC1_SIG_DET_STS */
+#define WM8994_AIF1DRC1_SIG_DET_STS_MASK 0x0200 /* AIF1DRC1_SIG_DET_STS */
+#define WM8994_AIF1DRC1_SIG_DET_STS_SHIFT 9 /* AIF1DRC1_SIG_DET_STS */
+#define WM8994_AIF1DRC1_SIG_DET_STS_WIDTH 1 /* AIF1DRC1_SIG_DET_STS */
+#define WM8994_SRC2_LOCK_STS 0x0100 /* SRC2_LOCK_STS */
+#define WM8994_SRC2_LOCK_STS_MASK 0x0100 /* SRC2_LOCK_STS */
+#define WM8994_SRC2_LOCK_STS_SHIFT 8 /* SRC2_LOCK_STS */
+#define WM8994_SRC2_LOCK_STS_WIDTH 1 /* SRC2_LOCK_STS */
+#define WM8994_SRC1_LOCK_STS 0x0080 /* SRC1_LOCK_STS */
+#define WM8994_SRC1_LOCK_STS_MASK 0x0080 /* SRC1_LOCK_STS */
+#define WM8994_SRC1_LOCK_STS_SHIFT 7 /* SRC1_LOCK_STS */
+#define WM8994_SRC1_LOCK_STS_WIDTH 1 /* SRC1_LOCK_STS */
+#define WM8994_FLL2_LOCK_STS 0x0040 /* FLL2_LOCK_STS */
+#define WM8994_FLL2_LOCK_STS_MASK 0x0040 /* FLL2_LOCK_STS */
+#define WM8994_FLL2_LOCK_STS_SHIFT 6 /* FLL2_LOCK_STS */
+#define WM8994_FLL2_LOCK_STS_WIDTH 1 /* FLL2_LOCK_STS */
+#define WM8994_FLL1_LOCK_STS 0x0020 /* FLL1_LOCK_STS */
+#define WM8994_FLL1_LOCK_STS_MASK 0x0020 /* FLL1_LOCK_STS */
+#define WM8994_FLL1_LOCK_STS_SHIFT 5 /* FLL1_LOCK_STS */
+#define WM8994_FLL1_LOCK_STS_WIDTH 1 /* FLL1_LOCK_STS */
+#define WM8994_MIC2_SHRT_STS 0x0010 /* MIC2_SHRT_STS */
+#define WM8994_MIC2_SHRT_STS_MASK 0x0010 /* MIC2_SHRT_STS */
+#define WM8994_MIC2_SHRT_STS_SHIFT 4 /* MIC2_SHRT_STS */
+#define WM8994_MIC2_SHRT_STS_WIDTH 1 /* MIC2_SHRT_STS */
+#define WM8994_MIC2_DET_STS 0x0008 /* MIC2_DET_STS */
+#define WM8994_MIC2_DET_STS_MASK 0x0008 /* MIC2_DET_STS */
+#define WM8994_MIC2_DET_STS_SHIFT 3 /* MIC2_DET_STS */
+#define WM8994_MIC2_DET_STS_WIDTH 1 /* MIC2_DET_STS */
+#define WM8994_MIC1_SHRT_STS 0x0004 /* MIC1_SHRT_STS */
+#define WM8994_MIC1_SHRT_STS_MASK 0x0004 /* MIC1_SHRT_STS */
+#define WM8994_MIC1_SHRT_STS_SHIFT 2 /* MIC1_SHRT_STS */
+#define WM8994_MIC1_SHRT_STS_WIDTH 1 /* MIC1_SHRT_STS */
+#define WM8994_MIC1_DET_STS 0x0002 /* MIC1_DET_STS */
+#define WM8994_MIC1_DET_STS_MASK 0x0002 /* MIC1_DET_STS */
+#define WM8994_MIC1_DET_STS_SHIFT 1 /* MIC1_DET_STS */
+#define WM8994_MIC1_DET_STS_WIDTH 1 /* MIC1_DET_STS */
+#define WM8994_TEMP_SHUT_STS 0x0001 /* TEMP_SHUT_STS */
+#define WM8994_TEMP_SHUT_STS_MASK 0x0001 /* TEMP_SHUT_STS */
+#define WM8994_TEMP_SHUT_STS_SHIFT 0 /* TEMP_SHUT_STS */
+#define WM8994_TEMP_SHUT_STS_WIDTH 1 /* TEMP_SHUT_STS */
+
+/*
+ * R1848 (0x738) - Interrupt Status 1 Mask
+ */
+#define WM8994_IM_GP11_EINT 0x0400 /* IM_GP11_EINT */
+#define WM8994_IM_GP11_EINT_MASK 0x0400 /* IM_GP11_EINT */
+#define WM8994_IM_GP11_EINT_SHIFT 10 /* IM_GP11_EINT */
+#define WM8994_IM_GP11_EINT_WIDTH 1 /* IM_GP11_EINT */
+#define WM8994_IM_GP10_EINT 0x0200 /* IM_GP10_EINT */
+#define WM8994_IM_GP10_EINT_MASK 0x0200 /* IM_GP10_EINT */
+#define WM8994_IM_GP10_EINT_SHIFT 9 /* IM_GP10_EINT */
+#define WM8994_IM_GP10_EINT_WIDTH 1 /* IM_GP10_EINT */
+#define WM8994_IM_GP9_EINT 0x0100 /* IM_GP9_EINT */
+#define WM8994_IM_GP9_EINT_MASK 0x0100 /* IM_GP9_EINT */
+#define WM8994_IM_GP9_EINT_SHIFT 8 /* IM_GP9_EINT */
+#define WM8994_IM_GP9_EINT_WIDTH 1 /* IM_GP9_EINT */
+#define WM8994_IM_GP8_EINT 0x0080 /* IM_GP8_EINT */
+#define WM8994_IM_GP8_EINT_MASK 0x0080 /* IM_GP8_EINT */
+#define WM8994_IM_GP8_EINT_SHIFT 7 /* IM_GP8_EINT */
+#define WM8994_IM_GP8_EINT_WIDTH 1 /* IM_GP8_EINT */
+#define WM8994_IM_GP7_EINT 0x0040 /* IM_GP7_EINT */
+#define WM8994_IM_GP7_EINT_MASK 0x0040 /* IM_GP7_EINT */
+#define WM8994_IM_GP7_EINT_SHIFT 6 /* IM_GP7_EINT */
+#define WM8994_IM_GP7_EINT_WIDTH 1 /* IM_GP7_EINT */
+#define WM8994_IM_GP6_EINT 0x0020 /* IM_GP6_EINT */
+#define WM8994_IM_GP6_EINT_MASK 0x0020 /* IM_GP6_EINT */
+#define WM8994_IM_GP6_EINT_SHIFT 5 /* IM_GP6_EINT */
+#define WM8994_IM_GP6_EINT_WIDTH 1 /* IM_GP6_EINT */
+#define WM8994_IM_GP5_EINT 0x0010 /* IM_GP5_EINT */
+#define WM8994_IM_GP5_EINT_MASK 0x0010 /* IM_GP5_EINT */
+#define WM8994_IM_GP5_EINT_SHIFT 4 /* IM_GP5_EINT */
+#define WM8994_IM_GP5_EINT_WIDTH 1 /* IM_GP5_EINT */
+#define WM8994_IM_GP4_EINT 0x0008 /* IM_GP4_EINT */
+#define WM8994_IM_GP4_EINT_MASK 0x0008 /* IM_GP4_EINT */
+#define WM8994_IM_GP4_EINT_SHIFT 3 /* IM_GP4_EINT */
+#define WM8994_IM_GP4_EINT_WIDTH 1 /* IM_GP4_EINT */
+#define WM8994_IM_GP3_EINT 0x0004 /* IM_GP3_EINT */
+#define WM8994_IM_GP3_EINT_MASK 0x0004 /* IM_GP3_EINT */
+#define WM8994_IM_GP3_EINT_SHIFT 2 /* IM_GP3_EINT */
+#define WM8994_IM_GP3_EINT_WIDTH 1 /* IM_GP3_EINT */
+#define WM8994_IM_GP2_EINT 0x0002 /* IM_GP2_EINT */
+#define WM8994_IM_GP2_EINT_MASK 0x0002 /* IM_GP2_EINT */
+#define WM8994_IM_GP2_EINT_SHIFT 1 /* IM_GP2_EINT */
+#define WM8994_IM_GP2_EINT_WIDTH 1 /* IM_GP2_EINT */
+#define WM8994_IM_GP1_EINT 0x0001 /* IM_GP1_EINT */
+#define WM8994_IM_GP1_EINT_MASK 0x0001 /* IM_GP1_EINT */
+#define WM8994_IM_GP1_EINT_SHIFT 0 /* IM_GP1_EINT */
+#define WM8994_IM_GP1_EINT_WIDTH 1 /* IM_GP1_EINT */
+
+/*
+ * R1849 (0x739) - Interrupt Status 2 Mask
+ */
+#define WM8994_IM_TEMP_WARN_EINT 0x8000 /* IM_TEMP_WARN_EINT */
+#define WM8994_IM_TEMP_WARN_EINT_MASK 0x8000 /* IM_TEMP_WARN_EINT */
+#define WM8994_IM_TEMP_WARN_EINT_SHIFT 15 /* IM_TEMP_WARN_EINT */
+#define WM8994_IM_TEMP_WARN_EINT_WIDTH 1 /* IM_TEMP_WARN_EINT */
+#define WM8994_IM_DCS_DONE_EINT 0x4000 /* IM_DCS_DONE_EINT */
+#define WM8994_IM_DCS_DONE_EINT_MASK 0x4000 /* IM_DCS_DONE_EINT */
+#define WM8994_IM_DCS_DONE_EINT_SHIFT 14 /* IM_DCS_DONE_EINT */
+#define WM8994_IM_DCS_DONE_EINT_WIDTH 1 /* IM_DCS_DONE_EINT */
+#define WM8994_IM_WSEQ_DONE_EINT 0x2000 /* IM_WSEQ_DONE_EINT */
+#define WM8994_IM_WSEQ_DONE_EINT_MASK 0x2000 /* IM_WSEQ_DONE_EINT */
+#define WM8994_IM_WSEQ_DONE_EINT_SHIFT 13 /* IM_WSEQ_DONE_EINT */
+#define WM8994_IM_WSEQ_DONE_EINT_WIDTH 1 /* IM_WSEQ_DONE_EINT */
+#define WM8994_IM_FIFOS_ERR_EINT 0x1000 /* IM_FIFOS_ERR_EINT */
+#define WM8994_IM_FIFOS_ERR_EINT_MASK 0x1000 /* IM_FIFOS_ERR_EINT */
+#define WM8994_IM_FIFOS_ERR_EINT_SHIFT 12 /* IM_FIFOS_ERR_EINT */
+#define WM8994_IM_FIFOS_ERR_EINT_WIDTH 1 /* IM_FIFOS_ERR_EINT */
+#define WM8994_IM_AIF2DRC_SIG_DET_EINT 0x0800 /* IM_AIF2DRC_SIG_DET_EINT */
+#define WM8994_IM_AIF2DRC_SIG_DET_EINT_MASK 0x0800 /* IM_AIF2DRC_SIG_DET_EINT */
+#define WM8994_IM_AIF2DRC_SIG_DET_EINT_SHIFT 11 /* IM_AIF2DRC_SIG_DET_EINT */
+#define WM8994_IM_AIF2DRC_SIG_DET_EINT_WIDTH 1 /* IM_AIF2DRC_SIG_DET_EINT */
+#define WM8994_IM_AIF1DRC2_SIG_DET_EINT 0x0400 /* IM_AIF1DRC2_SIG_DET_EINT */
+#define WM8994_IM_AIF1DRC2_SIG_DET_EINT_MASK 0x0400 /* IM_AIF1DRC2_SIG_DET_EINT */
+#define WM8994_IM_AIF1DRC2_SIG_DET_EINT_SHIFT 10 /* IM_AIF1DRC2_SIG_DET_EINT */
+#define WM8994_IM_AIF1DRC2_SIG_DET_EINT_WIDTH 1 /* IM_AIF1DRC2_SIG_DET_EINT */
+#define WM8994_IM_AIF1DRC1_SIG_DET_EINT 0x0200 /* IM_AIF1DRC1_SIG_DET_EINT */
+#define WM8994_IM_AIF1DRC1_SIG_DET_EINT_MASK 0x0200 /* IM_AIF1DRC1_SIG_DET_EINT */
+#define WM8994_IM_AIF1DRC1_SIG_DET_EINT_SHIFT 9 /* IM_AIF1DRC1_SIG_DET_EINT */
+#define WM8994_IM_AIF1DRC1_SIG_DET_EINT_WIDTH 1 /* IM_AIF1DRC1_SIG_DET_EINT */
+#define WM8994_IM_SRC2_LOCK_EINT 0x0100 /* IM_SRC2_LOCK_EINT */
+#define WM8994_IM_SRC2_LOCK_EINT_MASK 0x0100 /* IM_SRC2_LOCK_EINT */
+#define WM8994_IM_SRC2_LOCK_EINT_SHIFT 8 /* IM_SRC2_LOCK_EINT */
+#define WM8994_IM_SRC2_LOCK_EINT_WIDTH 1 /* IM_SRC2_LOCK_EINT */
+#define WM8994_IM_SRC1_LOCK_EINT 0x0080 /* IM_SRC1_LOCK_EINT */
+#define WM8994_IM_SRC1_LOCK_EINT_MASK 0x0080 /* IM_SRC1_LOCK_EINT */
+#define WM8994_IM_SRC1_LOCK_EINT_SHIFT 7 /* IM_SRC1_LOCK_EINT */
+#define WM8994_IM_SRC1_LOCK_EINT_WIDTH 1 /* IM_SRC1_LOCK_EINT */
+#define WM8994_IM_FLL2_LOCK_EINT 0x0040 /* IM_FLL2_LOCK_EINT */
+#define WM8994_IM_FLL2_LOCK_EINT_MASK 0x0040 /* IM_FLL2_LOCK_EINT */
+#define WM8994_IM_FLL2_LOCK_EINT_SHIFT 6 /* IM_FLL2_LOCK_EINT */
+#define WM8994_IM_FLL2_LOCK_EINT_WIDTH 1 /* IM_FLL2_LOCK_EINT */
+#define WM8994_IM_FLL1_LOCK_EINT 0x0020 /* IM_FLL1_LOCK_EINT */
+#define WM8994_IM_FLL1_LOCK_EINT_MASK 0x0020 /* IM_FLL1_LOCK_EINT */
+#define WM8994_IM_FLL1_LOCK_EINT_SHIFT 5 /* IM_FLL1_LOCK_EINT */
+#define WM8994_IM_FLL1_LOCK_EINT_WIDTH 1 /* IM_FLL1_LOCK_EINT */
+#define WM8994_IM_MIC2_SHRT_EINT 0x0010 /* IM_MIC2_SHRT_EINT */
+#define WM8994_IM_MIC2_SHRT_EINT_MASK 0x0010 /* IM_MIC2_SHRT_EINT */
+#define WM8994_IM_MIC2_SHRT_EINT_SHIFT 4 /* IM_MIC2_SHRT_EINT */
+#define WM8994_IM_MIC2_SHRT_EINT_WIDTH 1 /* IM_MIC2_SHRT_EINT */
+#define WM8994_IM_MIC2_DET_EINT 0x0008 /* IM_MIC2_DET_EINT */
+#define WM8994_IM_MIC2_DET_EINT_MASK 0x0008 /* IM_MIC2_DET_EINT */
+#define WM8994_IM_MIC2_DET_EINT_SHIFT 3 /* IM_MIC2_DET_EINT */
+#define WM8994_IM_MIC2_DET_EINT_WIDTH 1 /* IM_MIC2_DET_EINT */
+#define WM8994_IM_MIC1_SHRT_EINT 0x0004 /* IM_MIC1_SHRT_EINT */
+#define WM8994_IM_MIC1_SHRT_EINT_MASK 0x0004 /* IM_MIC1_SHRT_EINT */
+#define WM8994_IM_MIC1_SHRT_EINT_SHIFT 2 /* IM_MIC1_SHRT_EINT */
+#define WM8994_IM_MIC1_SHRT_EINT_WIDTH 1 /* IM_MIC1_SHRT_EINT */
+#define WM8994_IM_MIC1_DET_EINT 0x0002 /* IM_MIC1_DET_EINT */
+#define WM8994_IM_MIC1_DET_EINT_MASK 0x0002 /* IM_MIC1_DET_EINT */
+#define WM8994_IM_MIC1_DET_EINT_SHIFT 1 /* IM_MIC1_DET_EINT */
+#define WM8994_IM_MIC1_DET_EINT_WIDTH 1 /* IM_MIC1_DET_EINT */
+#define WM8994_IM_TEMP_SHUT_EINT 0x0001 /* IM_TEMP_SHUT_EINT */
+#define WM8994_IM_TEMP_SHUT_EINT_MASK 0x0001 /* IM_TEMP_SHUT_EINT */
+#define WM8994_IM_TEMP_SHUT_EINT_SHIFT 0 /* IM_TEMP_SHUT_EINT */
+#define WM8994_IM_TEMP_SHUT_EINT_WIDTH 1 /* IM_TEMP_SHUT_EINT */
+
+/*
+ * R1856 (0x740) - Interrupt Control
+ */
+#define WM8994_IM_IRQ 0x0001 /* IM_IRQ */
+#define WM8994_IM_IRQ_MASK 0x0001 /* IM_IRQ */
+#define WM8994_IM_IRQ_SHIFT 0 /* IM_IRQ */
+#define WM8994_IM_IRQ_WIDTH 1 /* IM_IRQ */
+
+/*
+ * R1864 (0x748) - IRQ Debounce
+ */
+#define WM8994_TEMP_WARN_DB 0x0020 /* TEMP_WARN_DB */
+#define WM8994_TEMP_WARN_DB_MASK 0x0020 /* TEMP_WARN_DB */
+#define WM8994_TEMP_WARN_DB_SHIFT 5 /* TEMP_WARN_DB */
+#define WM8994_TEMP_WARN_DB_WIDTH 1 /* TEMP_WARN_DB */
+#define WM8994_MIC2_SHRT_DB 0x0010 /* MIC2_SHRT_DB */
+#define WM8994_MIC2_SHRT_DB_MASK 0x0010 /* MIC2_SHRT_DB */
+#define WM8994_MIC2_SHRT_DB_SHIFT 4 /* MIC2_SHRT_DB */
+#define WM8994_MIC2_SHRT_DB_WIDTH 1 /* MIC2_SHRT_DB */
+#define WM8994_MIC2_DET_DB 0x0008 /* MIC2_DET_DB */
+#define WM8994_MIC2_DET_DB_MASK 0x0008 /* MIC2_DET_DB */
+#define WM8994_MIC2_DET_DB_SHIFT 3 /* MIC2_DET_DB */
+#define WM8994_MIC2_DET_DB_WIDTH 1 /* MIC2_DET_DB */
+#define WM8994_MIC1_SHRT_DB 0x0004 /* MIC1_SHRT_DB */
+#define WM8994_MIC1_SHRT_DB_MASK 0x0004 /* MIC1_SHRT_DB */
+#define WM8994_MIC1_SHRT_DB_SHIFT 2 /* MIC1_SHRT_DB */
+#define WM8994_MIC1_SHRT_DB_WIDTH 1 /* MIC1_SHRT_DB */
+#define WM8994_MIC1_DET_DB 0x0002 /* MIC1_DET_DB */
+#define WM8994_MIC1_DET_DB_MASK 0x0002 /* MIC1_DET_DB */
+#define WM8994_MIC1_DET_DB_SHIFT 1 /* MIC1_DET_DB */
+#define WM8994_MIC1_DET_DB_WIDTH 1 /* MIC1_DET_DB */
+#define WM8994_TEMP_SHUT_DB 0x0001 /* TEMP_SHUT_DB */
+#define WM8994_TEMP_SHUT_DB_MASK 0x0001 /* TEMP_SHUT_DB */
+#define WM8994_TEMP_SHUT_DB_SHIFT 0 /* TEMP_SHUT_DB */
+#define WM8994_TEMP_SHUT_DB_WIDTH 1 /* TEMP_SHUT_DB */
+
+#endif
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 90957f14195..3899395a03d 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -870,6 +870,108 @@ extern int mprotect_fixup(struct vm_area_struct *vma,
*/
int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
struct page **pages);
+/*
+ * per-process(per-mm_struct) statistics.
+ */
+#if defined(SPLIT_RSS_COUNTING)
+/*
+ * The mm counters are not protected by its page_table_lock,
+ * so must be incremented atomically.
+ */
+static inline void set_mm_counter(struct mm_struct *mm, int member, long value)
+{
+ atomic_long_set(&mm->rss_stat.count[member], value);
+}
+
+unsigned long get_mm_counter(struct mm_struct *mm, int member);
+
+static inline void add_mm_counter(struct mm_struct *mm, int member, long value)
+{
+ atomic_long_add(value, &mm->rss_stat.count[member]);
+}
+
+static inline void inc_mm_counter(struct mm_struct *mm, int member)
+{
+ atomic_long_inc(&mm->rss_stat.count[member]);
+}
+
+static inline void dec_mm_counter(struct mm_struct *mm, int member)
+{
+ atomic_long_dec(&mm->rss_stat.count[member]);
+}
+
+#else /* !USE_SPLIT_PTLOCKS */
+/*
+ * The mm counters are protected by its page_table_lock,
+ * so can be incremented directly.
+ */
+static inline void set_mm_counter(struct mm_struct *mm, int member, long value)
+{
+ mm->rss_stat.count[member] = value;
+}
+
+static inline unsigned long get_mm_counter(struct mm_struct *mm, int member)
+{
+ return mm->rss_stat.count[member];
+}
+
+static inline void add_mm_counter(struct mm_struct *mm, int member, long value)
+{
+ mm->rss_stat.count[member] += value;
+}
+
+static inline void inc_mm_counter(struct mm_struct *mm, int member)
+{
+ mm->rss_stat.count[member]++;
+}
+
+static inline void dec_mm_counter(struct mm_struct *mm, int member)
+{
+ mm->rss_stat.count[member]--;
+}
+
+#endif /* !USE_SPLIT_PTLOCKS */
+
+static inline unsigned long get_mm_rss(struct mm_struct *mm)
+{
+ return get_mm_counter(mm, MM_FILEPAGES) +
+ get_mm_counter(mm, MM_ANONPAGES);
+}
+
+static inline unsigned long get_mm_hiwater_rss(struct mm_struct *mm)
+{
+ return max(mm->hiwater_rss, get_mm_rss(mm));
+}
+
+static inline unsigned long get_mm_hiwater_vm(struct mm_struct *mm)
+{
+ return max(mm->hiwater_vm, mm->total_vm);
+}
+
+static inline void update_hiwater_rss(struct mm_struct *mm)
+{
+ unsigned long _rss = get_mm_rss(mm);
+
+ if ((mm)->hiwater_rss < _rss)
+ (mm)->hiwater_rss = _rss;
+}
+
+static inline void update_hiwater_vm(struct mm_struct *mm)
+{
+ if (mm->hiwater_vm < mm->total_vm)
+ mm->hiwater_vm = mm->total_vm;
+}
+
+static inline void setmax_mm_hiwater_rss(unsigned long *maxrss,
+ struct mm_struct *mm)
+{
+ unsigned long hiwater_rss = get_mm_hiwater_rss(mm);
+
+ if (*maxrss < hiwater_rss)
+ *maxrss = hiwater_rss;
+}
+
+void sync_mm_rss(struct task_struct *task, struct mm_struct *mm);
/*
* A callback you can register to apply pressure to ageable caches.
@@ -1114,7 +1216,7 @@ static inline void vma_nonlinear_insert(struct vm_area_struct *vma,
/* mmap.c */
extern int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin);
-extern void vma_adjust(struct vm_area_struct *vma, unsigned long start,
+extern int vma_adjust(struct vm_area_struct *vma, unsigned long start,
unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert);
extern struct vm_area_struct *vma_merge(struct mm_struct *,
struct vm_area_struct *prev, unsigned long addr, unsigned long end,
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 36f96271306..048b46270aa 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -24,12 +24,6 @@ struct address_space;
#define USE_SPLIT_PTLOCKS (NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS)
-#if USE_SPLIT_PTLOCKS
-typedef atomic_long_t mm_counter_t;
-#else /* !USE_SPLIT_PTLOCKS */
-typedef unsigned long mm_counter_t;
-#endif /* !USE_SPLIT_PTLOCKS */
-
/*
* Each physical page in the system has a struct page associated with
* it to keep track of whatever it is we are using the page for at the
@@ -169,7 +163,8 @@ struct vm_area_struct {
* can only be in the i_mmap tree. An anonymous MAP_PRIVATE, stack
* or brk vma (with NULL file) can only be in an anon_vma list.
*/
- struct list_head anon_vma_node; /* Serialized by anon_vma->lock */
+ struct list_head anon_vma_chain; /* Serialized by mmap_sem &
+ * page_table_lock */
struct anon_vma *anon_vma; /* Serialized by page_table_lock */
/* Function pointers to deal with this struct. */
@@ -201,6 +196,29 @@ struct core_state {
struct completion startup;
};
+enum {
+ MM_FILEPAGES,
+ MM_ANONPAGES,
+ MM_SWAPENTS,
+ NR_MM_COUNTERS
+};
+
+#if USE_SPLIT_PTLOCKS
+#define SPLIT_RSS_COUNTING
+struct mm_rss_stat {
+ atomic_long_t count[NR_MM_COUNTERS];
+};
+/* per-thread cached information, */
+struct task_rss_stat {
+ int events; /* for synchronization threshold */
+ int count[NR_MM_COUNTERS];
+};
+#else /* !USE_SPLIT_PTLOCKS */
+struct mm_rss_stat {
+ unsigned long count[NR_MM_COUNTERS];
+};
+#endif /* !USE_SPLIT_PTLOCKS */
+
struct mm_struct {
struct vm_area_struct * mmap; /* list of VMAs */
struct rb_root mm_rb;
@@ -227,11 +245,6 @@ struct mm_struct {
* by mmlist_lock
*/
- /* Special counters, in some configurations protected by the
- * page_table_lock, in other configurations by being atomic.
- */
- mm_counter_t _file_rss;
- mm_counter_t _anon_rss;
unsigned long hiwater_rss; /* High-watermark of RSS usage */
unsigned long hiwater_vm; /* High-water virtual memory usage */
@@ -244,6 +257,12 @@ struct mm_struct {
unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */
+ /*
+ * Special counters, in some configurations protected by the
+ * page_table_lock, in other configurations by being atomic.
+ */
+ struct mm_rss_stat rss_stat;
+
struct linux_binfmt *binfmt;
cpumask_t cpu_vm_mask;
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 2ee22e8af11..d02d2c6e0cf 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -99,6 +99,8 @@ struct mmc_card {
#define MMC_STATE_BLOCKADDR (1<<3) /* card uses block-addressing */
unsigned int quirks; /* card quirks */
#define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */
+#define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */
+ /* for byte mode */
u32 raw_cid[4]; /* raw card CID */
u32 raw_csd[4]; /* raw card CSD */
@@ -139,6 +141,11 @@ static inline int mmc_card_lenient_fn0(const struct mmc_card *c)
return c->quirks & MMC_QUIRK_LENIENT_FN0;
}
+static inline int mmc_blksz_for_byte_mode(const struct mmc_card *c)
+{
+ return c->quirks & MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
+}
+
#define mmc_card_name(c) ((c)->cid.prod_name)
#define mmc_card_id(c) (dev_name(&(c)->dev))
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index eaf36364b7d..43eaf5ca584 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -14,6 +14,7 @@
#include <linux/sched.h>
#include <linux/mmc/core.h>
+#include <linux/mmc/pm.h>
struct mmc_ios {
unsigned int clock; /* clock rate */
@@ -152,6 +153,8 @@ struct mmc_host {
#define MMC_CAP_NONREMOVABLE (1 << 8) /* Nonremovable e.g. eMMC */
#define MMC_CAP_WAIT_WHILE_BUSY (1 << 9) /* Waits while card is busy */
+ mmc_pm_flag_t pm_caps; /* supported pm features */
+
/* host specific block data */
unsigned int max_seg_size; /* see blk_queue_max_segment_size */
unsigned short max_hw_segs; /* see blk_queue_max_hw_segments */
@@ -197,6 +200,8 @@ struct mmc_host {
struct task_struct *sdio_irq_thread;
atomic_t sdio_irq_thread_abort;
+ mmc_pm_flag_t pm_flags; /* requested pm features */
+
#ifdef CONFIG_LEDS_TRIGGERS
struct led_trigger *led; /* activity led */
#endif
diff --git a/include/linux/mmc/pm.h b/include/linux/mmc/pm.h
new file mode 100644
index 00000000000..d37aac49cf9
--- /dev/null
+++ b/include/linux/mmc/pm.h
@@ -0,0 +1,30 @@
+/*
+ * linux/include/linux/mmc/pm.h
+ *
+ * Author: Nicolas Pitre
+ * Copyright: (C) 2009 Marvell Technology Group Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef LINUX_MMC_PM_H
+#define LINUX_MMC_PM_H
+
+/*
+ * These flags are used to describe power management features that
+ * some cards (typically SDIO cards) might wish to benefit from when
+ * the host system is being suspended. There are several layers of
+ * abstractions involved, from the host controller driver, to the MMC core
+ * code, to the SDIO core code, to finally get to the actual SDIO function
+ * driver. This file is therefore used for common definitions shared across
+ * all those layers.
+ */
+
+typedef unsigned int mmc_pm_flag_t;
+
+#define MMC_PM_KEEP_POWER (1 << 0) /* preserve card power during suspend */
+#define MMC_PM_WAKE_SDIO_IRQ (1 << 1) /* wake up host system on SDIO IRQ assertion */
+
+#endif
diff --git a/include/linux/mmc/sdio.h b/include/linux/mmc/sdio.h
index 47ba464f517..0ebaef577ff 100644
--- a/include/linux/mmc/sdio.h
+++ b/include/linux/mmc/sdio.h
@@ -95,6 +95,8 @@
#define SDIO_BUS_WIDTH_1BIT 0x00
#define SDIO_BUS_WIDTH_4BIT 0x02
+#define SDIO_BUS_ASYNC_INT 0x20
+
#define SDIO_BUS_CD_DISABLE 0x80 /* disable pull-up on DAT3 (pin 1) */
#define SDIO_CCCR_CAPS 0x08
diff --git a/include/linux/mmc/sdio_func.h b/include/linux/mmc/sdio_func.h
index ac3ab683fec..c6c0cceba5f 100644
--- a/include/linux/mmc/sdio_func.h
+++ b/include/linux/mmc/sdio_func.h
@@ -15,6 +15,8 @@
#include <linux/device.h>
#include <linux/mod_devicetable.h>
+#include <linux/mmc/pm.h>
+
struct mmc_card;
struct sdio_func;
@@ -153,5 +155,8 @@ extern unsigned char sdio_f0_readb(struct sdio_func *func,
extern void sdio_f0_writeb(struct sdio_func *func, unsigned char b,
unsigned int addr, int *err_ret);
+extern mmc_pm_flag_t sdio_get_host_pm_caps(struct sdio_func *func);
+extern int sdio_set_host_pm_flags(struct sdio_func *func, mmc_pm_flag_t flags);
+
#endif
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index a01a103341b..bc209d8b7b5 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -306,6 +306,7 @@ struct zone {
* free areas of different sizes
*/
spinlock_t lock;
+ int all_unreclaimable; /* All pages pinned */
#ifdef CONFIG_MEMORY_HOTPLUG
/* see spanned/present_pages for more description */
seqlock_t span_seqlock;
@@ -417,7 +418,6 @@ struct zone {
} ____cacheline_internodealigned_in_smp;
typedef enum {
- ZONE_ALL_UNRECLAIMABLE, /* all pages pinned */
ZONE_RECLAIM_LOCKED, /* prevents concurrent reclaim */
ZONE_OOM_LOCKED, /* zone is in OOM killer zonelist */
} zone_flags_t;
@@ -437,11 +437,6 @@ static inline void zone_clear_flag(struct zone *zone, zone_flags_t flag)
clear_bit(flag, &zone->flags);
}
-static inline int zone_is_all_unreclaimable(const struct zone *zone)
-{
- return test_bit(ZONE_ALL_UNRECLAIMABLE, &zone->flags);
-}
-
static inline int zone_is_reclaim_locked(const struct zone *zone)
{
return test_bit(ZONE_RECLAIM_LOCKED, &zone->flags);
diff --git a/include/linux/nodemask.h b/include/linux/nodemask.h
index 454997cccbd..c4fa64b585f 100644
--- a/include/linux/nodemask.h
+++ b/include/linux/nodemask.h
@@ -69,8 +69,6 @@
* int node_online(node) Is some node online?
* int node_possible(node) Is some node possible?
*
- * int any_online_node(mask) First online node in mask
- *
* node_set_online(node) set bit 'node' in node_online_map
* node_set_offline(node) clear bit 'node' in node_online_map
*
@@ -467,15 +465,6 @@ static inline int num_node_state(enum node_states state)
#define node_online_map node_states[N_ONLINE]
#define node_possible_map node_states[N_POSSIBLE]
-#define any_online_node(mask) \
-({ \
- int node; \
- for_each_node_mask(node, (mask)) \
- if (node_online(node)) \
- break; \
- node; \
-})
-
#define num_online_nodes() num_node_state(N_ONLINE)
#define num_possible_nodes() num_node_state(N_POSSIBLE)
#define node_online(node) node_state((node), N_ONLINE)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index ec95ebe629f..cd5809a5963 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -678,6 +678,8 @@ enum pci_lost_interrupt_reason pci_lost_interrupt(struct pci_dev *dev);
int pci_find_capability(struct pci_dev *dev, int cap);
int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap);
int pci_find_ext_capability(struct pci_dev *dev, int cap);
+int pci_bus_find_ext_capability(struct pci_bus *bus, unsigned int devfn,
+ int cap);
int pci_find_ht_capability(struct pci_dev *dev, int ht_cap);
int pci_find_next_ht_capability(struct pci_dev *dev, int pos, int ht_cap);
struct pci_bus *pci_find_next_bus(const struct pci_bus *from);
diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h
index 9f2ad0aa3c3..c8f302991b6 100644
--- a/include/linux/pci_regs.h
+++ b/include/linux/pci_regs.h
@@ -507,6 +507,7 @@
#define PCI_EXT_CAP_ID_VC 2
#define PCI_EXT_CAP_ID_DSN 3
#define PCI_EXT_CAP_ID_PWR 4
+#define PCI_EXT_CAP_ID_VNDR 11
#define PCI_EXT_CAP_ID_ACS 13
#define PCI_EXT_CAP_ID_ARI 14
#define PCI_EXT_CAP_ID_ATS 15
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 71ff887ca44..212da17d06a 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -21,7 +21,7 @@ struct platform_device {
u32 num_resources;
struct resource * resource;
- struct platform_device_id *id_entry;
+ const struct platform_device_id *id_entry;
/* arch specific additions */
struct pdev_archdata archdata;
@@ -62,7 +62,7 @@ struct platform_driver {
int (*suspend)(struct platform_device *, pm_message_t state);
int (*resume)(struct platform_device *);
struct device_driver driver;
- struct platform_device_id *id_table;
+ const struct platform_device_id *id_table;
};
extern int platform_driver_register(struct platform_driver *);
@@ -77,6 +77,11 @@ 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))
+extern struct platform_device *platform_create_bundle(struct platform_driver *driver,
+ int (*probe)(struct platform_device *),
+ struct resource *res, unsigned int n_res,
+ const void *data, size_t size);
+
/* early platform driver interface */
struct early_platform_driver {
const char *class_str;
diff --git a/include/linux/pm.h b/include/linux/pm.h
index e80df06ad22..8e258c72797 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -215,20 +215,59 @@ struct dev_pm_ops {
int (*runtime_idle)(struct device *dev);
};
+#ifdef CONFIG_PM_SLEEP
+#define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \
+ .suspend = suspend_fn, \
+ .resume = resume_fn, \
+ .freeze = suspend_fn, \
+ .thaw = resume_fn, \
+ .poweroff = suspend_fn, \
+ .restore = resume_fn,
+#else
+#define SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn)
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+#define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \
+ .runtime_suspend = suspend_fn, \
+ .runtime_resume = resume_fn, \
+ .runtime_idle = idle_fn,
+#else
+#define SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn)
+#endif
+
/*
* Use this if you want to use the same suspend and resume callbacks for suspend
* to RAM and hibernation.
*/
#define SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \
const struct dev_pm_ops name = { \
- .suspend = suspend_fn, \
- .resume = resume_fn, \
- .freeze = suspend_fn, \
- .thaw = resume_fn, \
- .poweroff = suspend_fn, \
- .restore = resume_fn, \
+ SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \
+}
+
+/*
+ * Use this for defining a set of PM operations to be used in all situations
+ * (sustem suspend, hibernation or runtime PM).
+ */
+#define UNIVERSAL_DEV_PM_OPS(name, suspend_fn, resume_fn, idle_fn) \
+const struct dev_pm_ops name = { \
+ SET_SYSTEM_SLEEP_PM_OPS(suspend_fn, resume_fn) \
+ SET_RUNTIME_PM_OPS(suspend_fn, resume_fn, idle_fn) \
}
+/*
+ * Use this for subsystems (bus types, device types, device classes) that don't
+ * need any special suspend/resume handling in addition to invoking the PM
+ * callbacks provided by device drivers supporting both the system sleep PM and
+ * runtime PM, make the pm member point to generic_subsys_pm_ops.
+ */
+#ifdef CONFIG_PM_OPS
+extern struct dev_pm_ops generic_subsys_pm_ops;
+#define GENERIC_SUBSYS_PM_OPS (&generic_subsys_pm_ops)
+#else
+#define GENERIC_SUBSYS_PM_OPS NULL
+#endif
+
/**
* PM_EVENT_ messages
*
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
index 7d773aac531..b776db73724 100644
--- a/include/linux/pm_runtime.h
+++ b/include/linux/pm_runtime.h
@@ -62,6 +62,11 @@ static inline void device_set_run_wake(struct device *dev, bool enable)
dev->power.run_wake = enable;
}
+static inline bool pm_runtime_suspended(struct device *dev)
+{
+ return dev->power.runtime_status == RPM_SUSPENDED;
+}
+
#else /* !CONFIG_PM_RUNTIME */
static inline int pm_runtime_idle(struct device *dev) { return -ENOSYS; }
@@ -89,6 +94,7 @@ static inline void pm_runtime_get_noresume(struct device *dev) {}
static inline void pm_runtime_put_noidle(struct device *dev) {}
static inline bool device_run_wake(struct device *dev) { return false; }
static inline void device_set_run_wake(struct device *dev, bool enable) {}
+static inline bool pm_runtime_suspended(struct device *dev) { return false; }
#endif /* !CONFIG_PM_RUNTIME */
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index b019ae64e2a..d25bd224d37 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -37,7 +37,27 @@ struct anon_vma {
* is serialized by a system wide lock only visible to
* mm_take_all_locks() (mm_all_locks_mutex).
*/
- struct list_head head; /* List of private "related" vmas */
+ struct list_head head; /* Chain of private "related" vmas */
+};
+
+/*
+ * The copy-on-write semantics of fork mean that an anon_vma
+ * can become associated with multiple processes. Furthermore,
+ * each child process will have its own anon_vma, where new
+ * pages for that process are instantiated.
+ *
+ * This structure allows us to find the anon_vmas associated
+ * with a VMA, or the VMAs associated with an anon_vma.
+ * The "same_vma" list contains the anon_vma_chains linking
+ * all the anon_vmas associated with this VMA.
+ * The "same_anon_vma" list contains the anon_vma_chains
+ * which link all the VMAs associated with this anon_vma.
+ */
+struct anon_vma_chain {
+ struct vm_area_struct *vma;
+ struct anon_vma *anon_vma;
+ struct list_head same_vma; /* locked by mmap_sem & page_table_lock */
+ struct list_head same_anon_vma; /* locked by anon_vma->lock */
};
#ifdef CONFIG_MMU
@@ -89,15 +109,23 @@ static inline void anon_vma_unlock(struct vm_area_struct *vma)
*/
void anon_vma_init(void); /* create anon_vma_cachep */
int anon_vma_prepare(struct vm_area_struct *);
-void __anon_vma_merge(struct vm_area_struct *, struct vm_area_struct *);
-void anon_vma_unlink(struct vm_area_struct *);
-void anon_vma_link(struct vm_area_struct *);
+void unlink_anon_vmas(struct vm_area_struct *);
+int anon_vma_clone(struct vm_area_struct *, struct vm_area_struct *);
+int anon_vma_fork(struct vm_area_struct *, struct vm_area_struct *);
void __anon_vma_link(struct vm_area_struct *);
void anon_vma_free(struct anon_vma *);
+static inline void anon_vma_merge(struct vm_area_struct *vma,
+ struct vm_area_struct *next)
+{
+ VM_BUG_ON(vma->anon_vma != next->anon_vma);
+ unlink_anon_vmas(next);
+}
+
/*
* rmap interfaces called when adding or removing pte of page
*/
+void page_move_anon_rmap(struct page *, struct vm_area_struct *, unsigned long);
void page_add_anon_rmap(struct page *, struct vm_area_struct *, unsigned long);
void page_add_new_anon_rmap(struct page *, struct vm_area_struct *, unsigned long);
void page_add_file_rmap(struct page *);
@@ -181,7 +209,7 @@ static inline int page_referenced(struct page *page, int is_locked,
unsigned long *vm_flags)
{
*vm_flags = 0;
- return TestClearPageReferenced(page);
+ return 0;
}
#define try_to_unmap(page, refs) SWAP_FAIL
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 4b1753f7e48..46c6f8d5dc0 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -396,60 +396,6 @@ extern void arch_unmap_area_topdown(struct mm_struct *, unsigned long);
static inline void arch_pick_mmap_layout(struct mm_struct *mm) {}
#endif
-#if USE_SPLIT_PTLOCKS
-/*
- * The mm counters are not protected by its page_table_lock,
- * so must be incremented atomically.
- */
-#define set_mm_counter(mm, member, value) atomic_long_set(&(mm)->_##member, value)
-#define get_mm_counter(mm, member) ((unsigned long)atomic_long_read(&(mm)->_##member))
-#define add_mm_counter(mm, member, value) atomic_long_add(value, &(mm)->_##member)
-#define inc_mm_counter(mm, member) atomic_long_inc(&(mm)->_##member)
-#define dec_mm_counter(mm, member) atomic_long_dec(&(mm)->_##member)
-
-#else /* !USE_SPLIT_PTLOCKS */
-/*
- * The mm counters are protected by its page_table_lock,
- * so can be incremented directly.
- */
-#define set_mm_counter(mm, member, value) (mm)->_##member = (value)
-#define get_mm_counter(mm, member) ((mm)->_##member)
-#define add_mm_counter(mm, member, value) (mm)->_##member += (value)
-#define inc_mm_counter(mm, member) (mm)->_##member++
-#define dec_mm_counter(mm, member) (mm)->_##member--
-
-#endif /* !USE_SPLIT_PTLOCKS */
-
-#define get_mm_rss(mm) \
- (get_mm_counter(mm, file_rss) + get_mm_counter(mm, anon_rss))
-#define update_hiwater_rss(mm) do { \
- unsigned long _rss = get_mm_rss(mm); \
- if ((mm)->hiwater_rss < _rss) \
- (mm)->hiwater_rss = _rss; \
-} while (0)
-#define update_hiwater_vm(mm) do { \
- if ((mm)->hiwater_vm < (mm)->total_vm) \
- (mm)->hiwater_vm = (mm)->total_vm; \
-} while (0)
-
-static inline unsigned long get_mm_hiwater_rss(struct mm_struct *mm)
-{
- return max(mm->hiwater_rss, get_mm_rss(mm));
-}
-
-static inline void setmax_mm_hiwater_rss(unsigned long *maxrss,
- struct mm_struct *mm)
-{
- unsigned long hiwater_rss = get_mm_hiwater_rss(mm);
-
- if (*maxrss < hiwater_rss)
- *maxrss = hiwater_rss;
-}
-
-static inline unsigned long get_mm_hiwater_vm(struct mm_struct *mm)
-{
- return max(mm->hiwater_vm, mm->total_vm);
-}
extern void set_dumpable(struct mm_struct *mm, int value);
extern int get_dumpable(struct mm_struct *mm);
@@ -1274,7 +1220,9 @@ struct task_struct {
struct plist_node pushable_tasks;
struct mm_struct *mm, *active_mm;
-
+#if defined(SPLIT_RSS_COUNTING)
+ struct task_rss_stat rss_stat;
+#endif
/* task state */
int exit_state;
int exit_code, exit_signal;
diff --git a/include/linux/serial_sci.h b/include/linux/serial_sci.h
index 1c297ddc9d5..1b177d29a7f 100644
--- a/include/linux/serial_sci.h
+++ b/include/linux/serial_sci.h
@@ -2,6 +2,7 @@
#define __LINUX_SERIAL_SCI_H
#include <linux/serial_core.h>
+#include <asm/dmaengine.h>
/*
* Generic header for SuperH SCI(F) (used by sh/sh64/h8300 and related parts)
@@ -16,6 +17,8 @@ enum {
SCIx_NR_IRQS,
};
+struct device;
+
/*
* Platform device specific platform_data struct
*/
@@ -26,6 +29,9 @@ struct plat_sci_port {
unsigned int type; /* SCI / SCIF / IRDA */
upf_t flags; /* UPF_* flags */
char *clk; /* clock string */
+ struct device *dma_dev;
+ enum sh_dmae_slave_chan_id dma_slave_tx;
+ enum sh_dmae_slave_chan_id dma_slave_rx;
};
#endif /* __LINUX_SERIAL_SCI_H */
diff --git a/include/linux/smp.h b/include/linux/smp.h
index 7a0570e6a59..cfa2d20e35f 100644
--- a/include/linux/smp.h
+++ b/include/linux/smp.h
@@ -154,7 +154,7 @@ smp_call_function_any(const struct cpumask *mask, void (*func)(void *info),
/*
* smp_processor_id(): get the current CPU ID.
*
- * if DEBUG_PREEMPT is enabled the we check whether it is
+ * if DEBUG_PREEMPT is enabled then we check whether it is
* used in a preemption-safe way. (smp_processor_id() is safe
* if it's used in a preemption-off critical section, or in
* a thread that is bound to the current CPU.)
diff --git a/include/linux/spi/max7301.h b/include/linux/spi/max7301.h
index 6dfd83f19b4..34af0a3477b 100644
--- a/include/linux/spi/max7301.h
+++ b/include/linux/spi/max7301.h
@@ -1,9 +1,27 @@
#ifndef LINUX_SPI_MAX7301_H
#define LINUX_SPI_MAX7301_H
+#include <linux/gpio.h>
+
+/*
+ * Some registers must be read back to modify.
+ * To save time we cache them here in memory
+ */
+struct max7301 {
+ struct mutex lock;
+ u8 port_config[8]; /* field 0 is unused */
+ u32 out_level; /* cached output levels */
+ struct gpio_chip chip;
+ struct device *dev;
+ int (*write)(struct device *dev, unsigned int reg, unsigned int val);
+ int (*read)(struct device *dev, unsigned int reg);
+};
+
struct max7301_platform_data {
/* number assigned to the first GPIO */
unsigned base;
};
+extern int __max730x_remove(struct device *dev);
+extern int __max730x_probe(struct max7301 *ts);
#endif
diff --git a/include/linux/sysdev.h b/include/linux/sysdev.h
index f395bb3fa2f..1154c29f410 100644
--- a/include/linux/sysdev.h
+++ b/include/linux/sysdev.h
@@ -27,10 +27,12 @@
struct sys_device;
+struct sysdev_class_attribute;
struct sysdev_class {
const char *name;
struct list_head drivers;
+ struct sysdev_class_attribute **attrs;
/* Default operations for these types of devices */
int (*shutdown)(struct sys_device *);
@@ -41,8 +43,10 @@ struct sysdev_class {
struct sysdev_class_attribute {
struct attribute attr;
- ssize_t (*show)(struct sysdev_class *, char *);
- ssize_t (*store)(struct sysdev_class *, const char *, size_t);
+ ssize_t (*show)(struct sysdev_class *, struct sysdev_class_attribute *,
+ char *);
+ ssize_t (*store)(struct sysdev_class *, struct sysdev_class_attribute *,
+ const char *, size_t);
};
#define _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) \
@@ -119,6 +123,19 @@ struct sysdev_attribute {
extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *);
extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *);
+/* Create/remove NULL terminated attribute list */
+static inline int
+sysdev_create_files(struct sys_device *d, struct sysdev_attribute **a)
+{
+ return sysfs_create_files(&d->kobj, (const struct attribute **)a);
+}
+
+static inline void
+sysdev_remove_files(struct sys_device *d, struct sysdev_attribute **a)
+{
+ return sysfs_remove_files(&d->kobj, (const struct attribute **)a);
+}
+
struct sysdev_ext_attribute {
struct sysdev_attribute attr;
void *var;
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index cfa83083a2d..f0496b3d181 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -15,6 +15,7 @@
#include <linux/compiler.h>
#include <linux/errno.h>
#include <linux/list.h>
+#include <linux/lockdep.h>
#include <asm/atomic.h>
struct kobject;
@@ -29,8 +30,33 @@ struct attribute {
const char *name;
struct module *owner;
mode_t mode;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+ struct lock_class_key *key;
+ struct lock_class_key skey;
+#endif
};
+/**
+ * sysfs_attr_init - initialize a dynamically allocated sysfs attribute
+ * @attr: struct attribute to initialize
+ *
+ * Initialize a dynamically allocated struct attribute so we can
+ * make lockdep happy. This is a new requirement for attributes
+ * and initially this is only needed when lockdep is enabled.
+ * Lockdep gives a nice error when your attribute is added to
+ * sysfs if you don't have this.
+ */
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+#define sysfs_attr_init(attr) \
+do { \
+ static struct lock_class_key __key; \
+ \
+ (attr)->key = &__key; \
+} while(0)
+#else
+#define sysfs_attr_init(attr) do {} while(0)
+#endif
+
struct attribute_group {
const char *name;
mode_t (*is_visible)(struct kobject *,
@@ -74,6 +100,18 @@ struct bin_attribute {
struct vm_area_struct *vma);
};
+/**
+ * sysfs_bin_attr_init - initialize a dynamically allocated bin_attribute
+ * @attr: struct bin_attribute to initialize
+ *
+ * Initialize a dynamically allocated struct bin_attribute so we
+ * can make lockdep happy. This is a new requirement for
+ * attributes and initially this is only needed when lockdep is
+ * enabled. Lockdep gives a nice error when your attribute is
+ * added to sysfs if you don't have this.
+ */
+#define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&(bin_attr)->attr)
+
struct sysfs_ops {
ssize_t (*show)(struct kobject *, struct attribute *,char *);
ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t);
@@ -94,9 +132,12 @@ int __must_check sysfs_move_dir(struct kobject *kobj,
int __must_check sysfs_create_file(struct kobject *kobj,
const struct attribute *attr);
+int __must_check sysfs_create_files(struct kobject *kobj,
+ const struct attribute **attr);
int __must_check sysfs_chmod_file(struct kobject *kobj, struct attribute *attr,
mode_t mode);
void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr);
+void sysfs_remove_files(struct kobject *kobj, const struct attribute **attr);
int __must_check sysfs_create_bin_file(struct kobject *kobj,
const struct bin_attribute *attr);
@@ -110,6 +151,9 @@ int __must_check sysfs_create_link_nowarn(struct kobject *kobj,
const char *name);
void sysfs_remove_link(struct kobject *kobj, const char *name);
+int sysfs_rename_link(struct kobject *kobj, struct kobject *target,
+ const char *old_name, const char *new_name);
+
int __must_check sysfs_create_group(struct kobject *kobj,
const struct attribute_group *grp);
int sysfs_update_group(struct kobject *kobj,
@@ -164,6 +208,12 @@ static inline int sysfs_create_file(struct kobject *kobj,
return 0;
}
+static inline int sysfs_create_files(struct kobject *kobj,
+ const struct attribute **attr)
+{
+ return 0;
+}
+
static inline int sysfs_chmod_file(struct kobject *kobj,
struct attribute *attr, mode_t mode)
{
@@ -175,6 +225,11 @@ static inline void sysfs_remove_file(struct kobject *kobj,
{
}
+static inline void sysfs_remove_files(struct kobject *kobj,
+ const struct attribute **attr)
+{
+}
+
static inline int sysfs_create_bin_file(struct kobject *kobj,
const struct bin_attribute *attr)
{
@@ -203,6 +258,12 @@ static inline void sysfs_remove_link(struct kobject *kobj, const char *name)
{
}
+static inline int sysfs_rename_link(struct kobject *k, struct kobject *t,
+ const char *old_name, const char *new_name)
+{
+ return 0;
+}
+
static inline int sysfs_create_group(struct kobject *kobj,
const struct attribute_group *grp)
{
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 3492abf82e7..8c9f053111b 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -512,9 +512,9 @@ extern struct usb_device *usb_get_dev(struct usb_device *dev);
extern void usb_put_dev(struct usb_device *dev);
/* USB device locking */
-#define usb_lock_device(udev) down(&(udev)->dev.sem)
-#define usb_unlock_device(udev) up(&(udev)->dev.sem)
-#define usb_trylock_device(udev) down_trylock(&(udev)->dev.sem)
+#define usb_lock_device(udev) device_lock(&(udev)->dev)
+#define usb_unlock_device(udev) device_unlock(&(udev)->dev)
+#define usb_trylock_device(udev) device_trylock(&(udev)->dev)
extern int usb_lock_device_for_reset(struct usb_device *udev,
const struct usb_interface *iface);
diff --git a/include/linux/usb/audio.h b/include/linux/usb/audio.h
index 6bb293684eb..4d3e450e2b0 100644
--- a/include/linux/usb/audio.h
+++ b/include/linux/usb/audio.h
@@ -269,8 +269,8 @@ struct uac_format_type_i_ext_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u8 bDescriptorSubtype;
- __u8 bSubslotSize;
__u8 bFormatType;
+ __u8 bSubslotSize;
__u8 bBitResolution;
__u8 bHeaderLength;
__u8 bControlSize;
diff --git a/include/sound/asound.h b/include/sound/asound.h
index 1f57bb92eb5..09859550063 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -544,7 +544,7 @@ struct snd_rawmidi_status {
* Timer section - /dev/snd/timer
*/
-#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 5)
+#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
enum {
SNDRV_TIMER_CLASS_NONE = -1,
diff --git a/init/initramfs.c b/init/initramfs.c
index b37d34beb90..37d3859b1b3 100644
--- a/init/initramfs.c
+++ b/init/initramfs.c
@@ -525,7 +525,7 @@ static void __init clean_rootfs(void)
int fd;
void *buf;
struct linux_dirent64 *dirp;
- int count;
+ int num;
fd = sys_open("/", O_RDONLY, 0);
WARN_ON(fd < 0);
@@ -539,9 +539,9 @@ static void __init clean_rootfs(void)
}
dirp = buf;
- count = sys_getdents64(fd, dirp, BUF_SIZE);
- while (count > 0) {
- while (count > 0) {
+ num = sys_getdents64(fd, dirp, BUF_SIZE);
+ while (num > 0) {
+ while (num > 0) {
struct stat st;
int ret;
@@ -554,12 +554,12 @@ static void __init clean_rootfs(void)
sys_unlink(dirp->d_name);
}
- count -= dirp->d_reclen;
+ num -= dirp->d_reclen;
dirp = (void *)dirp + dirp->d_reclen;
}
dirp = buf;
memset(buf, 0, BUF_SIZE);
- count = sys_getdents64(fd, dirp, BUF_SIZE);
+ num = sys_getdents64(fd, dirp, BUF_SIZE);
}
sys_close(fd);
diff --git a/init/main.c b/init/main.c
index 40aaa020cd6..a1ab78ceb4b 100644
--- a/init/main.c
+++ b/init/main.c
@@ -174,7 +174,7 @@ static int __init maxcpus(char *str)
early_param("maxcpus", maxcpus);
#else
-const unsigned int setup_max_cpus = NR_CPUS;
+static const unsigned int setup_max_cpus = NR_CPUS;
#endif
/*
@@ -618,7 +618,7 @@ asmlinkage void __init start_kernel(void)
local_irq_enable();
/* Interrupts are enabled now so all GFP allocations are safe. */
- set_gfp_allowed_mask(__GFP_BITS_MASK);
+ gfp_allowed_mask = __GFP_BITS_MASK;
kmem_cache_init_late();
@@ -847,7 +847,8 @@ static noinline int init_post(void)
run_init_process("/bin/init");
run_init_process("/bin/sh");
- panic("No init found. Try passing init= option to kernel.");
+ panic("No init found. Try passing init= option to kernel. "
+ "See Linux Documentation/init.txt for guidance.");
}
static int __init kernel_init(void * unused)
diff --git a/kernel/Makefile b/kernel/Makefile
index 7b974699f8c..a987aa1676b 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -91,6 +91,9 @@ obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
obj-$(CONFIG_TRACEPOINTS) += tracepoint.o
obj-$(CONFIG_LATENCYTOP) += latencytop.o
+obj-$(CONFIG_BINFMT_ELF) += elfcore.o
+obj-$(CONFIG_COMPAT_BINFMT_ELF) += elfcore.o
+obj-$(CONFIG_BINFMT_ELF_FDPIC) += elfcore.o
obj-$(CONFIG_FUNCTION_TRACER) += trace/
obj-$(CONFIG_TRACING) += trace/
obj-$(CONFIG_X86_DS) += trace/
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 677f25376a3..f8cced2692b 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -338,7 +338,7 @@ int __cpuinit cpu_up(unsigned int cpu)
if (!cpu_possible(cpu)) {
printk(KERN_ERR "can't online cpu %d because it is not "
"configured as may-hotadd at boot time\n", cpu);
-#if defined(CONFIG_IA64) || defined(CONFIG_X86_64)
+#if defined(CONFIG_IA64)
printk(KERN_ERR "please check additional_cpus= boot "
"parameter\n");
#endif
diff --git a/kernel/elfcore.c b/kernel/elfcore.c
new file mode 100644
index 00000000000..ff915efef66
--- /dev/null
+++ b/kernel/elfcore.c
@@ -0,0 +1,28 @@
+#include <linux/elf.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+
+#include <asm/elf.h>
+
+
+Elf_Half __weak elf_core_extra_phdrs(void)
+{
+ return 0;
+}
+
+int __weak elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size,
+ unsigned long limit)
+{
+ return 1;
+}
+
+int __weak elf_core_write_extra_data(struct file *file, size_t *size,
+ unsigned long limit)
+{
+ return 1;
+}
+
+size_t __weak elf_core_extra_data_size(void)
+{
+ return 0;
+}
diff --git a/kernel/exit.c b/kernel/exit.c
index 45ed043b8bf..ce1e48c2d93 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -952,7 +952,8 @@ NORET_TYPE void do_exit(long code)
preempt_count());
acct_update_integrals(tsk);
-
+ /* sync mm's RSS info before statistics gathering */
+ sync_mm_rss(tsk, tsk->mm);
group_dead = atomic_dec_and_test(&tsk->signal->live);
if (group_dead) {
hrtimer_cancel(&tsk->signal->real_timer);
@@ -1188,7 +1189,7 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
if (unlikely(wo->wo_flags & WNOWAIT)) {
int exit_code = p->exit_code;
- int why, status;
+ int why;
get_task_struct(p);
read_unlock(&tasklist_lock);
diff --git a/kernel/fork.c b/kernel/fork.c
index 17bbf093356..b0ec34abc0b 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -329,15 +329,17 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
if (!tmp)
goto fail_nomem;
*tmp = *mpnt;
+ INIT_LIST_HEAD(&tmp->anon_vma_chain);
pol = mpol_dup(vma_policy(mpnt));
retval = PTR_ERR(pol);
if (IS_ERR(pol))
goto fail_nomem_policy;
vma_set_policy(tmp, pol);
+ if (anon_vma_fork(tmp, mpnt))
+ goto fail_nomem_anon_vma_fork;
tmp->vm_flags &= ~VM_LOCKED;
tmp->vm_mm = mm;
tmp->vm_next = NULL;
- anon_vma_link(tmp);
file = tmp->vm_file;
if (file) {
struct inode *inode = file->f_path.dentry->d_inode;
@@ -392,6 +394,8 @@ out:
flush_tlb_mm(oldmm);
up_write(&oldmm->mmap_sem);
return retval;
+fail_nomem_anon_vma_fork:
+ mpol_put(pol);
fail_nomem_policy:
kmem_cache_free(vm_area_cachep, tmp);
fail_nomem:
@@ -455,8 +459,7 @@ static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p)
(current->mm->flags & MMF_INIT_MASK) : default_dump_filter;
mm->core_state = NULL;
mm->nr_ptes = 0;
- set_mm_counter(mm, file_rss, 0);
- set_mm_counter(mm, anon_rss, 0);
+ memset(&mm->rss_stat, 0, sizeof(mm->rss_stat));
spin_lock_init(&mm->page_table_lock);
mm->free_area_cache = TASK_UNMAPPED_BASE;
mm->cached_hole_size = ~0UL;
@@ -825,6 +828,8 @@ void __cleanup_sighand(struct sighand_struct *sighand)
*/
static void posix_cpu_timers_init_group(struct signal_struct *sig)
{
+ unsigned long cpu_limit;
+
/* Thread group counters. */
thread_group_cputime_init(sig);
@@ -839,9 +844,9 @@ static void posix_cpu_timers_init_group(struct signal_struct *sig)
sig->cputime_expires.virt_exp = cputime_zero;
sig->cputime_expires.sched_exp = 0;
- if (sig->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
- sig->cputime_expires.prof_exp =
- secs_to_cputime(sig->rlim[RLIMIT_CPU].rlim_cur);
+ cpu_limit = ACCESS_ONCE(sig->rlim[RLIMIT_CPU].rlim_cur);
+ if (cpu_limit != RLIM_INFINITY) {
+ sig->cputime_expires.prof_exp = secs_to_cputime(cpu_limit);
sig->cputimer.running = 1;
}
@@ -1034,7 +1039,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
#endif
retval = -EAGAIN;
if (atomic_read(&p->real_cred->user->processes) >=
- p->signal->rlim[RLIMIT_NPROC].rlim_cur) {
+ task_rlimit(p, RLIMIT_NPROC)) {
if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
p->real_cred->user != INIT_USER)
goto bad_fork_free;
diff --git a/kernel/module.c b/kernel/module.c
index e5538d5f00a..c968d3606dc 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1085,6 +1085,7 @@ static void add_sect_attrs(struct module *mod, unsigned int nsect,
if (sattr->name == NULL)
goto out;
sect_attrs->nsections++;
+ sysfs_attr_init(&sattr->mattr.attr);
sattr->mattr.show = module_sect_show;
sattr->mattr.store = NULL;
sattr->mattr.attr.name = sattr->name;
@@ -1180,6 +1181,7 @@ static void add_notes_attrs(struct module *mod, unsigned int nsect,
if (sect_empty(&sechdrs[i]))
continue;
if (sechdrs[i].sh_type == SHT_NOTE) {
+ sysfs_bin_attr_init(nattr);
nattr->attr.name = mod->sect_attrs->attrs[loaded].name;
nattr->attr.mode = S_IRUGO;
nattr->size = sechdrs[i].sh_size;
@@ -1252,6 +1254,7 @@ int module_add_modinfo_attrs(struct module *mod)
if (!attr->test ||
(attr->test && attr->test(mod))) {
memcpy(temp_attr, attr, sizeof(*temp_attr));
+ sysfs_attr_init(&temp_attr->attr);
error = sysfs_create_file(&mod->mkobj.kobj,&temp_attr->attr);
++temp_attr;
}
diff --git a/kernel/panic.c b/kernel/panic.c
index c787333282b..13d966b4c14 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -36,15 +36,36 @@ ATOMIC_NOTIFIER_HEAD(panic_notifier_list);
EXPORT_SYMBOL(panic_notifier_list);
-static long no_blink(long time)
-{
- return 0;
-}
-
/* Returns how long it waited in ms */
long (*panic_blink)(long time);
EXPORT_SYMBOL(panic_blink);
+static void panic_blink_one_second(void)
+{
+ static long i = 0, end;
+
+ if (panic_blink) {
+ end = i + MSEC_PER_SEC;
+
+ while (i < end) {
+ i += panic_blink(i);
+ mdelay(1);
+ i++;
+ }
+ } else {
+ /*
+ * When running under a hypervisor a small mdelay may get
+ * rounded up to the hypervisor timeslice. For example, with
+ * a 1ms in 10ms hypervisor timeslice we might inflate a
+ * mdelay(1) loop by 10x.
+ *
+ * If we have nothing to blink, spin on 1 second calls to
+ * mdelay to avoid this.
+ */
+ mdelay(MSEC_PER_SEC);
+ }
+}
+
/**
* panic - halt the system
* @fmt: The text string to print
@@ -95,9 +116,6 @@ NORET_TYPE void panic(const char * fmt, ...)
bust_spinlocks(0);
- if (!panic_blink)
- panic_blink = no_blink;
-
if (panic_timeout > 0) {
/*
* Delay timeout seconds before rebooting the machine.
@@ -105,11 +123,9 @@ NORET_TYPE void panic(const char * fmt, ...)
*/
printk(KERN_EMERG "Rebooting in %d seconds..", panic_timeout);
- for (i = 0; i < panic_timeout*1000; ) {
+ for (i = 0; i < panic_timeout; i++) {
touch_nmi_watchdog();
- i += panic_blink(i);
- mdelay(1);
- i++;
+ panic_blink_one_second();
}
/*
* This will not be a clean reboot, with everything
@@ -135,11 +151,9 @@ NORET_TYPE void panic(const char * fmt, ...)
}
#endif
local_irq_enable();
- for (i = 0; ; ) {
+ while (1) {
touch_softlockup_watchdog();
- i += panic_blink(i);
- mdelay(1);
- i++;
+ panic_blink_one_second();
}
}
diff --git a/kernel/params.c b/kernel/params.c
index cf1b6918312..d55a53ec923 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -24,7 +24,6 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/ctype.h>
-#include <linux/string.h>
#if 0
#define DEBUGP printk
@@ -517,6 +516,7 @@ static __modinit int add_sysfs_param(struct module_kobject *mk,
new->grp.attrs = attrs;
/* Tack new one on the end. */
+ sysfs_attr_init(&new->attrs[num].mattr.attr);
new->attrs[num].param = kp;
new->attrs[num].mattr.show = param_attr_show;
new->attrs[num].mattr.store = param_attr_store;
@@ -723,7 +723,7 @@ static ssize_t module_attr_store(struct kobject *kobj,
return ret;
}
-static struct sysfs_ops module_sysfs_ops = {
+static const struct sysfs_ops module_sysfs_ops = {
.show = module_attr_show,
.store = module_attr_store,
};
@@ -737,7 +737,7 @@ static int uevent_filter(struct kset *kset, struct kobject *kobj)
return 0;
}
-static struct kset_uevent_ops module_uevent_ops = {
+static const struct kset_uevent_ops module_uevent_ops = {
.filter = uevent_filter,
};
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index a661e799186..f40560b8654 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -2610,7 +2610,7 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
if (user_locked > user_lock_limit)
extra = user_locked - user_lock_limit;
- lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
+ lock_limit = rlimit(RLIMIT_MEMLOCK);
lock_limit >>= PAGE_SHIFT;
locked = vma->vm_mm->locked_vm + extra;
@@ -5481,13 +5481,16 @@ void __init perf_event_init(void)
register_cpu_notifier(&perf_cpu_nb);
}
-static ssize_t perf_show_reserve_percpu(struct sysdev_class *class, char *buf)
+static ssize_t perf_show_reserve_percpu(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
return sprintf(buf, "%d\n", perf_reserved_percpu);
}
static ssize_t
perf_set_reserve_percpu(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
const char *buf,
size_t count)
{
@@ -5516,13 +5519,17 @@ perf_set_reserve_percpu(struct sysdev_class *class,
return count;
}
-static ssize_t perf_show_overcommit(struct sysdev_class *class, char *buf)
+static ssize_t perf_show_overcommit(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ char *buf)
{
return sprintf(buf, "%d\n", perf_overcommit);
}
static ssize_t
-perf_set_overcommit(struct sysdev_class *class, const char *buf, size_t count)
+perf_set_overcommit(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
+ const char *buf, size_t count)
{
unsigned long val;
int err;
diff --git a/kernel/pid.c b/kernel/pid.c
index b08e697cd83..86b296943e5 100644
--- a/kernel/pid.c
+++ b/kernel/pid.c
@@ -376,7 +376,7 @@ struct task_struct *pid_task(struct pid *pid, enum pid_type type)
EXPORT_SYMBOL(pid_task);
/*
- * Must be called under rcu_read_lock() or with tasklist_lock read-held.
+ * Must be called under rcu_read_lock().
*/
struct task_struct *find_task_by_pid_ns(pid_t nr, struct pid_namespace *ns)
{
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 438ff452351..1a22dfd42df 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -982,6 +982,7 @@ static void check_thread_timers(struct task_struct *tsk,
int maxfire;
struct list_head *timers = tsk->cpu_timers;
struct signal_struct *const sig = tsk->signal;
+ unsigned long soft;
maxfire = 20;
tsk->cputime_expires.prof_exp = cputime_zero;
@@ -1030,9 +1031,10 @@ static void check_thread_timers(struct task_struct *tsk,
/*
* Check for the special case thread timers.
*/
- if (sig->rlim[RLIMIT_RTTIME].rlim_cur != RLIM_INFINITY) {
- unsigned long hard = sig->rlim[RLIMIT_RTTIME].rlim_max;
- unsigned long *soft = &sig->rlim[RLIMIT_RTTIME].rlim_cur;
+ soft = ACCESS_ONCE(sig->rlim[RLIMIT_RTTIME].rlim_cur);
+ if (soft != RLIM_INFINITY) {
+ unsigned long hard =
+ ACCESS_ONCE(sig->rlim[RLIMIT_RTTIME].rlim_max);
if (hard != RLIM_INFINITY &&
tsk->rt.timeout > DIV_ROUND_UP(hard, USEC_PER_SEC/HZ)) {
@@ -1043,14 +1045,13 @@ static void check_thread_timers(struct task_struct *tsk,
__group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
return;
}
- if (tsk->rt.timeout > DIV_ROUND_UP(*soft, USEC_PER_SEC/HZ)) {
+ if (tsk->rt.timeout > DIV_ROUND_UP(soft, USEC_PER_SEC/HZ)) {
/*
* At the soft limit, send a SIGXCPU every second.
*/
- if (sig->rlim[RLIMIT_RTTIME].rlim_cur
- < sig->rlim[RLIMIT_RTTIME].rlim_max) {
- sig->rlim[RLIMIT_RTTIME].rlim_cur +=
- USEC_PER_SEC;
+ if (soft < hard) {
+ soft += USEC_PER_SEC;
+ sig->rlim[RLIMIT_RTTIME].rlim_cur = soft;
}
printk(KERN_INFO
"RT Watchdog Timeout: %s[%d]\n",
@@ -1121,6 +1122,7 @@ static void check_process_timers(struct task_struct *tsk,
unsigned long long sum_sched_runtime, sched_expires;
struct list_head *timers = sig->cpu_timers;
struct task_cputime cputime;
+ unsigned long soft;
/*
* Don't sample the current process CPU clocks if there are no timers.
@@ -1193,11 +1195,13 @@ static void check_process_timers(struct task_struct *tsk,
SIGPROF);
check_cpu_itimer(tsk, &sig->it[CPUCLOCK_VIRT], &virt_expires, utime,
SIGVTALRM);
-
- if (sig->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
+ soft = ACCESS_ONCE(sig->rlim[RLIMIT_CPU].rlim_cur);
+ if (soft != RLIM_INFINITY) {
unsigned long psecs = cputime_to_secs(ptime);
+ unsigned long hard =
+ ACCESS_ONCE(sig->rlim[RLIMIT_CPU].rlim_max);
cputime_t x;
- if (psecs >= sig->rlim[RLIMIT_CPU].rlim_max) {
+ if (psecs >= hard) {
/*
* At the hard limit, we just die.
* No need to calculate anything else now.
@@ -1205,17 +1209,17 @@ static void check_process_timers(struct task_struct *tsk,
__group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
return;
}
- if (psecs >= sig->rlim[RLIMIT_CPU].rlim_cur) {
+ if (psecs >= soft) {
/*
* At the soft limit, send a SIGXCPU every second.
*/
__group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
- if (sig->rlim[RLIMIT_CPU].rlim_cur
- < sig->rlim[RLIMIT_CPU].rlim_max) {
- sig->rlim[RLIMIT_CPU].rlim_cur++;
+ if (soft < hard) {
+ soft++;
+ sig->rlim[RLIMIT_CPU].rlim_cur = soft;
}
}
- x = secs_to_cputime(sig->rlim[RLIMIT_CPU].rlim_cur);
+ x = secs_to_cputime(soft);
if (cputime_eq(prof_expires, cputime_zero) ||
cputime_lt(x, prof_expires)) {
prof_expires = x;
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index bbfe472d752..da5288ec239 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -323,6 +323,7 @@ static int create_image(int platform_mode)
int hibernation_snapshot(int platform_mode)
{
int error;
+ gfp_t saved_mask;
error = platform_begin(platform_mode);
if (error)
@@ -334,6 +335,7 @@ int hibernation_snapshot(int platform_mode)
goto Close;
suspend_console();
+ saved_mask = clear_gfp_allowed_mask(GFP_IOFS);
error = dpm_suspend_start(PMSG_FREEZE);
if (error)
goto Recover_platform;
@@ -351,6 +353,7 @@ int hibernation_snapshot(int platform_mode)
dpm_resume_end(in_suspend ?
(error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
+ set_gfp_allowed_mask(saved_mask);
resume_console();
Close:
platform_end(platform_mode);
@@ -445,14 +448,17 @@ static int resume_target_kernel(bool platform_mode)
int hibernation_restore(int platform_mode)
{
int error;
+ gfp_t saved_mask;
pm_prepare_console();
suspend_console();
+ saved_mask = clear_gfp_allowed_mask(GFP_IOFS);
error = dpm_suspend_start(PMSG_QUIESCE);
if (!error) {
error = resume_target_kernel(platform_mode);
dpm_resume_end(PMSG_RECOVER);
}
+ set_gfp_allowed_mask(saved_mask);
resume_console();
pm_restore_console();
return error;
@@ -466,6 +472,7 @@ int hibernation_restore(int platform_mode)
int hibernation_platform_enter(void)
{
int error;
+ gfp_t saved_mask;
if (!hibernation_ops)
return -ENOSYS;
@@ -481,6 +488,7 @@ int hibernation_platform_enter(void)
entering_platform_hibernation = true;
suspend_console();
+ saved_mask = clear_gfp_allowed_mask(GFP_IOFS);
error = dpm_suspend_start(PMSG_HIBERNATE);
if (error) {
if (hibernation_ops->recover)
@@ -518,6 +526,7 @@ int hibernation_platform_enter(void)
Resume_devices:
entering_platform_hibernation = false;
dpm_resume_end(PMSG_RESTORE);
+ set_gfp_allowed_mask(saved_mask);
resume_console();
Close:
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c
index 6f10dfc2d3e..44cce10b582 100644
--- a/kernel/power/suspend.c
+++ b/kernel/power/suspend.c
@@ -189,6 +189,7 @@ static int suspend_enter(suspend_state_t state)
int suspend_devices_and_enter(suspend_state_t state)
{
int error;
+ gfp_t saved_mask;
if (!suspend_ops)
return -ENOSYS;
@@ -199,6 +200,7 @@ int suspend_devices_and_enter(suspend_state_t state)
goto Close;
}
suspend_console();
+ saved_mask = clear_gfp_allowed_mask(GFP_IOFS);
suspend_test_start();
error = dpm_suspend_start(PMSG_SUSPEND);
if (error) {
@@ -215,6 +217,7 @@ int suspend_devices_and_enter(suspend_state_t state)
suspend_test_start();
dpm_resume_end(PMSG_RESUME);
suspend_test_finish("resume devices");
+ set_gfp_allowed_mask(saved_mask);
resume_console();
Close:
if (suspend_ops->end)
diff --git a/kernel/printk.c b/kernel/printk.c
index 40674122ecf..75077ad0b53 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -70,8 +70,6 @@ int console_printk[4] = {
DEFAULT_CONSOLE_LOGLEVEL, /* default_console_loglevel */
};
-static int saved_console_loglevel = -1;
-
/*
* Low level drivers may need that to know if they can schedule in
* their unblank() callback or not. So let's export it.
@@ -146,6 +144,7 @@ static char __log_buf[__LOG_BUF_LEN];
static char *log_buf = __log_buf;
static int log_buf_len = __LOG_BUF_LEN;
static unsigned logged_chars; /* Number of chars produced since last read+clear operation */
+static int saved_console_loglevel = -1;
#ifdef CONFIG_KEXEC
/*
diff --git a/kernel/relay.c b/kernel/relay.c
index c705a41b4ba..3d97f282161 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -1215,14 +1215,14 @@ static void relay_page_release(struct splice_pipe_desc *spd, unsigned int i)
/*
* subbuf_splice_actor - splice up to one subbuf's worth of data
*/
-static int subbuf_splice_actor(struct file *in,
+static ssize_t subbuf_splice_actor(struct file *in,
loff_t *ppos,
struct pipe_inode_info *pipe,
size_t len,
unsigned int flags,
int *nonpad_ret)
{
- unsigned int pidx, poff, total_len, subbuf_pages, nr_pages, ret;
+ unsigned int pidx, poff, total_len, subbuf_pages, nr_pages;
struct rchan_buf *rbuf = in->private_data;
unsigned int subbuf_size = rbuf->chan->subbuf_size;
uint64_t pos = (uint64_t) *ppos;
@@ -1241,6 +1241,7 @@ static int subbuf_splice_actor(struct file *in,
.ops = &relay_pipe_buf_ops,
.spd_release = relay_page_release,
};
+ ssize_t ret;
if (rbuf->subbufs_produced == rbuf->subbufs_consumed)
return 0;
diff --git a/kernel/sched.c b/kernel/sched.c
index abb36b16b93..150b6988de4 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -4353,7 +4353,7 @@ int can_nice(const struct task_struct *p, const int nice)
/* convert nice value [19,-20] to rlimit style value [1,40] */
int nice_rlim = 20 - nice;
- return (nice_rlim <= p->signal->rlim[RLIMIT_NICE].rlim_cur ||
+ return (nice_rlim <= task_rlimit(p, RLIMIT_NICE) ||
capable(CAP_SYS_NICE));
}
@@ -4530,7 +4530,7 @@ recheck:
if (!lock_task_sighand(p, &flags))
return -ESRCH;
- rlim_rtprio = p->signal->rlim[RLIMIT_RTPRIO].rlim_cur;
+ rlim_rtprio = task_rlimit(p, RLIMIT_RTPRIO);
unlock_task_sighand(p, &flags);
/* can't set/change the rt policy */
@@ -7406,11 +7406,13 @@ static ssize_t sched_power_savings_store(const char *buf, size_t count, int smt)
#ifdef CONFIG_SCHED_MC
static ssize_t sched_mc_power_savings_show(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
char *page)
{
return sprintf(page, "%u\n", sched_mc_power_savings);
}
static ssize_t sched_mc_power_savings_store(struct sysdev_class *class,
+ struct sysdev_class_attribute *attr,
const char *buf, size_t count)
{
return sched_power_savings_store(buf, count, 0);
@@ -7422,11 +7424,13 @@ static SYSDEV_CLASS_ATTR(sched_mc_power_savings, 0644,
#ifdef CONFIG_SCHED_SMT
static ssize_t sched_smt_power_savings_show(struct sysdev_class *dev,
+ struct sysdev_class_attribute *attr,
char *page)
{
return sprintf(page, "%u\n", sched_smt_power_savings);
}
static ssize_t sched_smt_power_savings_store(struct sysdev_class *dev,
+ struct sysdev_class_attribute *attr,
const char *buf, size_t count)
{
return sched_power_savings_store(buf, count, 1);
diff --git a/kernel/sched_cpupri.c b/kernel/sched_cpupri.c
index eeb3506c483..82095bf2099 100644
--- a/kernel/sched_cpupri.c
+++ b/kernel/sched_cpupri.c
@@ -47,7 +47,7 @@ static int convert_prio(int prio)
}
#define for_each_cpupri_active(array, idx) \
- for_each_bit(idx, array, CPUPRI_NR_PRIORITIES)
+ for_each_set_bit(idx, array, CPUPRI_NR_PRIORITIES)
/**
* cpupri_find - find the best (lowest-pri) CPU in the system
diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c
index bf3e38fdbe6..5a6ed1f0990 100644
--- a/kernel/sched_rt.c
+++ b/kernel/sched_rt.c
@@ -1662,8 +1662,9 @@ static void watchdog(struct rq *rq, struct task_struct *p)
if (!p->signal)
return;
- soft = p->signal->rlim[RLIMIT_RTTIME].rlim_cur;
- hard = p->signal->rlim[RLIMIT_RTTIME].rlim_max;
+ /* max may change after cur was read, this will be fixed next tick */
+ soft = task_rlimit(p, RLIMIT_RTTIME);
+ hard = task_rlimit_max(p, RLIMIT_RTTIME);
if (soft != RLIM_INFINITY) {
unsigned long next;
diff --git a/kernel/signal.c b/kernel/signal.c
index 5bb9baffa4f..dbd7fe073c5 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -245,7 +245,7 @@ __sigqueue_alloc(int sig, struct task_struct *t, gfp_t flags, int override_rlimi
if (override_rlimit ||
atomic_read(&user->sigpending) <=
- t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur) {
+ task_rlimit(t, RLIMIT_SIGPENDING)) {
q = kmem_cache_alloc(sigqueue_cachep, flags);
} else {
print_dropped_signal(sig);
diff --git a/kernel/sys.c b/kernel/sys.c
index 877fe4f8e05..9814e43fb23 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -571,8 +571,7 @@ static int set_user(struct cred *new)
if (!new_user)
return -EAGAIN;
- if (atomic_read(&new_user->processes) >=
- current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
+ if (atomic_read(&new_user->processes) >= rlimit(RLIMIT_NPROC) &&
new_user != INIT_USER) {
free_uid(new_user);
return -EAGAIN;
diff --git a/kernel/tsacct.c b/kernel/tsacct.c
index 00d59d048ed..0a67e041edf 100644
--- a/kernel/tsacct.c
+++ b/kernel/tsacct.c
@@ -21,6 +21,7 @@
#include <linux/tsacct_kern.h>
#include <linux/acct.h>
#include <linux/jiffies.h>
+#include <linux/mm.h>
/*
* fill in basic accounting fields
diff --git a/lib/Kconfig b/lib/Kconfig
index 97b136ff117..170d8ca901d 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -160,6 +160,9 @@ config TEXTSEARCH_BM
config TEXTSEARCH_FSM
tristate
+config BTREE
+ boolean
+
config HAS_IOMEM
boolean
depends on !NO_IOMEM
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 5e3407d997b..b520ec1f33c 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -864,8 +864,7 @@ config DEBUG_FORCE_WEAK_PER_CPU
config LKDTM
tristate "Linux Kernel Dump Test Tool Module"
- depends on DEBUG_KERNEL
- depends on KPROBES
+ depends on DEBUG_FS
depends on BLOCK
default n
help
@@ -876,7 +875,7 @@ config LKDTM
called lkdtm.
Documentation on how to use the module can be found in
- drivers/misc/lkdtm.c
+ Documentation/fault-injection/provoke-crashes.txt
config FAULT_INJECTION
bool "Fault-injection framework"
diff --git a/lib/Makefile b/lib/Makefile
index 3b0b4a696db..2e152aed719 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -41,6 +41,7 @@ lib-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_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_BTREE) += btree.o
obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
obj-$(CONFIG_DEBUG_LIST) += list_debug.o
obj-$(CONFIG_DEBUG_OBJECTS) += debugobjects.o
diff --git a/lib/bitmap.c b/lib/bitmap.c
index 11bf4975058..ffb78c916cc 100644
--- a/lib/bitmap.c
+++ b/lib/bitmap.c
@@ -487,7 +487,7 @@ int __bitmap_parse(const char *buf, unsigned int buflen,
EXPORT_SYMBOL(__bitmap_parse);
/**
- * bitmap_parse_user()
+ * bitmap_parse_user - convert an ASCII hex string in a user buffer into a bitmap
*
* @ubuf: pointer to user buffer containing string.
* @ulen: buffer size in bytes. If string is smaller than this
@@ -619,7 +619,7 @@ int bitmap_parselist(const char *bp, unsigned long *maskp, int nmaskbits)
EXPORT_SYMBOL(bitmap_parselist);
/**
- * bitmap_pos_to_ord(buf, pos, bits)
+ * bitmap_pos_to_ord - find ordinal of set bit at given position in bitmap
* @buf: pointer to a bitmap
* @pos: a bit position in @buf (0 <= @pos < @bits)
* @bits: number of valid bit positions in @buf
@@ -655,7 +655,7 @@ static int bitmap_pos_to_ord(const unsigned long *buf, int pos, int bits)
}
/**
- * bitmap_ord_to_pos(buf, ord, bits)
+ * bitmap_ord_to_pos - find position of n-th set bit in bitmap
* @buf: pointer to bitmap
* @ord: ordinal bit position (n-th set bit, n >= 0)
* @bits: number of valid bit positions in @buf
@@ -733,10 +733,9 @@ void bitmap_remap(unsigned long *dst, const unsigned long *src,
bitmap_zero(dst, bits);
w = bitmap_weight(new, bits);
- for (oldbit = find_first_bit(src, bits);
- oldbit < bits;
- oldbit = find_next_bit(src, bits, oldbit + 1)) {
+ for_each_set_bit(oldbit, src, bits) {
int n = bitmap_pos_to_ord(old, oldbit, bits);
+
if (n < 0 || w == 0)
set_bit(oldbit, dst); /* identity map */
else
@@ -903,9 +902,7 @@ void bitmap_onto(unsigned long *dst, const unsigned long *orig,
*/
m = 0;
- for (n = find_first_bit(relmap, bits);
- n < bits;
- n = find_next_bit(relmap, bits, n + 1)) {
+ for_each_set_bit(n, relmap, bits) {
/* m == bitmap_pos_to_ord(relmap, n, bits) */
if (test_bit(m, orig))
set_bit(n, dst);
@@ -934,9 +931,7 @@ void bitmap_fold(unsigned long *dst, const unsigned long *orig,
return;
bitmap_zero(dst, bits);
- for (oldbit = find_first_bit(orig, bits);
- oldbit < bits;
- oldbit = find_next_bit(orig, bits, oldbit + 1))
+ for_each_set_bit(oldbit, orig, bits)
set_bit(oldbit % sz, dst);
}
EXPORT_SYMBOL(bitmap_fold);
diff --git a/lib/btree.c b/lib/btree.c
new file mode 100644
index 00000000000..41859a82021
--- /dev/null
+++ b/lib/btree.c
@@ -0,0 +1,797 @@
+/*
+ * lib/btree.c - Simple In-memory B+Tree
+ *
+ * As should be obvious for Linux kernel code, license is GPLv2
+ *
+ * Copyright (c) 2007-2008 Joern Engel <joern@logfs.org>
+ * Bits and pieces stolen from Peter Zijlstra's code, which is
+ * Copyright 2007, Red Hat Inc. Peter Zijlstra <pzijlstr@redhat.com>
+ * GPLv2
+ *
+ * see http://programming.kicks-ass.net/kernel-patches/vma_lookup/btree.patch
+ *
+ * A relatively simple B+Tree implementation. I have written it as a learning
+ * excercise to understand how B+Trees work. Turned out to be useful as well.
+ *
+ * B+Trees can be used similar to Linux radix trees (which don't have anything
+ * in common with textbook radix trees, beware). Prerequisite for them working
+ * well is that access to a random tree node is much faster than a large number
+ * of operations within each node.
+ *
+ * Disks have fulfilled the prerequisite for a long time. More recently DRAM
+ * has gained similar properties, as memory access times, when measured in cpu
+ * cycles, have increased. Cacheline sizes have increased as well, which also
+ * helps B+Trees.
+ *
+ * Compared to radix trees, B+Trees are more efficient when dealing with a
+ * sparsely populated address space. Between 25% and 50% of the memory is
+ * occupied with valid pointers. When densely populated, radix trees contain
+ * ~98% pointers - hard to beat. Very sparse radix trees contain only ~2%
+ * pointers.
+ *
+ * This particular implementation stores pointers identified by a long value.
+ * Storing NULL pointers is illegal, lookup will return NULL when no entry
+ * was found.
+ *
+ * A tricks was used that is not commonly found in textbooks. The lowest
+ * values are to the right, not to the left. All used slots within a node
+ * are on the left, all unused slots contain NUL values. Most operations
+ * simply loop once over all slots and terminate on the first NUL.
+ */
+
+#include <linux/btree.h>
+#include <linux/cache.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define NODESIZE MAX(L1_CACHE_BYTES, 128)
+
+struct btree_geo {
+ int keylen;
+ int no_pairs;
+ int no_longs;
+};
+
+struct btree_geo btree_geo32 = {
+ .keylen = 1,
+ .no_pairs = NODESIZE / sizeof(long) / 2,
+ .no_longs = NODESIZE / sizeof(long) / 2,
+};
+EXPORT_SYMBOL_GPL(btree_geo32);
+
+#define LONG_PER_U64 (64 / BITS_PER_LONG)
+struct btree_geo btree_geo64 = {
+ .keylen = LONG_PER_U64,
+ .no_pairs = NODESIZE / sizeof(long) / (1 + LONG_PER_U64),
+ .no_longs = LONG_PER_U64 * (NODESIZE / sizeof(long) / (1 + LONG_PER_U64)),
+};
+EXPORT_SYMBOL_GPL(btree_geo64);
+
+struct btree_geo btree_geo128 = {
+ .keylen = 2 * LONG_PER_U64,
+ .no_pairs = NODESIZE / sizeof(long) / (1 + 2 * LONG_PER_U64),
+ .no_longs = 2 * LONG_PER_U64 * (NODESIZE / sizeof(long) / (1 + 2 * LONG_PER_U64)),
+};
+EXPORT_SYMBOL_GPL(btree_geo128);
+
+static struct kmem_cache *btree_cachep;
+
+void *btree_alloc(gfp_t gfp_mask, void *pool_data)
+{
+ return kmem_cache_alloc(btree_cachep, gfp_mask);
+}
+EXPORT_SYMBOL_GPL(btree_alloc);
+
+void btree_free(void *element, void *pool_data)
+{
+ kmem_cache_free(btree_cachep, element);
+}
+EXPORT_SYMBOL_GPL(btree_free);
+
+static unsigned long *btree_node_alloc(struct btree_head *head, gfp_t gfp)
+{
+ unsigned long *node;
+
+ node = mempool_alloc(head->mempool, gfp);
+ memset(node, 0, NODESIZE);
+ return node;
+}
+
+static int longcmp(const unsigned long *l1, const unsigned long *l2, size_t n)
+{
+ size_t i;
+
+ for (i = 0; i < n; i++) {
+ if (l1[i] < l2[i])
+ return -1;
+ if (l1[i] > l2[i])
+ return 1;
+ }
+ return 0;
+}
+
+static unsigned long *longcpy(unsigned long *dest, const unsigned long *src,
+ size_t n)
+{
+ size_t i;
+
+ for (i = 0; i < n; i++)
+ dest[i] = src[i];
+ return dest;
+}
+
+static unsigned long *longset(unsigned long *s, unsigned long c, size_t n)
+{
+ size_t i;
+
+ for (i = 0; i < n; i++)
+ s[i] = c;
+ return s;
+}
+
+static void dec_key(struct btree_geo *geo, unsigned long *key)
+{
+ unsigned long val;
+ int i;
+
+ for (i = geo->keylen - 1; i >= 0; i--) {
+ val = key[i];
+ key[i] = val - 1;
+ if (val)
+ break;
+ }
+}
+
+static unsigned long *bkey(struct btree_geo *geo, unsigned long *node, int n)
+{
+ return &node[n * geo->keylen];
+}
+
+static void *bval(struct btree_geo *geo, unsigned long *node, int n)
+{
+ return (void *)node[geo->no_longs + n];
+}
+
+static void setkey(struct btree_geo *geo, unsigned long *node, int n,
+ unsigned long *key)
+{
+ longcpy(bkey(geo, node, n), key, geo->keylen);
+}
+
+static void setval(struct btree_geo *geo, unsigned long *node, int n,
+ void *val)
+{
+ node[geo->no_longs + n] = (unsigned long) val;
+}
+
+static void clearpair(struct btree_geo *geo, unsigned long *node, int n)
+{
+ longset(bkey(geo, node, n), 0, geo->keylen);
+ node[geo->no_longs + n] = 0;
+}
+
+static inline void __btree_init(struct btree_head *head)
+{
+ head->node = NULL;
+ head->height = 0;
+}
+
+void btree_init_mempool(struct btree_head *head, mempool_t *mempool)
+{
+ __btree_init(head);
+ head->mempool = mempool;
+}
+EXPORT_SYMBOL_GPL(btree_init_mempool);
+
+int btree_init(struct btree_head *head)
+{
+ __btree_init(head);
+ head->mempool = mempool_create(0, btree_alloc, btree_free, NULL);
+ if (!head->mempool)
+ return -ENOMEM;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(btree_init);
+
+void btree_destroy(struct btree_head *head)
+{
+ mempool_destroy(head->mempool);
+ head->mempool = NULL;
+}
+EXPORT_SYMBOL_GPL(btree_destroy);
+
+void *btree_last(struct btree_head *head, struct btree_geo *geo,
+ unsigned long *key)
+{
+ int height = head->height;
+ unsigned long *node = head->node;
+
+ if (height == 0)
+ return NULL;
+
+ for ( ; height > 1; height--)
+ node = bval(geo, node, 0);
+
+ longcpy(key, bkey(geo, node, 0), geo->keylen);
+ return bval(geo, node, 0);
+}
+EXPORT_SYMBOL_GPL(btree_last);
+
+static int keycmp(struct btree_geo *geo, unsigned long *node, int pos,
+ unsigned long *key)
+{
+ return longcmp(bkey(geo, node, pos), key, geo->keylen);
+}
+
+static int keyzero(struct btree_geo *geo, unsigned long *key)
+{
+ int i;
+
+ for (i = 0; i < geo->keylen; i++)
+ if (key[i])
+ return 0;
+
+ return 1;
+}
+
+void *btree_lookup(struct btree_head *head, struct btree_geo *geo,
+ unsigned long *key)
+{
+ int i, height = head->height;
+ unsigned long *node = head->node;
+
+ if (height == 0)
+ return NULL;
+
+ for ( ; height > 1; height--) {
+ for (i = 0; i < geo->no_pairs; i++)
+ if (keycmp(geo, node, i, key) <= 0)
+ break;
+ if (i == geo->no_pairs)
+ return NULL;
+ node = bval(geo, node, i);
+ if (!node)
+ return NULL;
+ }
+
+ if (!node)
+ return NULL;
+
+ for (i = 0; i < geo->no_pairs; i++)
+ if (keycmp(geo, node, i, key) == 0)
+ return bval(geo, node, i);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(btree_lookup);
+
+int btree_update(struct btree_head *head, struct btree_geo *geo,
+ unsigned long *key, void *val)
+{
+ int i, height = head->height;
+ unsigned long *node = head->node;
+
+ if (height == 0)
+ return -ENOENT;
+
+ for ( ; height > 1; height--) {
+ for (i = 0; i < geo->no_pairs; i++)
+ if (keycmp(geo, node, i, key) <= 0)
+ break;
+ if (i == geo->no_pairs)
+ return -ENOENT;
+ node = bval(geo, node, i);
+ if (!node)
+ return -ENOENT;
+ }
+
+ if (!node)
+ return -ENOENT;
+
+ for (i = 0; i < geo->no_pairs; i++)
+ if (keycmp(geo, node, i, key) == 0) {
+ setval(geo, node, i, val);
+ return 0;
+ }
+ return -ENOENT;
+}
+EXPORT_SYMBOL_GPL(btree_update);
+
+/*
+ * Usually this function is quite similar to normal lookup. But the key of
+ * a parent node may be smaller than the smallest key of all its siblings.
+ * In such a case we cannot just return NULL, as we have only proven that no
+ * key smaller than __key, but larger than this parent key exists.
+ * So we set __key to the parent key and retry. We have to use the smallest
+ * such parent key, which is the last parent key we encountered.
+ */
+void *btree_get_prev(struct btree_head *head, struct btree_geo *geo,
+ unsigned long *__key)
+{
+ int i, height;
+ unsigned long *node, *oldnode;
+ unsigned long *retry_key = NULL, key[geo->keylen];
+
+ if (keyzero(geo, __key))
+ return NULL;
+
+ if (head->height == 0)
+ return NULL;
+retry:
+ longcpy(key, __key, geo->keylen);
+ dec_key(geo, key);
+
+ node = head->node;
+ for (height = head->height ; height > 1; height--) {
+ for (i = 0; i < geo->no_pairs; i++)
+ if (keycmp(geo, node, i, key) <= 0)
+ break;
+ if (i == geo->no_pairs)
+ goto miss;
+ oldnode = node;
+ node = bval(geo, node, i);
+ if (!node)
+ goto miss;
+ retry_key = bkey(geo, oldnode, i);
+ }
+
+ if (!node)
+ goto miss;
+
+ for (i = 0; i < geo->no_pairs; i++) {
+ if (keycmp(geo, node, i, key) <= 0) {
+ if (bval(geo, node, i)) {
+ longcpy(__key, bkey(geo, node, i), geo->keylen);
+ return bval(geo, node, i);
+ } else
+ goto miss;
+ }
+ }
+miss:
+ if (retry_key) {
+ __key = retry_key;
+ retry_key = NULL;
+ goto retry;
+ }
+ return NULL;
+}
+
+static int getpos(struct btree_geo *geo, unsigned long *node,
+ unsigned long *key)
+{
+ int i;
+
+ for (i = 0; i < geo->no_pairs; i++) {
+ if (keycmp(geo, node, i, key) <= 0)
+ break;
+ }
+ return i;
+}
+
+static int getfill(struct btree_geo *geo, unsigned long *node, int start)
+{
+ int i;
+
+ for (i = start; i < geo->no_pairs; i++)
+ if (!bval(geo, node, i))
+ break;
+ return i;
+}
+
+/*
+ * locate the correct leaf node in the btree
+ */
+static unsigned long *find_level(struct btree_head *head, struct btree_geo *geo,
+ unsigned long *key, int level)
+{
+ unsigned long *node = head->node;
+ int i, height;
+
+ for (height = head->height; height > level; height--) {
+ for (i = 0; i < geo->no_pairs; i++)
+ if (keycmp(geo, node, i, key) <= 0)
+ break;
+
+ if ((i == geo->no_pairs) || !bval(geo, node, i)) {
+ /* right-most key is too large, update it */
+ /* FIXME: If the right-most key on higher levels is
+ * always zero, this wouldn't be necessary. */
+ i--;
+ setkey(geo, node, i, key);
+ }
+ BUG_ON(i < 0);
+ node = bval(geo, node, i);
+ }
+ BUG_ON(!node);
+ return node;
+}
+
+static int btree_grow(struct btree_head *head, struct btree_geo *geo,
+ gfp_t gfp)
+{
+ unsigned long *node;
+ int fill;
+
+ node = btree_node_alloc(head, gfp);
+ if (!node)
+ return -ENOMEM;
+ if (head->node) {
+ fill = getfill(geo, head->node, 0);
+ setkey(geo, node, 0, bkey(geo, head->node, fill - 1));
+ setval(geo, node, 0, head->node);
+ }
+ head->node = node;
+ head->height++;
+ return 0;
+}
+
+static void btree_shrink(struct btree_head *head, struct btree_geo *geo)
+{
+ unsigned long *node;
+ int fill;
+
+ if (head->height <= 1)
+ return;
+
+ node = head->node;
+ fill = getfill(geo, node, 0);
+ BUG_ON(fill > 1);
+ head->node = bval(geo, node, 0);
+ head->height--;
+ mempool_free(node, head->mempool);
+}
+
+static int btree_insert_level(struct btree_head *head, struct btree_geo *geo,
+ unsigned long *key, void *val, int level,
+ gfp_t gfp)
+{
+ unsigned long *node;
+ int i, pos, fill, err;
+
+ BUG_ON(!val);
+ if (head->height < level) {
+ err = btree_grow(head, geo, gfp);
+ if (err)
+ return err;
+ }
+
+retry:
+ node = find_level(head, geo, key, level);
+ pos = getpos(geo, node, key);
+ fill = getfill(geo, node, pos);
+ /* two identical keys are not allowed */
+ BUG_ON(pos < fill && keycmp(geo, node, pos, key) == 0);
+
+ if (fill == geo->no_pairs) {
+ /* need to split node */
+ unsigned long *new;
+
+ new = btree_node_alloc(head, gfp);
+ if (!new)
+ return -ENOMEM;
+ err = btree_insert_level(head, geo,
+ bkey(geo, node, fill / 2 - 1),
+ new, level + 1, gfp);
+ if (err) {
+ mempool_free(new, head->mempool);
+ return err;
+ }
+ for (i = 0; i < fill / 2; i++) {
+ setkey(geo, new, i, bkey(geo, node, i));
+ setval(geo, new, i, bval(geo, node, i));
+ setkey(geo, node, i, bkey(geo, node, i + fill / 2));
+ setval(geo, node, i, bval(geo, node, i + fill / 2));
+ clearpair(geo, node, i + fill / 2);
+ }
+ if (fill & 1) {
+ setkey(geo, node, i, bkey(geo, node, fill - 1));
+ setval(geo, node, i, bval(geo, node, fill - 1));
+ clearpair(geo, node, fill - 1);
+ }
+ goto retry;
+ }
+ BUG_ON(fill >= geo->no_pairs);
+
+ /* shift and insert */
+ for (i = fill; i > pos; i--) {
+ setkey(geo, node, i, bkey(geo, node, i - 1));
+ setval(geo, node, i, bval(geo, node, i - 1));
+ }
+ setkey(geo, node, pos, key);
+ setval(geo, node, pos, val);
+
+ return 0;
+}
+
+int btree_insert(struct btree_head *head, struct btree_geo *geo,
+ unsigned long *key, void *val, gfp_t gfp)
+{
+ return btree_insert_level(head, geo, key, val, 1, gfp);
+}
+EXPORT_SYMBOL_GPL(btree_insert);
+
+static void *btree_remove_level(struct btree_head *head, struct btree_geo *geo,
+ unsigned long *key, int level);
+static void merge(struct btree_head *head, struct btree_geo *geo, int level,
+ unsigned long *left, int lfill,
+ unsigned long *right, int rfill,
+ unsigned long *parent, int lpos)
+{
+ int i;
+
+ for (i = 0; i < rfill; i++) {
+ /* Move all keys to the left */
+ setkey(geo, left, lfill + i, bkey(geo, right, i));
+ setval(geo, left, lfill + i, bval(geo, right, i));
+ }
+ /* Exchange left and right child in parent */
+ setval(geo, parent, lpos, right);
+ setval(geo, parent, lpos + 1, left);
+ /* Remove left (formerly right) child from parent */
+ btree_remove_level(head, geo, bkey(geo, parent, lpos), level + 1);
+ mempool_free(right, head->mempool);
+}
+
+static void rebalance(struct btree_head *head, struct btree_geo *geo,
+ unsigned long *key, int level, unsigned long *child, int fill)
+{
+ unsigned long *parent, *left = NULL, *right = NULL;
+ int i, no_left, no_right;
+
+ if (fill == 0) {
+ /* Because we don't steal entries from a neigbour, this case
+ * can happen. Parent node contains a single child, this
+ * node, so merging with a sibling never happens.
+ */
+ btree_remove_level(head, geo, key, level + 1);
+ mempool_free(child, head->mempool);
+ return;
+ }
+
+ parent = find_level(head, geo, key, level + 1);
+ i = getpos(geo, parent, key);
+ BUG_ON(bval(geo, parent, i) != child);
+
+ if (i > 0) {
+ left = bval(geo, parent, i - 1);
+ no_left = getfill(geo, left, 0);
+ if (fill + no_left <= geo->no_pairs) {
+ merge(head, geo, level,
+ left, no_left,
+ child, fill,
+ parent, i - 1);
+ return;
+ }
+ }
+ if (i + 1 < getfill(geo, parent, i)) {
+ right = bval(geo, parent, i + 1);
+ no_right = getfill(geo, right, 0);
+ if (fill + no_right <= geo->no_pairs) {
+ merge(head, geo, level,
+ child, fill,
+ right, no_right,
+ parent, i);
+ return;
+ }
+ }
+ /*
+ * We could also try to steal one entry from the left or right
+ * neighbor. By not doing so we changed the invariant from
+ * "all nodes are at least half full" to "no two neighboring
+ * nodes can be merged". Which means that the average fill of
+ * all nodes is still half or better.
+ */
+}
+
+static void *btree_remove_level(struct btree_head *head, struct btree_geo *geo,
+ unsigned long *key, int level)
+{
+ unsigned long *node;
+ int i, pos, fill;
+ void *ret;
+
+ if (level > head->height) {
+ /* we recursed all the way up */
+ head->height = 0;
+ head->node = NULL;
+ return NULL;
+ }
+
+ node = find_level(head, geo, key, level);
+ pos = getpos(geo, node, key);
+ fill = getfill(geo, node, pos);
+ if ((level == 1) && (keycmp(geo, node, pos, key) != 0))
+ return NULL;
+ ret = bval(geo, node, pos);
+
+ /* remove and shift */
+ for (i = pos; i < fill - 1; i++) {
+ setkey(geo, node, i, bkey(geo, node, i + 1));
+ setval(geo, node, i, bval(geo, node, i + 1));
+ }
+ clearpair(geo, node, fill - 1);
+
+ if (fill - 1 < geo->no_pairs / 2) {
+ if (level < head->height)
+ rebalance(head, geo, key, level, node, fill - 1);
+ else if (fill - 1 == 1)
+ btree_shrink(head, geo);
+ }
+
+ return ret;
+}
+
+void *btree_remove(struct btree_head *head, struct btree_geo *geo,
+ unsigned long *key)
+{
+ if (head->height == 0)
+ return NULL;
+
+ return btree_remove_level(head, geo, key, 1);
+}
+EXPORT_SYMBOL_GPL(btree_remove);
+
+int btree_merge(struct btree_head *target, struct btree_head *victim,
+ struct btree_geo *geo, gfp_t gfp)
+{
+ unsigned long key[geo->keylen];
+ unsigned long dup[geo->keylen];
+ void *val;
+ int err;
+
+ BUG_ON(target == victim);
+
+ if (!(target->node)) {
+ /* target is empty, just copy fields over */
+ target->node = victim->node;
+ target->height = victim->height;
+ __btree_init(victim);
+ return 0;
+ }
+
+ /* TODO: This needs some optimizations. Currently we do three tree
+ * walks to remove a single object from the victim.
+ */
+ for (;;) {
+ if (!btree_last(victim, geo, key))
+ break;
+ val = btree_lookup(victim, geo, key);
+ err = btree_insert(target, geo, key, val, gfp);
+ if (err)
+ return err;
+ /* We must make a copy of the key, as the original will get
+ * mangled inside btree_remove. */
+ longcpy(dup, key, geo->keylen);
+ btree_remove(victim, geo, dup);
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(btree_merge);
+
+static size_t __btree_for_each(struct btree_head *head, struct btree_geo *geo,
+ unsigned long *node, unsigned long opaque,
+ void (*func)(void *elem, unsigned long opaque,
+ unsigned long *key, size_t index,
+ void *func2),
+ void *func2, int reap, int height, size_t count)
+{
+ int i;
+ unsigned long *child;
+
+ for (i = 0; i < geo->no_pairs; i++) {
+ child = bval(geo, node, i);
+ if (!child)
+ break;
+ if (height > 1)
+ count = __btree_for_each(head, geo, child, opaque,
+ func, func2, reap, height - 1, count);
+ else
+ func(child, opaque, bkey(geo, node, i), count++,
+ func2);
+ }
+ if (reap)
+ mempool_free(node, head->mempool);
+ return count;
+}
+
+static void empty(void *elem, unsigned long opaque, unsigned long *key,
+ size_t index, void *func2)
+{
+}
+
+void visitorl(void *elem, unsigned long opaque, unsigned long *key,
+ size_t index, void *__func)
+{
+ visitorl_t func = __func;
+
+ func(elem, opaque, *key, index);
+}
+EXPORT_SYMBOL_GPL(visitorl);
+
+void visitor32(void *elem, unsigned long opaque, unsigned long *__key,
+ size_t index, void *__func)
+{
+ visitor32_t func = __func;
+ u32 *key = (void *)__key;
+
+ func(elem, opaque, *key, index);
+}
+EXPORT_SYMBOL_GPL(visitor32);
+
+void visitor64(void *elem, unsigned long opaque, unsigned long *__key,
+ size_t index, void *__func)
+{
+ visitor64_t func = __func;
+ u64 *key = (void *)__key;
+
+ func(elem, opaque, *key, index);
+}
+EXPORT_SYMBOL_GPL(visitor64);
+
+void visitor128(void *elem, unsigned long opaque, unsigned long *__key,
+ size_t index, void *__func)
+{
+ visitor128_t func = __func;
+ u64 *key = (void *)__key;
+
+ func(elem, opaque, key[0], key[1], index);
+}
+EXPORT_SYMBOL_GPL(visitor128);
+
+size_t btree_visitor(struct btree_head *head, struct btree_geo *geo,
+ unsigned long opaque,
+ void (*func)(void *elem, unsigned long opaque,
+ unsigned long *key,
+ size_t index, void *func2),
+ void *func2)
+{
+ size_t count = 0;
+
+ if (!func2)
+ func = empty;
+ if (head->node)
+ count = __btree_for_each(head, geo, head->node, opaque, func,
+ func2, 0, head->height, 0);
+ return count;
+}
+EXPORT_SYMBOL_GPL(btree_visitor);
+
+size_t btree_grim_visitor(struct btree_head *head, struct btree_geo *geo,
+ unsigned long opaque,
+ void (*func)(void *elem, unsigned long opaque,
+ unsigned long *key,
+ size_t index, void *func2),
+ void *func2)
+{
+ size_t count = 0;
+
+ if (!func2)
+ func = empty;
+ if (head->node)
+ count = __btree_for_each(head, geo, head->node, opaque, func,
+ func2, 1, head->height, 0);
+ __btree_init(head);
+ return count;
+}
+EXPORT_SYMBOL_GPL(btree_grim_visitor);
+
+static int __init btree_module_init(void)
+{
+ btree_cachep = kmem_cache_create("btree_node", NODESIZE, 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+ return 0;
+}
+
+static void __exit btree_module_exit(void)
+{
+ kmem_cache_destroy(btree_cachep);
+}
+
+/* If core code starts using btree, initialization should happen even earlier */
+module_init(btree_module_init);
+module_exit(btree_module_exit);
+
+MODULE_AUTHOR("Joern Engel <joern@logfs.org>");
+MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
+MODULE_LICENSE("GPL");
diff --git a/lib/crc32.c b/lib/crc32.c
index 02e3b31b3a7..0f45fbff34c 100644
--- a/lib/crc32.c
+++ b/lib/crc32.c
@@ -30,11 +30,15 @@
#include <asm/atomic.h>
#include "crc32defs.h"
#if CRC_LE_BITS == 8
-#define tole(x) __constant_cpu_to_le32(x)
-#define tobe(x) __constant_cpu_to_be32(x)
+# define tole(x) __constant_cpu_to_le32(x)
#else
-#define tole(x) (x)
-#define tobe(x) (x)
+# define tole(x) (x)
+#endif
+
+#if CRC_BE_BITS == 8
+# define tobe(x) __constant_cpu_to_be32(x)
+#else
+# define tobe(x) (x)
#endif
#include "crc32table.h"
@@ -52,20 +56,19 @@ crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 *tab)
# else
# define DO_CRC(x) crc = tab[((crc >> 24) ^ (x)) & 255] ^ (crc << 8)
# endif
- const u32 *b = (const u32 *)buf;
+ const u32 *b;
size_t rem_len;
/* Align it */
- if (unlikely((long)b & 3 && len)) {
- u8 *p = (u8 *)b;
+ if (unlikely((long)buf & 3 && len)) {
do {
- DO_CRC(*p++);
- } while ((--len) && ((long)p)&3);
- b = (u32 *)p;
+ DO_CRC(*buf++);
+ } while ((--len) && ((long)buf)&3);
}
rem_len = len & 3;
/* load data 32 bits wide, xor data 32 bits wide. */
len = len >> 2;
+ b = (const u32 *)buf;
for (--b; len; --len) {
crc ^= *++b; /* use pre increment for speed */
DO_CRC(0);
@@ -82,6 +85,7 @@ crc32_body(u32 crc, unsigned char const *buf, size_t len, const u32 *tab)
} while (--len);
}
return crc;
+#undef DO_CRC
}
#endif
/**
@@ -119,9 +123,6 @@ u32 __pure crc32_le(u32 crc, unsigned char const *p, size_t len)
crc = __cpu_to_le32(crc);
crc = crc32_body(crc, p, len, tab);
return __le32_to_cpu(crc);
-#undef ENDIAN_SHIFT
-#undef DO_CRC
-
# elif CRC_LE_BITS == 4
while (len--) {
crc ^= *p++;
@@ -179,9 +180,6 @@ u32 __pure crc32_be(u32 crc, unsigned char const *p, size_t len)
crc = __cpu_to_be32(crc);
crc = crc32_body(crc, p, len, tab);
return __be32_to_cpu(crc);
-#undef ENDIAN_SHIFT
-#undef DO_CRC
-
# elif CRC_BE_BITS == 4
while (len--) {
crc ^= *p++ << 24;
diff --git a/lib/kobject.c b/lib/kobject.c
index b512b746d2a..8115eb1bbf4 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -700,7 +700,7 @@ static ssize_t kobj_attr_store(struct kobject *kobj, struct attribute *attr,
return ret;
}
-struct sysfs_ops kobj_sysfs_ops = {
+const struct sysfs_ops kobj_sysfs_ops = {
.show = kobj_attr_show,
.store = kobj_attr_store,
};
@@ -789,7 +789,7 @@ static struct kobj_type kset_ktype = {
* If the kset was not able to be created, NULL will be returned.
*/
static struct kset *kset_create(const char *name,
- struct kset_uevent_ops *uevent_ops,
+ const struct kset_uevent_ops *uevent_ops,
struct kobject *parent_kobj)
{
struct kset *kset;
@@ -832,7 +832,7 @@ static struct kset *kset_create(const char *name,
* If the kset was not able to be created, NULL will be returned.
*/
struct kset *kset_create_and_add(const char *name,
- struct kset_uevent_ops *uevent_ops,
+ const struct kset_uevent_ops *uevent_ops,
struct kobject *parent_kobj)
{
struct kset *kset;
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index 920a3ca6e25..c9d3a3e8405 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -95,7 +95,7 @@ int kobject_uevent_env(struct kobject *kobj, enum kobject_action action,
const char *subsystem;
struct kobject *top_kobj;
struct kset *kset;
- struct kset_uevent_ops *uevent_ops;
+ const struct kset_uevent_ops *uevent_ops;
u64 seq;
int i = 0;
int retval = 0;
diff --git a/lib/list_sort.c b/lib/list_sort.c
index 19d11e0bb95..4b5cb794c38 100644
--- a/lib/list_sort.c
+++ b/lib/list_sort.c
@@ -4,99 +4,214 @@
#include <linux/slab.h>
#include <linux/list.h>
+#define MAX_LIST_LENGTH_BITS 20
+
+/*
+ * Returns a list organized in an intermediate format suited
+ * to chaining of merge() calls: null-terminated, no reserved or
+ * sentinel head node, "prev" links not maintained.
+ */
+static struct list_head *merge(void *priv,
+ int (*cmp)(void *priv, struct list_head *a,
+ struct list_head *b),
+ struct list_head *a, struct list_head *b)
+{
+ struct list_head head, *tail = &head;
+
+ while (a && b) {
+ /* if equal, take 'a' -- important for sort stability */
+ if ((*cmp)(priv, a, b) <= 0) {
+ tail->next = a;
+ a = a->next;
+ } else {
+ tail->next = b;
+ b = b->next;
+ }
+ tail = tail->next;
+ }
+ tail->next = a?:b;
+ return head.next;
+}
+
+/*
+ * Combine final list merge with restoration of standard doubly-linked
+ * list structure. This approach duplicates code from merge(), but
+ * runs faster than the tidier alternatives of either a separate final
+ * prev-link restoration pass, or maintaining the prev links
+ * throughout.
+ */
+static void merge_and_restore_back_links(void *priv,
+ int (*cmp)(void *priv, struct list_head *a,
+ struct list_head *b),
+ struct list_head *head,
+ struct list_head *a, struct list_head *b)
+{
+ struct list_head *tail = head;
+
+ while (a && b) {
+ /* if equal, take 'a' -- important for sort stability */
+ if ((*cmp)(priv, a, b) <= 0) {
+ tail->next = a;
+ a->prev = tail;
+ a = a->next;
+ } else {
+ tail->next = b;
+ b->prev = tail;
+ b = b->next;
+ }
+ tail = tail->next;
+ }
+ tail->next = a ? : b;
+
+ do {
+ /*
+ * In worst cases this loop may run many iterations.
+ * Continue callbacks to the client even though no
+ * element comparison is needed, so the client's cmp()
+ * routine can invoke cond_resched() periodically.
+ */
+ (*cmp)(priv, tail, tail);
+
+ tail->next->prev = tail;
+ tail = tail->next;
+ } while (tail->next);
+
+ tail->next = head;
+ head->prev = tail;
+}
+
/**
- * list_sort - sort a list.
- * @priv: private data, passed to @cmp
+ * list_sort - sort a list
+ * @priv: private data, opaque to list_sort(), passed to @cmp
* @head: the list to sort
* @cmp: the elements comparison function
*
- * This function has been implemented by Mark J Roberts <mjr@znex.org>. It
- * implements "merge sort" which has O(nlog(n)) complexity. The list is sorted
- * in ascending order.
+ * This function implements "merge sort", which has O(nlog(n))
+ * complexity.
*
- * The comparison function @cmp is supposed to return a negative value if @a is
- * less than @b, and a positive value if @a is greater than @b. If @a and @b
- * are equivalent, then it does not matter what this function returns.
+ * The comparison function @cmp must return a negative value if @a
+ * should sort before @b, and a positive value if @a should sort after
+ * @b. If @a and @b are equivalent, and their original relative
+ * ordering is to be preserved, @cmp must return 0.
*/
void list_sort(void *priv, struct list_head *head,
- int (*cmp)(void *priv, struct list_head *a,
- struct list_head *b))
+ int (*cmp)(void *priv, struct list_head *a,
+ struct list_head *b))
{
- struct list_head *p, *q, *e, *list, *tail, *oldhead;
- int insize, nmerges, psize, qsize, i;
+ struct list_head *part[MAX_LIST_LENGTH_BITS+1]; /* sorted partial lists
+ -- last slot is a sentinel */
+ int lev; /* index into part[] */
+ int max_lev = 0;
+ struct list_head *list;
if (list_empty(head))
return;
+ memset(part, 0, sizeof(part));
+
+ head->prev->next = NULL;
list = head->next;
- list_del(head);
- insize = 1;
- for (;;) {
- p = oldhead = list;
- list = tail = NULL;
- nmerges = 0;
-
- while (p) {
- nmerges++;
- q = p;
- psize = 0;
- for (i = 0; i < insize; i++) {
- psize++;
- q = q->next == oldhead ? NULL : q->next;
- if (!q)
- break;
- }
- qsize = insize;
- while (psize > 0 || (qsize > 0 && q)) {
- if (!psize) {
- e = q;
- q = q->next;
- qsize--;
- if (q == oldhead)
- q = NULL;
- } else if (!qsize || !q) {
- e = p;
- p = p->next;
- psize--;
- if (p == oldhead)
- p = NULL;
- } else if (cmp(priv, p, q) <= 0) {
- e = p;
- p = p->next;
- psize--;
- if (p == oldhead)
- p = NULL;
- } else {
- e = q;
- q = q->next;
- qsize--;
- if (q == oldhead)
- q = NULL;
- }
- if (tail)
- tail->next = e;
- else
- list = e;
- e->prev = tail;
- tail = e;
+ while (list) {
+ struct list_head *cur = list;
+ list = list->next;
+ cur->next = NULL;
+
+ for (lev = 0; part[lev]; lev++) {
+ cur = merge(priv, cmp, part[lev], cur);
+ part[lev] = NULL;
+ }
+ if (lev > max_lev) {
+ if (unlikely(lev >= ARRAY_SIZE(part)-1)) {
+ printk_once(KERN_DEBUG "list passed to"
+ " list_sort() too long for"
+ " efficiency\n");
+ lev--;
}
- p = q;
+ max_lev = lev;
}
+ part[lev] = cur;
+ }
- tail->next = list;
- list->prev = tail;
+ for (lev = 0; lev < max_lev; lev++)
+ if (part[lev])
+ list = merge(priv, cmp, part[lev], list);
- if (nmerges <= 1)
- break;
+ merge_and_restore_back_links(priv, cmp, head, part[max_lev], list);
+}
+EXPORT_SYMBOL(list_sort);
- insize *= 2;
- }
+#ifdef DEBUG_LIST_SORT
+struct debug_el {
+ struct list_head l_h;
+ int value;
+ unsigned serial;
+};
- head->next = list;
- head->prev = list->prev;
- list->prev->next = head;
- list->prev = head;
+static int cmp(void *priv, struct list_head *a, struct list_head *b)
+{
+ return container_of(a, struct debug_el, l_h)->value
+ - container_of(b, struct debug_el, l_h)->value;
}
-EXPORT_SYMBOL(list_sort);
+/*
+ * The pattern of set bits in the list length determines which cases
+ * are hit in list_sort().
+ */
+#define LIST_SORT_TEST_LENGTH (512+128+2) /* not including head */
+
+static int __init list_sort_test(void)
+{
+ int i, r = 1, count;
+ struct list_head *head = kmalloc(sizeof(*head), GFP_KERNEL);
+ struct list_head *cur;
+
+ printk(KERN_WARNING "testing list_sort()\n");
+
+ cur = head;
+ for (i = 0; i < LIST_SORT_TEST_LENGTH; i++) {
+ struct debug_el *el = kmalloc(sizeof(*el), GFP_KERNEL);
+ BUG_ON(!el);
+ /* force some equivalencies */
+ el->value = (r = (r * 725861) % 6599) % (LIST_SORT_TEST_LENGTH/3);
+ el->serial = i;
+
+ el->l_h.prev = cur;
+ cur->next = &el->l_h;
+ cur = cur->next;
+ }
+ head->prev = cur;
+
+ list_sort(NULL, head, cmp);
+
+ count = 1;
+ for (cur = head->next; cur->next != head; cur = cur->next) {
+ struct debug_el *el = container_of(cur, struct debug_el, l_h);
+ int cmp_result = cmp(NULL, cur, cur->next);
+ if (cur->next->prev != cur) {
+ printk(KERN_EMERG "list_sort() returned "
+ "a corrupted list!\n");
+ return 1;
+ } else if (cmp_result > 0) {
+ printk(KERN_EMERG "list_sort() failed to sort!\n");
+ return 1;
+ } else if (cmp_result == 0 &&
+ el->serial >= container_of(cur->next,
+ struct debug_el, l_h)->serial) {
+ printk(KERN_EMERG "list_sort() failed to preserve order"
+ " of equivalent elements!\n");
+ return 1;
+ }
+ kfree(cur->prev);
+ count++;
+ }
+ kfree(cur);
+ if (count != LIST_SORT_TEST_LENGTH) {
+ printk(KERN_EMERG "list_sort() returned list of"
+ "different length!\n");
+ return 1;
+ }
+ return 0;
+}
+module_init(list_sort_test);
+#endif
diff --git a/lib/show_mem.c b/lib/show_mem.c
index 238e72a18ce..fdc77c82f92 100644
--- a/lib/show_mem.c
+++ b/lib/show_mem.c
@@ -15,7 +15,7 @@ void show_mem(void)
unsigned long total = 0, reserved = 0, shared = 0,
nonshared = 0, highmem = 0;
- printk(KERN_INFO "Mem-Info:\n");
+ printk("Mem-Info:\n");
show_free_areas();
for_each_online_pgdat(pgdat) {
@@ -49,15 +49,15 @@ void show_mem(void)
pgdat_resize_unlock(pgdat, &flags);
}
- printk(KERN_INFO "%lu pages RAM\n", total);
+ printk("%lu pages RAM\n", total);
#ifdef CONFIG_HIGHMEM
- printk(KERN_INFO "%lu pages HighMem\n", highmem);
+ printk("%lu pages HighMem\n", highmem);
#endif
- printk(KERN_INFO "%lu pages reserved\n", reserved);
- printk(KERN_INFO "%lu pages shared\n", shared);
- printk(KERN_INFO "%lu pages non-shared\n", nonshared);
+ printk("%lu pages reserved\n", reserved);
+ printk("%lu pages shared\n", shared);
+ printk("%lu pages non-shared\n", nonshared);
#ifdef CONFIG_QUICKLIST
- printk(KERN_INFO "%lu pages in pagetable cache\n",
+ printk("%lu pages in pagetable cache\n",
quicklist_total_size());
#endif
}
diff --git a/lib/string.c b/lib/string.c
index a1cdcfcc42d..f71bead1be3 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -36,25 +36,21 @@ int strnicmp(const char *s1, const char *s2, size_t len)
/* Yes, Virginia, it had better be unsigned */
unsigned char c1, c2;
- c1 = c2 = 0;
- if (len) {
- do {
- c1 = *s1;
- c2 = *s2;
- s1++;
- s2++;
- if (!c1)
- break;
- if (!c2)
- break;
- if (c1 == c2)
- continue;
- c1 = tolower(c1);
- c2 = tolower(c2);
- if (c1 != c2)
- break;
- } while (--len);
- }
+ if (!len)
+ return 0;
+
+ do {
+ c1 = *s1++;
+ c2 = *s2++;
+ if (!c1 || !c2)
+ break;
+ if (c1 == c2)
+ continue;
+ c1 = tolower(c1);
+ c2 = tolower(c2);
+ if (c1 != c2)
+ break;
+ } while (--len);
return (int)c1 - (int)c2;
}
EXPORT_SYMBOL(strnicmp);
@@ -693,13 +689,13 @@ EXPORT_SYMBOL(strstr);
*/
char *strnstr(const char *s1, const char *s2, size_t len)
{
- size_t l1 = len, l2;
+ size_t l2;
l2 = strlen(s2);
if (!l2)
return (char *)s1;
- while (l1 >= l2) {
- l1--;
+ while (len >= l2) {
+ len--;
if (!memcmp(s1, s2, l2))
return (char *)s1;
s1++;
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index af4aaa6c36f..0d461c7c14d 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -381,8 +381,8 @@ static noinline char *put_dec(char *buf, unsigned long long num)
#define PLUS 4 /* show plus */
#define SPACE 8 /* space if plus */
#define LEFT 16 /* left justified */
-#define SMALL 32 /* Must be 32 == 0x20 */
-#define SPECIAL 64 /* 0x */
+#define SMALL 32 /* use lowercase in hex (must be 32 == 0x20) */
+#define SPECIAL 64 /* prefix hex with "0x", octal with "0" */
enum format_type {
FORMAT_TYPE_NONE, /* Just a string part */
@@ -408,12 +408,12 @@ enum format_type {
};
struct printf_spec {
- enum format_type type;
- int flags; /* flags to number() */
- int field_width; /* width of output field */
- int base;
- int precision; /* # of digits/chars */
- int qualifier;
+ u16 type;
+ s16 field_width; /* width of output field */
+ u8 flags; /* flags to number() */
+ u8 base;
+ s8 precision; /* # of digits/chars */
+ u8 qualifier;
};
static char *number(char *buf, char *end, unsigned long long num,
@@ -597,22 +597,29 @@ static char *resource_string(char *buf, char *end, struct resource *res,
#ifndef MEM_RSRC_PRINTK_SIZE
#define MEM_RSRC_PRINTK_SIZE 10
#endif
- struct printf_spec hex_spec = {
+ static const struct printf_spec io_spec = {
.base = 16,
+ .field_width = IO_RSRC_PRINTK_SIZE,
.precision = -1,
.flags = SPECIAL | SMALL | ZEROPAD,
};
- struct printf_spec dec_spec = {
+ static const struct printf_spec mem_spec = {
+ .base = 16,
+ .field_width = MEM_RSRC_PRINTK_SIZE,
+ .precision = -1,
+ .flags = SPECIAL | SMALL | ZEROPAD,
+ };
+ static const struct printf_spec dec_spec = {
.base = 10,
.precision = -1,
.flags = 0,
};
- struct printf_spec str_spec = {
+ static const struct printf_spec str_spec = {
.field_width = -1,
.precision = 10,
.flags = LEFT,
};
- struct printf_spec flag_spec = {
+ static const struct printf_spec flag_spec = {
.base = 16,
.precision = -1,
.flags = SPECIAL | SMALL,
@@ -628,35 +635,31 @@ static char *resource_string(char *buf, char *end, struct resource *res,
2*RSRC_BUF_SIZE + FLAG_BUF_SIZE + RAW_BUF_SIZE)];
char *p = sym, *pend = sym + sizeof(sym);
- int size = -1, addr = 0;
int decode = (fmt[0] == 'R') ? 1 : 0;
-
- if (res->flags & IORESOURCE_IO) {
- size = IO_RSRC_PRINTK_SIZE;
- addr = 1;
- } else if (res->flags & IORESOURCE_MEM) {
- size = MEM_RSRC_PRINTK_SIZE;
- addr = 1;
- }
+ const struct printf_spec *specp;
*p++ = '[';
- if (res->flags & IORESOURCE_IO)
+ if (res->flags & IORESOURCE_IO) {
p = string(p, pend, "io ", str_spec);
- else if (res->flags & IORESOURCE_MEM)
+ specp = &io_spec;
+ } else if (res->flags & IORESOURCE_MEM) {
p = string(p, pend, "mem ", str_spec);
- else if (res->flags & IORESOURCE_IRQ)
+ specp = &mem_spec;
+ } else if (res->flags & IORESOURCE_IRQ) {
p = string(p, pend, "irq ", str_spec);
- else if (res->flags & IORESOURCE_DMA)
+ specp = &dec_spec;
+ } else if (res->flags & IORESOURCE_DMA) {
p = string(p, pend, "dma ", str_spec);
- else {
+ specp = &dec_spec;
+ } else {
p = string(p, pend, "??? ", str_spec);
+ specp = &mem_spec;
decode = 0;
}
- hex_spec.field_width = size;
- p = number(p, pend, res->start, addr ? hex_spec : dec_spec);
+ p = number(p, pend, res->start, *specp);
if (res->start != res->end) {
*p++ = '-';
- p = number(p, pend, res->end, addr ? hex_spec : dec_spec);
+ p = number(p, pend, res->end, *specp);
}
if (decode) {
if (res->flags & IORESOURCE_MEM_64)
@@ -1333,7 +1336,7 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
break;
case FORMAT_TYPE_NRCHARS: {
- int qualifier = spec.qualifier;
+ u8 qualifier = spec.qualifier;
if (qualifier == 'l') {
long *ip = va_arg(args, long *);
@@ -1619,7 +1622,7 @@ do { \
case FORMAT_TYPE_NRCHARS: {
/* skip %n 's argument */
- int qualifier = spec.qualifier;
+ u8 qualifier = spec.qualifier;
void *skip_arg;
if (qualifier == 'l')
skip_arg = va_arg(args, long *);
@@ -1885,7 +1888,9 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
char *next;
char digit;
int num = 0;
- int qualifier, base, field_width;
+ u8 qualifier;
+ u8 base;
+ s16 field_width;
bool is_sign;
while (*fmt && *str) {
@@ -1963,7 +1968,7 @@ int vsscanf(const char *buf, const char *fmt, va_list args)
{
char *s = (char *)va_arg(args, char *);
if (field_width == -1)
- field_width = INT_MAX;
+ field_width = SHORT_MAX;
/* first, skip leading white space in buffer */
str = skip_spaces(str);
diff --git a/mm/fadvise.c b/mm/fadvise.c
index e43359214f6..8d723c9e8b7 100644
--- a/mm/fadvise.c
+++ b/mm/fadvise.c
@@ -77,12 +77,20 @@ SYSCALL_DEFINE(fadvise64_64)(int fd, loff_t offset, loff_t len, int advice)
switch (advice) {
case POSIX_FADV_NORMAL:
file->f_ra.ra_pages = bdi->ra_pages;
+ spin_lock(&file->f_lock);
+ file->f_mode &= ~FMODE_RANDOM;
+ spin_unlock(&file->f_lock);
break;
case POSIX_FADV_RANDOM:
- file->f_ra.ra_pages = 0;
+ spin_lock(&file->f_lock);
+ file->f_mode |= FMODE_RANDOM;
+ spin_unlock(&file->f_lock);
break;
case POSIX_FADV_SEQUENTIAL:
file->f_ra.ra_pages = bdi->ra_pages * 2;
+ spin_lock(&file->f_lock);
+ file->f_mode &= ~FMODE_RANDOM;
+ spin_unlock(&file->f_lock);
break;
case POSIX_FADV_WILLNEED:
if (!mapping->a_ops->readpage) {
diff --git a/mm/filemap.c b/mm/filemap.c
index 148b52a5bb7..045b31c3765 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1986,7 +1986,7 @@ EXPORT_SYMBOL(iov_iter_single_seg_count);
inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk)
{
struct inode *inode = file->f_mapping->host;
- unsigned long limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
+ unsigned long limit = rlimit(RLIMIT_FSIZE);
if (unlikely(*pos < 0))
return -EINVAL;
diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c
index 1888b2d71bb..78b94f0b6d5 100644
--- a/mm/filemap_xip.c
+++ b/mm/filemap_xip.c
@@ -194,7 +194,7 @@ retry:
flush_cache_page(vma, address, pte_pfn(*pte));
pteval = ptep_clear_flush_notify(vma, address, pte);
page_remove_rmap(page);
- dec_mm_counter(mm, file_rss);
+ dec_mm_counter(mm, MM_FILEPAGES);
BUG_ON(pte_dirty(pteval));
pte_unmap_unlock(pte, ptl);
page_cache_release(page);
diff --git a/mm/fremap.c b/mm/fremap.c
index b6ec85abbb3..46f5dacf90a 100644
--- a/mm/fremap.c
+++ b/mm/fremap.c
@@ -40,7 +40,7 @@ static void zap_pte(struct mm_struct *mm, struct vm_area_struct *vma,
page_remove_rmap(page);
page_cache_release(page);
update_hiwater_rss(mm);
- dec_mm_counter(mm, file_rss);
+ dec_mm_counter(mm, MM_FILEPAGES);
}
} else {
if (!pte_file(pte))
diff --git a/mm/ksm.c b/mm/ksm.c
index 56a0da1f997..a93f1b7f508 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -1563,10 +1563,12 @@ int page_referenced_ksm(struct page *page, struct mem_cgroup *memcg,
again:
hlist_for_each_entry(rmap_item, hlist, &stable_node->hlist, hlist) {
struct anon_vma *anon_vma = rmap_item->anon_vma;
+ struct anon_vma_chain *vmac;
struct vm_area_struct *vma;
spin_lock(&anon_vma->lock);
- list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
+ list_for_each_entry(vmac, &anon_vma->head, same_anon_vma) {
+ vma = vmac->vma;
if (rmap_item->address < vma->vm_start ||
rmap_item->address >= vma->vm_end)
continue;
@@ -1614,10 +1616,12 @@ int try_to_unmap_ksm(struct page *page, enum ttu_flags flags)
again:
hlist_for_each_entry(rmap_item, hlist, &stable_node->hlist, hlist) {
struct anon_vma *anon_vma = rmap_item->anon_vma;
+ struct anon_vma_chain *vmac;
struct vm_area_struct *vma;
spin_lock(&anon_vma->lock);
- list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
+ list_for_each_entry(vmac, &anon_vma->head, same_anon_vma) {
+ vma = vmac->vma;
if (rmap_item->address < vma->vm_start ||
rmap_item->address >= vma->vm_end)
continue;
@@ -1664,10 +1668,12 @@ int rmap_walk_ksm(struct page *page, int (*rmap_one)(struct page *,
again:
hlist_for_each_entry(rmap_item, hlist, &stable_node->hlist, hlist) {
struct anon_vma *anon_vma = rmap_item->anon_vma;
+ struct anon_vma_chain *vmac;
struct vm_area_struct *vma;
spin_lock(&anon_vma->lock);
- list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
+ list_for_each_entry(vmac, &anon_vma->head, same_anon_vma) {
+ vma = vmac->vma;
if (rmap_item->address < vma->vm_start ||
rmap_item->address >= vma->vm_end)
continue;
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 954032b80be..d813823ab08 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2545,7 +2545,7 @@ static int mem_cgroup_force_empty_list(struct mem_cgroup *mem,
pc = list_entry(list->prev, struct page_cgroup, lru);
if (busy == pc) {
list_move(&pc->lru, list);
- busy = 0;
+ busy = NULL;
spin_unlock_irqrestore(&zone->lru_lock, flags);
continue;
}
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 17299fd4577..d1f33516297 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -383,9 +383,12 @@ static void collect_procs_anon(struct page *page, struct list_head *to_kill,
if (av == NULL) /* Not actually mapped anymore */
goto out;
for_each_process (tsk) {
+ struct anon_vma_chain *vmac;
+
if (!task_early_kill(tsk))
continue;
- list_for_each_entry (vma, &av->head, anon_vma_node) {
+ list_for_each_entry(vmac, &av->head, same_anon_vma) {
+ vma = vmac->vma;
if (!page_mapped_in_vma(page, vma))
continue;
if (vma->vm_mm == tsk->mm)
diff --git a/mm/memory.c b/mm/memory.c
index 72fb5f39bcc..d1153e37e9b 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -121,6 +121,80 @@ static int __init init_zero_pfn(void)
}
core_initcall(init_zero_pfn);
+
+#if defined(SPLIT_RSS_COUNTING)
+
+void __sync_task_rss_stat(struct task_struct *task, struct mm_struct *mm)
+{
+ int i;
+
+ for (i = 0; i < NR_MM_COUNTERS; i++) {
+ if (task->rss_stat.count[i]) {
+ add_mm_counter(mm, i, task->rss_stat.count[i]);
+ task->rss_stat.count[i] = 0;
+ }
+ }
+ task->rss_stat.events = 0;
+}
+
+static void add_mm_counter_fast(struct mm_struct *mm, int member, int val)
+{
+ struct task_struct *task = current;
+
+ if (likely(task->mm == mm))
+ task->rss_stat.count[member] += val;
+ else
+ add_mm_counter(mm, member, val);
+}
+#define inc_mm_counter_fast(mm, member) add_mm_counter_fast(mm, member, 1)
+#define dec_mm_counter_fast(mm, member) add_mm_counter_fast(mm, member, -1)
+
+/* sync counter once per 64 page faults */
+#define TASK_RSS_EVENTS_THRESH (64)
+static void check_sync_rss_stat(struct task_struct *task)
+{
+ if (unlikely(task != current))
+ return;
+ if (unlikely(task->rss_stat.events++ > TASK_RSS_EVENTS_THRESH))
+ __sync_task_rss_stat(task, task->mm);
+}
+
+unsigned long get_mm_counter(struct mm_struct *mm, int member)
+{
+ long val = 0;
+
+ /*
+ * Don't use task->mm here...for avoiding to use task_get_mm()..
+ * The caller must guarantee task->mm is not invalid.
+ */
+ val = atomic_long_read(&mm->rss_stat.count[member]);
+ /*
+ * counter is updated in asynchronous manner and may go to minus.
+ * But it's never be expected number for users.
+ */
+ if (val < 0)
+ return 0;
+ return (unsigned long)val;
+}
+
+void sync_mm_rss(struct task_struct *task, struct mm_struct *mm)
+{
+ __sync_task_rss_stat(task, mm);
+}
+#else
+
+#define inc_mm_counter_fast(mm, member) inc_mm_counter(mm, member)
+#define dec_mm_counter_fast(mm, member) dec_mm_counter(mm, member)
+
+static void check_sync_rss_stat(struct task_struct *task)
+{
+}
+
+void sync_mm_rss(struct task_struct *task, struct mm_struct *mm)
+{
+}
+#endif
+
/*
* If a p?d_bad entry is found while walking page tables, report
* the error, before resetting entry to p?d_none. Usually (but
@@ -300,7 +374,7 @@ void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *vma,
* Hide vma from rmap and truncate_pagecache before freeing
* pgtables
*/
- anon_vma_unlink(vma);
+ unlink_anon_vmas(vma);
unlink_file_vma(vma);
if (is_vm_hugetlb_page(vma)) {
@@ -314,7 +388,7 @@ void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *vma,
&& !is_vm_hugetlb_page(next)) {
vma = next;
next = vma->vm_next;
- anon_vma_unlink(vma);
+ unlink_anon_vmas(vma);
unlink_file_vma(vma);
}
free_pgd_range(tlb, addr, vma->vm_end,
@@ -376,12 +450,20 @@ int __pte_alloc_kernel(pmd_t *pmd, unsigned long address)
return 0;
}
-static inline void add_mm_rss(struct mm_struct *mm, int file_rss, int anon_rss)
+static inline void init_rss_vec(int *rss)
{
- if (file_rss)
- add_mm_counter(mm, file_rss, file_rss);
- if (anon_rss)
- add_mm_counter(mm, anon_rss, anon_rss);
+ memset(rss, 0, sizeof(int) * NR_MM_COUNTERS);
+}
+
+static inline void add_mm_rss_vec(struct mm_struct *mm, int *rss)
+{
+ int i;
+
+ if (current->mm == mm)
+ sync_mm_rss(current, mm);
+ for (i = 0; i < NR_MM_COUNTERS; i++)
+ if (rss[i])
+ add_mm_counter(mm, i, rss[i]);
}
/*
@@ -597,7 +679,9 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
&src_mm->mmlist);
spin_unlock(&mmlist_lock);
}
- if (is_write_migration_entry(entry) &&
+ if (likely(!non_swap_entry(entry)))
+ rss[MM_SWAPENTS]++;
+ else if (is_write_migration_entry(entry) &&
is_cow_mapping(vm_flags)) {
/*
* COW mappings require pages in both parent
@@ -632,7 +716,10 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm,
if (page) {
get_page(page);
page_dup_rmap(page);
- rss[PageAnon(page)]++;
+ if (PageAnon(page))
+ rss[MM_ANONPAGES]++;
+ else
+ rss[MM_FILEPAGES]++;
}
out_set_pte:
@@ -648,11 +735,12 @@ static int copy_pte_range(struct mm_struct *dst_mm, struct mm_struct *src_mm,
pte_t *src_pte, *dst_pte;
spinlock_t *src_ptl, *dst_ptl;
int progress = 0;
- int rss[2];
+ int rss[NR_MM_COUNTERS];
swp_entry_t entry = (swp_entry_t){0};
again:
- rss[1] = rss[0] = 0;
+ init_rss_vec(rss);
+
dst_pte = pte_alloc_map_lock(dst_mm, dst_pmd, addr, &dst_ptl);
if (!dst_pte)
return -ENOMEM;
@@ -688,7 +776,7 @@ again:
arch_leave_lazy_mmu_mode();
spin_unlock(src_ptl);
pte_unmap_nested(orig_src_pte);
- add_mm_rss(dst_mm, rss[0], rss[1]);
+ add_mm_rss_vec(dst_mm, rss);
pte_unmap_unlock(orig_dst_pte, dst_ptl);
cond_resched();
@@ -816,8 +904,9 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
struct mm_struct *mm = tlb->mm;
pte_t *pte;
spinlock_t *ptl;
- int file_rss = 0;
- int anon_rss = 0;
+ int rss[NR_MM_COUNTERS];
+
+ init_rss_vec(rss);
pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
arch_enter_lazy_mmu_mode();
@@ -863,14 +952,14 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
set_pte_at(mm, addr, pte,
pgoff_to_pte(page->index));
if (PageAnon(page))
- anon_rss--;
+ rss[MM_ANONPAGES]--;
else {
if (pte_dirty(ptent))
set_page_dirty(page);
if (pte_young(ptent) &&
likely(!VM_SequentialReadHint(vma)))
mark_page_accessed(page);
- file_rss--;
+ rss[MM_FILEPAGES]--;
}
page_remove_rmap(page);
if (unlikely(page_mapcount(page) < 0))
@@ -887,13 +976,18 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
if (pte_file(ptent)) {
if (unlikely(!(vma->vm_flags & VM_NONLINEAR)))
print_bad_pte(vma, addr, ptent, NULL);
- } else if
- (unlikely(!free_swap_and_cache(pte_to_swp_entry(ptent))))
- print_bad_pte(vma, addr, ptent, NULL);
+ } else {
+ swp_entry_t entry = pte_to_swp_entry(ptent);
+
+ if (!non_swap_entry(entry))
+ rss[MM_SWAPENTS]--;
+ if (unlikely(!free_swap_and_cache(entry)))
+ print_bad_pte(vma, addr, ptent, NULL);
+ }
pte_clear_not_present_full(mm, addr, pte, tlb->fullmm);
} while (pte++, addr += PAGE_SIZE, (addr != end && *zap_work > 0));
- add_mm_rss(mm, file_rss, anon_rss);
+ add_mm_rss_vec(mm, rss);
arch_leave_lazy_mmu_mode();
pte_unmap_unlock(pte - 1, ptl);
@@ -1527,7 +1621,7 @@ static int insert_page(struct vm_area_struct *vma, unsigned long addr,
/* Ok, finally just insert the thing.. */
get_page(page);
- inc_mm_counter(mm, file_rss);
+ inc_mm_counter_fast(mm, MM_FILEPAGES);
page_add_file_rmap(page);
set_pte_at(mm, addr, pte, mk_pte(page, prot));
@@ -2044,6 +2138,13 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
page_cache_release(old_page);
}
reuse = reuse_swap_page(old_page);
+ if (reuse)
+ /*
+ * The page is all ours. Move it to our anon_vma so
+ * the rmap code will not search our parent or siblings.
+ * Protected against the rmap code by the page lock.
+ */
+ page_move_anon_rmap(old_page, vma, address);
unlock_page(old_page);
} else if (unlikely((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
(VM_WRITE|VM_SHARED))) {
@@ -2163,11 +2264,11 @@ gotten:
if (likely(pte_same(*page_table, orig_pte))) {
if (old_page) {
if (!PageAnon(old_page)) {
- dec_mm_counter(mm, file_rss);
- inc_mm_counter(mm, anon_rss);
+ dec_mm_counter_fast(mm, MM_FILEPAGES);
+ inc_mm_counter_fast(mm, MM_ANONPAGES);
}
} else
- inc_mm_counter(mm, anon_rss);
+ inc_mm_counter_fast(mm, MM_ANONPAGES);
flush_cache_page(vma, address, pte_pfn(orig_pte));
entry = mk_pte(new_page, vma->vm_page_prot);
entry = maybe_mkwrite(pte_mkdirty(entry), vma);
@@ -2604,7 +2705,8 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
* discarded at swap_free().
*/
- inc_mm_counter(mm, anon_rss);
+ inc_mm_counter_fast(mm, MM_ANONPAGES);
+ dec_mm_counter_fast(mm, MM_SWAPENTS);
pte = mk_pte(page, vma->vm_page_prot);
if ((flags & FAULT_FLAG_WRITE) && reuse_swap_page(page)) {
pte = maybe_mkwrite(pte_mkdirty(pte), vma);
@@ -2688,7 +2790,7 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
if (!pte_none(*page_table))
goto release;
- inc_mm_counter(mm, anon_rss);
+ inc_mm_counter_fast(mm, MM_ANONPAGES);
page_add_new_anon_rmap(page, vma, address);
setpte:
set_pte_at(mm, address, page_table, entry);
@@ -2842,10 +2944,10 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
if (flags & FAULT_FLAG_WRITE)
entry = maybe_mkwrite(pte_mkdirty(entry), vma);
if (anon) {
- inc_mm_counter(mm, anon_rss);
+ inc_mm_counter_fast(mm, MM_ANONPAGES);
page_add_new_anon_rmap(page, vma, address);
} else {
- inc_mm_counter(mm, file_rss);
+ inc_mm_counter_fast(mm, MM_FILEPAGES);
page_add_file_rmap(page);
if (flags & FAULT_FLAG_WRITE) {
dirty_page = page;
@@ -3023,6 +3125,9 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
count_vm_event(PGFAULT);
+ /* do counter updates before entering really critical section. */
+ check_sync_rss_stat(current);
+
if (unlikely(is_vm_hugetlb_page(vma)))
return hugetlb_fault(mm, vma, address, flags);
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 030ce8a5bb0..78e34e63c7b 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -28,6 +28,7 @@
#include <linux/pfn.h>
#include <linux/suspend.h>
#include <linux/mm_inline.h>
+#include <linux/firmware-map.h>
#include <asm/tlbflush.h>
@@ -523,6 +524,9 @@ int __ref add_memory(int nid, u64 start, u64 size)
BUG_ON(ret);
}
+ /* create new memmap entry */
+ firmware_map_add_hotplug(start, start + size, "System RAM");
+
goto out;
error:
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 290fb5bf044..bda230e52ac 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -563,24 +563,50 @@ static int policy_vma(struct vm_area_struct *vma, struct mempolicy *new)
}
/* Step 2: apply policy to a range and do splits. */
-static int mbind_range(struct vm_area_struct *vma, unsigned long start,
- unsigned long end, struct mempolicy *new)
+static int mbind_range(struct mm_struct *mm, unsigned long start,
+ unsigned long end, struct mempolicy *new_pol)
{
struct vm_area_struct *next;
- int err;
+ struct vm_area_struct *prev;
+ struct vm_area_struct *vma;
+ int err = 0;
+ pgoff_t pgoff;
+ unsigned long vmstart;
+ unsigned long vmend;
- err = 0;
- for (; vma && vma->vm_start < end; vma = next) {
+ vma = find_vma_prev(mm, start, &prev);
+ if (!vma || vma->vm_start > start)
+ return -EFAULT;
+
+ for (; vma && vma->vm_start < end; prev = vma, vma = next) {
next = vma->vm_next;
- if (vma->vm_start < start)
- err = split_vma(vma->vm_mm, vma, start, 1);
- if (!err && vma->vm_end > end)
- err = split_vma(vma->vm_mm, vma, end, 0);
- if (!err)
- err = policy_vma(vma, new);
+ vmstart = max(start, vma->vm_start);
+ vmend = min(end, vma->vm_end);
+
+ pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
+ prev = vma_merge(mm, prev, vmstart, vmend, vma->vm_flags,
+ vma->anon_vma, vma->vm_file, pgoff, new_pol);
+ if (prev) {
+ vma = prev;
+ next = vma->vm_next;
+ continue;
+ }
+ if (vma->vm_start != vmstart) {
+ err = split_vma(vma->vm_mm, vma, vmstart, 1);
+ if (err)
+ goto out;
+ }
+ if (vma->vm_end != vmend) {
+ err = split_vma(vma->vm_mm, vma, vmend, 0);
+ if (err)
+ goto out;
+ }
+ err = policy_vma(vma, new_pol);
if (err)
- break;
+ goto out;
}
+
+ out:
return err;
}
@@ -862,36 +888,36 @@ int do_migrate_pages(struct mm_struct *mm,
if (err)
goto out;
-/*
- * Find a 'source' bit set in 'tmp' whose corresponding 'dest'
- * bit in 'to' is not also set in 'tmp'. Clear the found 'source'
- * bit in 'tmp', and return that <source, dest> pair for migration.
- * The pair of nodemasks 'to' and 'from' define the map.
- *
- * If no pair of bits is found that way, fallback to picking some
- * pair of 'source' and 'dest' bits that are not the same. If the
- * 'source' and 'dest' bits are the same, this represents a node
- * that will be migrating to itself, so no pages need move.
- *
- * If no bits are left in 'tmp', or if all remaining bits left
- * in 'tmp' correspond to the same bit in 'to', return false
- * (nothing left to migrate).
- *
- * This lets us pick a pair of nodes to migrate between, such that
- * if possible the dest node is not already occupied by some other
- * source node, minimizing the risk of overloading the memory on a
- * node that would happen if we migrated incoming memory to a node
- * before migrating outgoing memory source that same node.
- *
- * A single scan of tmp is sufficient. As we go, we remember the
- * most recent <s, d> pair that moved (s != d). If we find a pair
- * that not only moved, but what's better, moved to an empty slot
- * (d is not set in tmp), then we break out then, with that pair.
- * Otherwise when we finish scannng from_tmp, we at least have the
- * most recent <s, d> pair that moved. If we get all the way through
- * the scan of tmp without finding any node that moved, much less
- * moved to an empty node, then there is nothing left worth migrating.
- */
+ /*
+ * Find a 'source' bit set in 'tmp' whose corresponding 'dest'
+ * bit in 'to' is not also set in 'tmp'. Clear the found 'source'
+ * bit in 'tmp', and return that <source, dest> pair for migration.
+ * The pair of nodemasks 'to' and 'from' define the map.
+ *
+ * If no pair of bits is found that way, fallback to picking some
+ * pair of 'source' and 'dest' bits that are not the same. If the
+ * 'source' and 'dest' bits are the same, this represents a node
+ * that will be migrating to itself, so no pages need move.
+ *
+ * If no bits are left in 'tmp', or if all remaining bits left
+ * in 'tmp' correspond to the same bit in 'to', return false
+ * (nothing left to migrate).
+ *
+ * This lets us pick a pair of nodes to migrate between, such that
+ * if possible the dest node is not already occupied by some other
+ * source node, minimizing the risk of overloading the memory on a
+ * node that would happen if we migrated incoming memory to a node
+ * before migrating outgoing memory source that same node.
+ *
+ * A single scan of tmp is sufficient. As we go, we remember the
+ * most recent <s, d> pair that moved (s != d). If we find a pair
+ * that not only moved, but what's better, moved to an empty slot
+ * (d is not set in tmp), then we break out then, with that pair.
+ * Otherwise when we finish scannng from_tmp, we at least have the
+ * most recent <s, d> pair that moved. If we get all the way through
+ * the scan of tmp without finding any node that moved, much less
+ * moved to an empty node, then there is nothing left worth migrating.
+ */
tmp = *from_nodes;
while (!nodes_empty(tmp)) {
@@ -1047,7 +1073,7 @@ static long do_mbind(unsigned long start, unsigned long len,
if (!IS_ERR(vma)) {
int nr_failed = 0;
- err = mbind_range(vma, start, end, new);
+ err = mbind_range(mm, start, end, new);
if (!list_empty(&pagelist))
nr_failed = migrate_pages(&pagelist, new_vma_page,
diff --git a/mm/migrate.c b/mm/migrate.c
index edb6101ed77..88000b89fc9 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -275,8 +275,6 @@ static int migrate_page_move_mapping(struct address_space *mapping,
*/
static void migrate_page_copy(struct page *newpage, struct page *page)
{
- int anon;
-
copy_highpage(newpage, page);
if (PageError(page))
@@ -313,8 +311,6 @@ static void migrate_page_copy(struct page *newpage, struct page *page)
ClearPageSwapCache(page);
ClearPagePrivate(page);
set_page_private(page, 0);
- /* page->mapping contains a flag for PageAnon() */
- anon = PageAnon(page);
page->mapping = NULL;
/*
diff --git a/mm/mlock.c b/mm/mlock.c
index 2b8335a8940..8f4e2dfceec 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -25,7 +25,7 @@ int can_do_mlock(void)
{
if (capable(CAP_IPC_LOCK))
return 1;
- if (current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur != 0)
+ if (rlimit(RLIMIT_MEMLOCK) != 0)
return 1;
return 0;
}
@@ -487,7 +487,7 @@ SYSCALL_DEFINE2(mlock, unsigned long, start, size_t, len)
locked = len >> PAGE_SHIFT;
locked += current->mm->locked_vm;
- lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
+ lock_limit = rlimit(RLIMIT_MEMLOCK);
lock_limit >>= PAGE_SHIFT;
/* check against resource limits */
@@ -550,7 +550,7 @@ SYSCALL_DEFINE1(mlockall, int, flags)
down_write(&current->mm->mmap_sem);
- lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
+ lock_limit = rlimit(RLIMIT_MEMLOCK);
lock_limit >>= PAGE_SHIFT;
ret = -ENOMEM;
@@ -584,7 +584,7 @@ int user_shm_lock(size_t size, struct user_struct *user)
int allowed = 0;
locked = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
- lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
+ lock_limit = rlimit(RLIMIT_MEMLOCK);
if (lock_limit == RLIM_INFINITY)
allowed = 1;
lock_limit >>= PAGE_SHIFT;
@@ -618,12 +618,12 @@ int account_locked_memory(struct mm_struct *mm, struct rlimit *rlim,
down_write(&mm->mmap_sem);
- lim = rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT;
+ lim = ACCESS_ONCE(rlim[RLIMIT_AS].rlim_cur) >> PAGE_SHIFT;
vm = mm->total_vm + pgsz;
if (lim < vm)
goto out;
- lim = rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
+ lim = ACCESS_ONCE(rlim[RLIMIT_MEMLOCK].rlim_cur) >> PAGE_SHIFT;
vm = mm->locked_vm + pgsz;
if (lim < vm)
goto out;
diff --git a/mm/mmap.c b/mm/mmap.c
index ee2298936fe..f1b4448626b 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -265,7 +265,7 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
* segment grow beyond its set limit the in case where the limit is
* not page aligned -Ram Gupta
*/
- rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
+ rlim = rlimit(RLIMIT_DATA);
if (rlim < RLIM_INFINITY && (brk - mm->start_brk) +
(mm->end_data - mm->start_data) > rlim)
goto out;
@@ -437,7 +437,6 @@ __vma_link(struct mm_struct *mm, struct vm_area_struct *vma,
{
__vma_link_list(mm, vma, prev, rb_parent);
__vma_link_rb(mm, vma, rb_link, rb_parent);
- __anon_vma_link(vma);
}
static void vma_link(struct mm_struct *mm, struct vm_area_struct *vma,
@@ -499,7 +498,7 @@ __vma_unlink(struct mm_struct *mm, struct vm_area_struct *vma,
* are necessary. The "insert" vma (if any) is to be inserted
* before we drop the necessary locks.
*/
-void vma_adjust(struct vm_area_struct *vma, unsigned long start,
+int vma_adjust(struct vm_area_struct *vma, unsigned long start,
unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert)
{
struct mm_struct *mm = vma->vm_mm;
@@ -542,6 +541,26 @@ again: remove_next = 1 + (end > next->vm_end);
}
}
+ /*
+ * When changing only vma->vm_end, we don't really need anon_vma lock.
+ */
+ if (vma->anon_vma && (insert || importer || start != vma->vm_start))
+ anon_vma = vma->anon_vma;
+ if (anon_vma) {
+ /*
+ * Easily overlooked: when mprotect shifts the boundary,
+ * make sure the expanding vma has anon_vma set if the
+ * shrinking vma had, to cover any anon pages imported.
+ */
+ if (importer && !importer->anon_vma) {
+ /* Block reverse map lookups until things are set up. */
+ if (anon_vma_clone(importer, vma)) {
+ return -ENOMEM;
+ }
+ importer->anon_vma = anon_vma;
+ }
+ }
+
if (file) {
mapping = file->f_mapping;
if (!(vma->vm_flags & VM_NONLINEAR))
@@ -567,25 +586,6 @@ again: remove_next = 1 + (end > next->vm_end);
}
}
- /*
- * When changing only vma->vm_end, we don't really need
- * anon_vma lock.
- */
- if (vma->anon_vma && (insert || importer || start != vma->vm_start))
- anon_vma = vma->anon_vma;
- if (anon_vma) {
- spin_lock(&anon_vma->lock);
- /*
- * Easily overlooked: when mprotect shifts the boundary,
- * make sure the expanding vma has anon_vma set if the
- * shrinking vma had, to cover any anon pages imported.
- */
- if (importer && !importer->anon_vma) {
- importer->anon_vma = anon_vma;
- __anon_vma_link(importer);
- }
- }
-
if (root) {
flush_dcache_mmap_lock(mapping);
vma_prio_tree_remove(vma, root);
@@ -616,8 +616,6 @@ again: remove_next = 1 + (end > next->vm_end);
__vma_unlink(mm, next, vma);
if (file)
__remove_shared_vm_struct(next, file, mapping);
- if (next->anon_vma)
- __anon_vma_merge(vma, next);
} else if (insert) {
/*
* split_vma has split insert from vma, and needs
@@ -627,8 +625,6 @@ again: remove_next = 1 + (end > next->vm_end);
__insert_vm_struct(mm, insert);
}
- if (anon_vma)
- spin_unlock(&anon_vma->lock);
if (mapping)
spin_unlock(&mapping->i_mmap_lock);
@@ -638,6 +634,8 @@ again: remove_next = 1 + (end > next->vm_end);
if (next->vm_flags & VM_EXECUTABLE)
removed_exe_file_vma(mm);
}
+ if (next->anon_vma)
+ anon_vma_merge(vma, next);
mm->map_count--;
mpol_put(vma_policy(next));
kmem_cache_free(vm_area_cachep, next);
@@ -653,6 +651,8 @@ again: remove_next = 1 + (end > next->vm_end);
}
validate_mm(mm);
+
+ return 0;
}
/*
@@ -759,6 +759,7 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm,
{
pgoff_t pglen = (end - addr) >> PAGE_SHIFT;
struct vm_area_struct *area, *next;
+ int err;
/*
* We later require that vma->vm_flags == vm_flags,
@@ -792,11 +793,13 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm,
is_mergeable_anon_vma(prev->anon_vma,
next->anon_vma)) {
/* cases 1, 6 */
- vma_adjust(prev, prev->vm_start,
+ err = vma_adjust(prev, prev->vm_start,
next->vm_end, prev->vm_pgoff, NULL);
} else /* cases 2, 5, 7 */
- vma_adjust(prev, prev->vm_start,
+ err = vma_adjust(prev, prev->vm_start,
end, prev->vm_pgoff, NULL);
+ if (err)
+ return NULL;
return prev;
}
@@ -808,11 +811,13 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm,
can_vma_merge_before(next, vm_flags,
anon_vma, file, pgoff+pglen)) {
if (prev && addr < prev->vm_end) /* case 4 */
- vma_adjust(prev, prev->vm_start,
+ err = vma_adjust(prev, prev->vm_start,
addr, prev->vm_pgoff, NULL);
else /* cases 3, 8 */
- vma_adjust(area, addr, next->vm_end,
+ err = vma_adjust(area, addr, next->vm_end,
next->vm_pgoff - pglen, NULL);
+ if (err)
+ return NULL;
return area;
}
@@ -967,7 +972,7 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
unsigned long locked, lock_limit;
locked = len >> PAGE_SHIFT;
locked += mm->locked_vm;
- lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
+ lock_limit = rlimit(RLIMIT_MEMLOCK);
lock_limit >>= PAGE_SHIFT;
if (locked > lock_limit && !capable(CAP_IPC_LOCK))
return -EAGAIN;
@@ -1205,6 +1210,7 @@ munmap_back:
vma->vm_flags = vm_flags;
vma->vm_page_prot = vm_get_page_prot(vm_flags);
vma->vm_pgoff = pgoff;
+ INIT_LIST_HEAD(&vma->anon_vma_chain);
if (file) {
error = -EINVAL;
@@ -1265,13 +1271,8 @@ out:
mm->total_vm += len >> PAGE_SHIFT;
vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT);
if (vm_flags & VM_LOCKED) {
- /*
- * makes pages present; downgrades, drops, reacquires mmap_sem
- */
- long nr_pages = mlock_vma_pages_range(vma, addr, addr + len);
- if (nr_pages < 0)
- return nr_pages; /* vma gone! */
- mm->locked_vm += (len >> PAGE_SHIFT) - nr_pages;
+ if (!mlock_vma_pages_range(vma, addr, addr + len))
+ mm->locked_vm += (len >> PAGE_SHIFT);
} else if ((flags & MAP_POPULATE) && !(flags & MAP_NONBLOCK))
make_pages_present(addr, addr + len);
return addr;
@@ -1599,7 +1600,7 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns
return -ENOMEM;
/* Stack limit test */
- if (size > rlim[RLIMIT_STACK].rlim_cur)
+ if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur))
return -ENOMEM;
/* mlock limit tests */
@@ -1607,7 +1608,8 @@ static int acct_stack_growth(struct vm_area_struct *vma, unsigned long size, uns
unsigned long locked;
unsigned long limit;
locked = mm->locked_vm + grow;
- limit = rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
+ limit = ACCESS_ONCE(rlim[RLIMIT_MEMLOCK].rlim_cur);
+ limit >>= PAGE_SHIFT;
if (locked > limit && !capable(CAP_IPC_LOCK))
return -ENOMEM;
}
@@ -1754,8 +1756,7 @@ find_extend_vma(struct mm_struct *mm, unsigned long addr)
if (!prev || expand_stack(prev, addr))
return NULL;
if (prev->vm_flags & VM_LOCKED) {
- if (mlock_vma_pages_range(prev, addr, prev->vm_end) < 0)
- return NULL; /* vma gone! */
+ mlock_vma_pages_range(prev, addr, prev->vm_end);
}
return prev;
}
@@ -1783,8 +1784,7 @@ find_extend_vma(struct mm_struct * mm, unsigned long addr)
if (expand_stack(vma, addr))
return NULL;
if (vma->vm_flags & VM_LOCKED) {
- if (mlock_vma_pages_range(vma, addr, start) < 0)
- return NULL; /* vma gone! */
+ mlock_vma_pages_range(vma, addr, start);
}
return vma;
}
@@ -1871,6 +1871,7 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
{
struct mempolicy *pol;
struct vm_area_struct *new;
+ int err = -ENOMEM;
if (is_vm_hugetlb_page(vma) && (addr &
~(huge_page_mask(hstate_vma(vma)))))
@@ -1878,11 +1879,13 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
new = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL);
if (!new)
- return -ENOMEM;
+ goto out_err;
/* most fields are the same, copy all, and then fixup */
*new = *vma;
+ INIT_LIST_HEAD(&new->anon_vma_chain);
+
if (new_below)
new->vm_end = addr;
else {
@@ -1892,11 +1895,14 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
pol = mpol_dup(vma_policy(vma));
if (IS_ERR(pol)) {
- kmem_cache_free(vm_area_cachep, new);
- return PTR_ERR(pol);
+ err = PTR_ERR(pol);
+ goto out_free_vma;
}
vma_set_policy(new, pol);
+ if (anon_vma_clone(new, vma))
+ goto out_free_mpol;
+
if (new->vm_file) {
get_file(new->vm_file);
if (vma->vm_flags & VM_EXECUTABLE)
@@ -1907,12 +1913,28 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
new->vm_ops->open(new);
if (new_below)
- vma_adjust(vma, addr, vma->vm_end, vma->vm_pgoff +
+ err = vma_adjust(vma, addr, vma->vm_end, vma->vm_pgoff +
((addr - new->vm_start) >> PAGE_SHIFT), new);
else
- vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new);
+ err = vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new);
- return 0;
+ /* Success. */
+ if (!err)
+ return 0;
+
+ /* Clean everything up if vma_adjust failed. */
+ new->vm_ops->close(new);
+ if (new->vm_file) {
+ if (vma->vm_flags & VM_EXECUTABLE)
+ removed_exe_file_vma(mm);
+ fput(new->vm_file);
+ }
+ out_free_mpol:
+ mpol_put(pol);
+ out_free_vma:
+ kmem_cache_free(vm_area_cachep, new);
+ out_err:
+ return err;
}
/*
@@ -2074,7 +2096,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
unsigned long locked, lock_limit;
locked = len >> PAGE_SHIFT;
locked += mm->locked_vm;
- lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
+ lock_limit = rlimit(RLIMIT_MEMLOCK);
lock_limit >>= PAGE_SHIFT;
if (locked > lock_limit && !capable(CAP_IPC_LOCK))
return -EAGAIN;
@@ -2122,6 +2144,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
return -ENOMEM;
}
+ INIT_LIST_HEAD(&vma->anon_vma_chain);
vma->vm_mm = mm;
vma->vm_start = addr;
vma->vm_end = addr + len;
@@ -2258,10 +2281,11 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
if (new_vma) {
*new_vma = *vma;
pol = mpol_dup(vma_policy(vma));
- if (IS_ERR(pol)) {
- kmem_cache_free(vm_area_cachep, new_vma);
- return NULL;
- }
+ if (IS_ERR(pol))
+ goto out_free_vma;
+ INIT_LIST_HEAD(&new_vma->anon_vma_chain);
+ if (anon_vma_clone(new_vma, vma))
+ goto out_free_mempol;
vma_set_policy(new_vma, pol);
new_vma->vm_start = addr;
new_vma->vm_end = addr + len;
@@ -2277,6 +2301,12 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
}
}
return new_vma;
+
+ out_free_mempol:
+ mpol_put(pol);
+ out_free_vma:
+ kmem_cache_free(vm_area_cachep, new_vma);
+ return NULL;
}
/*
@@ -2288,7 +2318,7 @@ int may_expand_vm(struct mm_struct *mm, unsigned long npages)
unsigned long cur = mm->total_vm; /* pages */
unsigned long lim;
- lim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT;
+ lim = rlimit(RLIMIT_AS) >> PAGE_SHIFT;
if (cur + npages > lim)
return 0;
@@ -2354,6 +2384,7 @@ int install_special_mapping(struct mm_struct *mm,
if (unlikely(vma == NULL))
return -ENOMEM;
+ INIT_LIST_HEAD(&vma->anon_vma_chain);
vma->vm_mm = mm;
vma->vm_start = addr;
vma->vm_end = addr + len;
@@ -2454,6 +2485,7 @@ static void vm_lock_mapping(struct mm_struct *mm, struct address_space *mapping)
int mm_take_all_locks(struct mm_struct *mm)
{
struct vm_area_struct *vma;
+ struct anon_vma_chain *avc;
int ret = -EINTR;
BUG_ON(down_read_trylock(&mm->mmap_sem));
@@ -2471,7 +2503,8 @@ int mm_take_all_locks(struct mm_struct *mm)
if (signal_pending(current))
goto out_unlock;
if (vma->anon_vma)
- vm_lock_anon_vma(mm, vma->anon_vma);
+ list_for_each_entry(avc, &vma->anon_vma_chain, same_vma)
+ vm_lock_anon_vma(mm, avc->anon_vma);
}
ret = 0;
@@ -2526,13 +2559,15 @@ static void vm_unlock_mapping(struct address_space *mapping)
void mm_drop_all_locks(struct mm_struct *mm)
{
struct vm_area_struct *vma;
+ struct anon_vma_chain *avc;
BUG_ON(down_read_trylock(&mm->mmap_sem));
BUG_ON(!mutex_is_locked(&mm_all_locks_mutex));
for (vma = mm->mmap; vma; vma = vma->vm_next) {
if (vma->anon_vma)
- vm_unlock_anon_vma(vma->anon_vma);
+ list_for_each_entry(avc, &vma->anon_vma_chain, same_vma)
+ vm_unlock_anon_vma(avc->anon_vma);
if (vma->vm_file && vma->vm_file->f_mapping)
vm_unlock_mapping(vma->vm_file->f_mapping);
}
diff --git a/mm/mremap.c b/mm/mremap.c
index 845190898d5..e9c75efce60 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -285,7 +285,7 @@ static struct vm_area_struct *vma_to_resize(unsigned long addr,
if (vma->vm_flags & VM_LOCKED) {
unsigned long locked, lock_limit;
locked = mm->locked_vm << PAGE_SHIFT;
- lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
+ lock_limit = rlimit(RLIMIT_MEMLOCK);
locked += new_len - old_len;
if (locked > lock_limit && !capable(CAP_IPC_LOCK))
goto Eagain;
@@ -460,8 +460,11 @@ unsigned long do_mremap(unsigned long addr,
if (vma_expandable(vma, new_len - old_len)) {
int pages = (new_len - old_len) >> PAGE_SHIFT;
- vma_adjust(vma, vma->vm_start,
- addr + new_len, vma->vm_pgoff, NULL);
+ if (vma_adjust(vma, vma->vm_start, addr + new_len,
+ vma->vm_pgoff, NULL)) {
+ ret = -ENOMEM;
+ goto out;
+ }
mm->total_vm += pages;
vm_stat_account(mm, vma->vm_flags, vma->vm_file, pages);
diff --git a/mm/nommu.c b/mm/nommu.c
index 48a2ecfaf05..b9b5cceb1b6 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -146,7 +146,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
(VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
for (i = 0; i < nr_pages; i++) {
- vma = find_vma(mm, start);
+ vma = find_extend_vma(mm, start);
if (!vma)
goto finish_or_fault;
@@ -764,7 +764,7 @@ EXPORT_SYMBOL(find_vma);
*/
struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr)
{
- return find_vma(mm, addr);
+ return find_vma(mm, addr & PAGE_MASK);
}
/*
@@ -1209,7 +1209,7 @@ unsigned long do_mmap_pgoff(struct file *file,
region->vm_flags = vm_flags;
region->vm_pgoff = pgoff;
- INIT_LIST_HEAD(&vma->anon_vma_node);
+ INIT_LIST_HEAD(&vma->anon_vma_chain);
vma->vm_flags = vm_flags;
vma->vm_pgoff = pgoff;
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 237050478f2..35755a4156d 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -401,8 +401,8 @@ static void __oom_kill_task(struct task_struct *p, int verbose)
"vsz:%lukB, anon-rss:%lukB, file-rss:%lukB\n",
task_pid_nr(p), p->comm,
K(p->mm->total_vm),
- K(get_mm_counter(p->mm, anon_rss)),
- K(get_mm_counter(p->mm, file_rss)));
+ K(get_mm_counter(p->mm, MM_ANONPAGES)),
+ K(get_mm_counter(p->mm, MM_FILEPAGES)));
task_unlock(p);
/*
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index a6b17aa4740..a8182c89de5 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -76,6 +76,31 @@ unsigned long totalreserve_pages __read_mostly;
int percpu_pagelist_fraction;
gfp_t gfp_allowed_mask __read_mostly = GFP_BOOT_MASK;
+#ifdef CONFIG_PM_SLEEP
+/*
+ * The following functions are used by the suspend/hibernate code to temporarily
+ * change gfp_allowed_mask in order to avoid using I/O during memory allocations
+ * while devices are suspended. To avoid races with the suspend/hibernate code,
+ * they should always be called with pm_mutex held (gfp_allowed_mask also should
+ * only be modified with pm_mutex held, unless the suspend/hibernate code is
+ * guaranteed not to run in parallel with that modification).
+ */
+void set_gfp_allowed_mask(gfp_t mask)
+{
+ WARN_ON(!mutex_is_locked(&pm_mutex));
+ gfp_allowed_mask = mask;
+}
+
+gfp_t clear_gfp_allowed_mask(gfp_t mask)
+{
+ gfp_t ret = gfp_allowed_mask;
+
+ WARN_ON(!mutex_is_locked(&pm_mutex));
+ gfp_allowed_mask &= ~mask;
+ return ret;
+}
+#endif /* CONFIG_PM_SLEEP */
+
#ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE
int pageblock_order __read_mostly;
#endif
@@ -530,7 +555,7 @@ static void free_pcppages_bulk(struct zone *zone, int count,
int batch_free = 0;
spin_lock(&zone->lock);
- zone_clear_flag(zone, ZONE_ALL_UNRECLAIMABLE);
+ zone->all_unreclaimable = 0;
zone->pages_scanned = 0;
__mod_zone_page_state(zone, NR_FREE_PAGES, count);
@@ -568,7 +593,7 @@ static void free_one_page(struct zone *zone, struct page *page, int order,
int migratetype)
{
spin_lock(&zone->lock);
- zone_clear_flag(zone, ZONE_ALL_UNRECLAIMABLE);
+ zone->all_unreclaimable = 0;
zone->pages_scanned = 0;
__mod_zone_page_state(zone, NR_FREE_PAGES, 1 << order);
@@ -583,6 +608,7 @@ static void __free_pages_ok(struct page *page, unsigned int order)
int bad = 0;
int wasMlocked = __TestClearPageMlocked(page);
+ trace_mm_page_free_direct(page, order);
kmemcheck_free_shadow(page, order);
for (i = 0 ; i < (1 << order) ; ++i)
@@ -1073,8 +1099,9 @@ void mark_free_pages(struct zone *zone)
/*
* Free a 0-order page
+ * cold == 1 ? free a cold page : free a hot page
*/
-static void free_hot_cold_page(struct page *page, int cold)
+void free_hot_cold_page(struct page *page, int cold)
{
struct zone *zone = page_zone(page);
struct per_cpu_pages *pcp;
@@ -1082,6 +1109,7 @@ static void free_hot_cold_page(struct page *page, int cold)
int migratetype;
int wasMlocked = __TestClearPageMlocked(page);
+ trace_mm_page_free_direct(page, 0);
kmemcheck_free_shadow(page, 0);
if (PageAnon(page))
@@ -1133,12 +1161,6 @@ out:
local_irq_restore(flags);
}
-void free_hot_page(struct page *page)
-{
- trace_mm_page_free_direct(page, 0);
- free_hot_cold_page(page, 0);
-}
-
/*
* split_page takes a non-compound higher-order page, and splits it into
* n (1<<order) sub-pages: page[0..n]
@@ -2008,9 +2030,8 @@ void __pagevec_free(struct pagevec *pvec)
void __free_pages(struct page *page, unsigned int order)
{
if (put_page_testzero(page)) {
- trace_mm_page_free_direct(page, order);
if (order == 0)
- free_hot_page(page);
+ free_hot_cold_page(page, 0);
else
__free_pages_ok(page, order);
}
@@ -2266,7 +2287,7 @@ void show_free_areas(void)
K(zone_page_state(zone, NR_BOUNCE)),
K(zone_page_state(zone, NR_WRITEBACK_TEMP)),
zone->pages_scanned,
- (zone_is_all_unreclaimable(zone) ? "yes" : "no")
+ (zone->all_unreclaimable ? "yes" : "no")
);
printk("lowmem_reserve[]:");
for (i = 0; i < MAX_NR_ZONES; i++)
@@ -4371,8 +4392,12 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn)
for (i = 0; i < MAX_NR_ZONES; i++) {
if (i == ZONE_MOVABLE)
continue;
- printk(" %-8s %0#10lx -> %0#10lx\n",
- zone_names[i],
+ printk(" %-8s ", zone_names[i]);
+ if (arch_zone_lowest_possible_pfn[i] ==
+ arch_zone_highest_possible_pfn[i])
+ printk("empty\n");
+ else
+ printk("%0#10lx -> %0#10lx\n",
arch_zone_lowest_possible_pfn[i],
arch_zone_highest_possible_pfn[i]);
}
diff --git a/mm/readahead.c b/mm/readahead.c
index 033bc135a41..337b20e946f 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -501,6 +501,12 @@ void page_cache_sync_readahead(struct address_space *mapping,
if (!ra->ra_pages)
return;
+ /* be dumb */
+ if (filp->f_mode & FMODE_RANDOM) {
+ force_page_cache_readahead(mapping, filp, offset, req_size);
+ return;
+ }
+
/* do read-ahead */
ondemand_readahead(mapping, ra, filp, false, offset, req_size);
}
diff --git a/mm/rmap.c b/mm/rmap.c
index 278cd277bde..fcd593c9c99 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -62,6 +62,7 @@
#include "internal.h"
static struct kmem_cache *anon_vma_cachep;
+static struct kmem_cache *anon_vma_chain_cachep;
static inline struct anon_vma *anon_vma_alloc(void)
{
@@ -73,6 +74,16 @@ void anon_vma_free(struct anon_vma *anon_vma)
kmem_cache_free(anon_vma_cachep, anon_vma);
}
+static inline struct anon_vma_chain *anon_vma_chain_alloc(void)
+{
+ return kmem_cache_alloc(anon_vma_chain_cachep, GFP_KERNEL);
+}
+
+void anon_vma_chain_free(struct anon_vma_chain *anon_vma_chain)
+{
+ kmem_cache_free(anon_vma_chain_cachep, anon_vma_chain);
+}
+
/**
* anon_vma_prepare - attach an anon_vma to a memory region
* @vma: the memory region in question
@@ -103,18 +114,23 @@ void anon_vma_free(struct anon_vma *anon_vma)
int anon_vma_prepare(struct vm_area_struct *vma)
{
struct anon_vma *anon_vma = vma->anon_vma;
+ struct anon_vma_chain *avc;
might_sleep();
if (unlikely(!anon_vma)) {
struct mm_struct *mm = vma->vm_mm;
struct anon_vma *allocated;
+ avc = anon_vma_chain_alloc();
+ if (!avc)
+ goto out_enomem;
+
anon_vma = find_mergeable_anon_vma(vma);
allocated = NULL;
if (!anon_vma) {
anon_vma = anon_vma_alloc();
if (unlikely(!anon_vma))
- return -ENOMEM;
+ goto out_enomem_free_avc;
allocated = anon_vma;
}
spin_lock(&anon_vma->lock);
@@ -123,53 +139,113 @@ int anon_vma_prepare(struct vm_area_struct *vma)
spin_lock(&mm->page_table_lock);
if (likely(!vma->anon_vma)) {
vma->anon_vma = anon_vma;
- list_add_tail(&vma->anon_vma_node, &anon_vma->head);
+ avc->anon_vma = anon_vma;
+ avc->vma = vma;
+ list_add(&avc->same_vma, &vma->anon_vma_chain);
+ list_add(&avc->same_anon_vma, &anon_vma->head);
allocated = NULL;
}
spin_unlock(&mm->page_table_lock);
spin_unlock(&anon_vma->lock);
- if (unlikely(allocated))
+ if (unlikely(allocated)) {
anon_vma_free(allocated);
+ anon_vma_chain_free(avc);
+ }
}
return 0;
+
+ out_enomem_free_avc:
+ anon_vma_chain_free(avc);
+ out_enomem:
+ return -ENOMEM;
}
-void __anon_vma_merge(struct vm_area_struct *vma, struct vm_area_struct *next)
+static void anon_vma_chain_link(struct vm_area_struct *vma,
+ struct anon_vma_chain *avc,
+ struct anon_vma *anon_vma)
{
- BUG_ON(vma->anon_vma != next->anon_vma);
- list_del(&next->anon_vma_node);
+ avc->vma = vma;
+ avc->anon_vma = anon_vma;
+ list_add(&avc->same_vma, &vma->anon_vma_chain);
+
+ spin_lock(&anon_vma->lock);
+ list_add_tail(&avc->same_anon_vma, &anon_vma->head);
+ spin_unlock(&anon_vma->lock);
}
-void __anon_vma_link(struct vm_area_struct *vma)
+/*
+ * Attach the anon_vmas from src to dst.
+ * Returns 0 on success, -ENOMEM on failure.
+ */
+int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
{
- struct anon_vma *anon_vma = vma->anon_vma;
+ struct anon_vma_chain *avc, *pavc;
- if (anon_vma)
- list_add_tail(&vma->anon_vma_node, &anon_vma->head);
+ list_for_each_entry(pavc, &src->anon_vma_chain, same_vma) {
+ avc = anon_vma_chain_alloc();
+ if (!avc)
+ goto enomem_failure;
+ anon_vma_chain_link(dst, avc, pavc->anon_vma);
+ }
+ return 0;
+
+ enomem_failure:
+ unlink_anon_vmas(dst);
+ return -ENOMEM;
}
-void anon_vma_link(struct vm_area_struct *vma)
+/*
+ * Attach vma to its own anon_vma, as well as to the anon_vmas that
+ * the corresponding VMA in the parent process is attached to.
+ * Returns 0 on success, non-zero on failure.
+ */
+int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
{
- struct anon_vma *anon_vma = vma->anon_vma;
+ struct anon_vma_chain *avc;
+ struct anon_vma *anon_vma;
- if (anon_vma) {
- spin_lock(&anon_vma->lock);
- list_add_tail(&vma->anon_vma_node, &anon_vma->head);
- spin_unlock(&anon_vma->lock);
- }
+ /* Don't bother if the parent process has no anon_vma here. */
+ if (!pvma->anon_vma)
+ return 0;
+
+ /*
+ * First, attach the new VMA to the parent VMA's anon_vmas,
+ * so rmap can find non-COWed pages in child processes.
+ */
+ if (anon_vma_clone(vma, pvma))
+ return -ENOMEM;
+
+ /* Then add our own anon_vma. */
+ anon_vma = anon_vma_alloc();
+ if (!anon_vma)
+ goto out_error;
+ avc = anon_vma_chain_alloc();
+ if (!avc)
+ goto out_error_free_anon_vma;
+ anon_vma_chain_link(vma, avc, anon_vma);
+ /* Mark this anon_vma as the one where our new (COWed) pages go. */
+ vma->anon_vma = anon_vma;
+
+ return 0;
+
+ out_error_free_anon_vma:
+ anon_vma_free(anon_vma);
+ out_error:
+ return -ENOMEM;
}
-void anon_vma_unlink(struct vm_area_struct *vma)
+static void anon_vma_unlink(struct anon_vma_chain *anon_vma_chain)
{
- struct anon_vma *anon_vma = vma->anon_vma;
+ struct anon_vma *anon_vma = anon_vma_chain->anon_vma;
int empty;
+ /* If anon_vma_fork fails, we can get an empty anon_vma_chain. */
if (!anon_vma)
return;
spin_lock(&anon_vma->lock);
- list_del(&vma->anon_vma_node);
+ list_del(&anon_vma_chain->same_anon_vma);
/* We must garbage collect the anon_vma if it's empty */
empty = list_empty(&anon_vma->head) && !ksm_refcount(anon_vma);
@@ -179,6 +255,18 @@ void anon_vma_unlink(struct vm_area_struct *vma)
anon_vma_free(anon_vma);
}
+void unlink_anon_vmas(struct vm_area_struct *vma)
+{
+ struct anon_vma_chain *avc, *next;
+
+ /* Unlink each anon_vma chained to the VMA. */
+ list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) {
+ anon_vma_unlink(avc);
+ list_del(&avc->same_vma);
+ anon_vma_chain_free(avc);
+ }
+}
+
static void anon_vma_ctor(void *data)
{
struct anon_vma *anon_vma = data;
@@ -192,6 +280,7 @@ void __init anon_vma_init(void)
{
anon_vma_cachep = kmem_cache_create("anon_vma", sizeof(struct anon_vma),
0, SLAB_DESTROY_BY_RCU|SLAB_PANIC, anon_vma_ctor);
+ anon_vma_chain_cachep = KMEM_CACHE(anon_vma_chain, SLAB_PANIC);
}
/*
@@ -396,7 +485,7 @@ static int page_referenced_anon(struct page *page,
{
unsigned int mapcount;
struct anon_vma *anon_vma;
- struct vm_area_struct *vma;
+ struct anon_vma_chain *avc;
int referenced = 0;
anon_vma = page_lock_anon_vma(page);
@@ -404,7 +493,8 @@ static int page_referenced_anon(struct page *page,
return referenced;
mapcount = page_mapcount(page);
- list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
+ list_for_each_entry(avc, &anon_vma->head, same_anon_vma) {
+ struct vm_area_struct *vma = avc->vma;
unsigned long address = vma_address(page, vma);
if (address == -EFAULT)
continue;
@@ -511,9 +601,6 @@ int page_referenced(struct page *page,
int referenced = 0;
int we_locked = 0;
- if (TestClearPageReferenced(page))
- referenced++;
-
*vm_flags = 0;
if (page_mapped(page) && page_rmapping(page)) {
if (!is_locked && (!PageAnon(page) || PageKsm(page))) {
@@ -614,6 +701,30 @@ int page_mkclean(struct page *page)
EXPORT_SYMBOL_GPL(page_mkclean);
/**
+ * page_move_anon_rmap - move a page to our anon_vma
+ * @page: the page to move to our anon_vma
+ * @vma: the vma the page belongs to
+ * @address: the user virtual address mapped
+ *
+ * When a page belongs exclusively to one process after a COW event,
+ * that page can be moved into the anon_vma that belongs to just that
+ * process, so the rmap code will not search the parent or sibling
+ * processes.
+ */
+void page_move_anon_rmap(struct page *page,
+ struct vm_area_struct *vma, unsigned long address)
+{
+ struct anon_vma *anon_vma = vma->anon_vma;
+
+ VM_BUG_ON(!PageLocked(page));
+ VM_BUG_ON(!anon_vma);
+ VM_BUG_ON(page->index != linear_page_index(vma, address));
+
+ anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON;
+ page->mapping = (struct address_space *) anon_vma;
+}
+
+/**
* __page_set_anon_rmap - setup new anonymous rmap
* @page: the page to add the mapping to
* @vma: the vm area in which the mapping is added
@@ -652,9 +763,6 @@ static void __page_check_anon_rmap(struct page *page,
* are initially only visible via the pagetables, and the pte is locked
* over the call to page_add_new_anon_rmap.
*/
- struct anon_vma *anon_vma = vma->anon_vma;
- anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON;
- BUG_ON(page->mapping != (struct address_space *)anon_vma);
BUG_ON(page->index != linear_page_index(vma, address));
#endif
}
@@ -815,9 +923,9 @@ int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
if (PageHWPoison(page) && !(flags & TTU_IGNORE_HWPOISON)) {
if (PageAnon(page))
- dec_mm_counter(mm, anon_rss);
+ dec_mm_counter(mm, MM_ANONPAGES);
else
- dec_mm_counter(mm, file_rss);
+ dec_mm_counter(mm, MM_FILEPAGES);
set_pte_at(mm, address, pte,
swp_entry_to_pte(make_hwpoison_entry(page)));
} else if (PageAnon(page)) {
@@ -839,7 +947,8 @@ int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
list_add(&mm->mmlist, &init_mm.mmlist);
spin_unlock(&mmlist_lock);
}
- dec_mm_counter(mm, anon_rss);
+ dec_mm_counter(mm, MM_ANONPAGES);
+ inc_mm_counter(mm, MM_SWAPENTS);
} else if (PAGE_MIGRATION) {
/*
* Store the pfn of the page in a special migration
@@ -857,7 +966,7 @@ int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
entry = make_migration_entry(page, pte_write(pteval));
set_pte_at(mm, address, pte, swp_entry_to_pte(entry));
} else
- dec_mm_counter(mm, file_rss);
+ dec_mm_counter(mm, MM_FILEPAGES);
page_remove_rmap(page);
page_cache_release(page);
@@ -996,7 +1105,7 @@ static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount,
page_remove_rmap(page);
page_cache_release(page);
- dec_mm_counter(mm, file_rss);
+ dec_mm_counter(mm, MM_FILEPAGES);
(*mapcount)--;
}
pte_unmap_unlock(pte - 1, ptl);
@@ -1024,14 +1133,15 @@ static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount,
static int try_to_unmap_anon(struct page *page, enum ttu_flags flags)
{
struct anon_vma *anon_vma;
- struct vm_area_struct *vma;
+ struct anon_vma_chain *avc;
int ret = SWAP_AGAIN;
anon_vma = page_lock_anon_vma(page);
if (!anon_vma)
return ret;
- list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
+ list_for_each_entry(avc, &anon_vma->head, same_anon_vma) {
+ struct vm_area_struct *vma = avc->vma;
unsigned long address = vma_address(page, vma);
if (address == -EFAULT)
continue;
@@ -1222,7 +1332,7 @@ static int rmap_walk_anon(struct page *page, int (*rmap_one)(struct page *,
struct vm_area_struct *, unsigned long, void *), void *arg)
{
struct anon_vma *anon_vma;
- struct vm_area_struct *vma;
+ struct anon_vma_chain *avc;
int ret = SWAP_AGAIN;
/*
@@ -1237,7 +1347,8 @@ static int rmap_walk_anon(struct page *page, int (*rmap_one)(struct page *,
if (!anon_vma)
return ret;
spin_lock(&anon_vma->lock);
- list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
+ list_for_each_entry(avc, &anon_vma->head, same_anon_vma) {
+ struct vm_area_struct *vma = avc->vma;
unsigned long address = vma_address(page, vma);
if (address == -EFAULT)
continue;
diff --git a/mm/slub.c b/mm/slub.c
index 0bfd3863d52..a2b8969ba6d 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -4390,7 +4390,7 @@ static void kmem_cache_release(struct kobject *kobj)
kfree(s);
}
-static struct sysfs_ops slab_sysfs_ops = {
+static const struct sysfs_ops slab_sysfs_ops = {
.show = slab_attr_show,
.store = slab_attr_store,
};
@@ -4409,7 +4409,7 @@ static int uevent_filter(struct kset *kset, struct kobject *kobj)
return 0;
}
-static struct kset_uevent_ops slab_uevent_ops = {
+static const struct kset_uevent_ops slab_uevent_ops = {
.filter = uevent_filter,
};
diff --git a/mm/swap.c b/mm/swap.c
index 308e57d8d7e..9036b89813a 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -55,7 +55,7 @@ static void __page_cache_release(struct page *page)
del_page_from_lru(zone, page);
spin_unlock_irqrestore(&zone->lru_lock, flags);
}
- free_hot_page(page);
+ free_hot_cold_page(page, 0);
}
static void put_compound_page(struct page *page)
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 6c0585b1641..84374d8cf81 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -840,7 +840,8 @@ static int unuse_pte(struct vm_area_struct *vma, pmd_t *pmd,
goto out;
}
- inc_mm_counter(vma->vm_mm, anon_rss);
+ dec_mm_counter(vma->vm_mm, MM_SWAPENTS);
+ inc_mm_counter(vma->vm_mm, MM_ANONPAGES);
get_page(page);
set_pte_at(vma->vm_mm, addr, pte,
pte_mkold(mk_pte(page, vma->vm_page_prot)));
@@ -1759,11 +1760,11 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
unsigned int type;
int i, prev;
int error;
- union swap_header *swap_header = NULL;
- unsigned int nr_good_pages = 0;
+ union swap_header *swap_header;
+ unsigned int nr_good_pages;
int nr_extents = 0;
sector_t span;
- unsigned long maxpages = 1;
+ unsigned long maxpages;
unsigned long swapfilepages;
unsigned char *swap_map = NULL;
struct page *page = NULL;
@@ -1922,9 +1923,13 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
* swap pte.
*/
maxpages = swp_offset(pte_to_swp_entry(
- swp_entry_to_pte(swp_entry(0, ~0UL)))) - 1;
- if (maxpages > swap_header->info.last_page)
- maxpages = swap_header->info.last_page;
+ swp_entry_to_pte(swp_entry(0, ~0UL)))) + 1;
+ if (maxpages > swap_header->info.last_page) {
+ maxpages = swap_header->info.last_page + 1;
+ /* p->max is an unsigned int: don't overflow it */
+ if ((unsigned int)maxpages == 0)
+ maxpages = UINT_MAX;
+ }
p->highest_bit = maxpages - 1;
error = -EINVAL;
@@ -1948,23 +1953,24 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
}
memset(swap_map, 0, maxpages);
+ nr_good_pages = maxpages - 1; /* omit header page */
+
for (i = 0; i < swap_header->info.nr_badpages; i++) {
- int page_nr = swap_header->info.badpages[i];
- if (page_nr <= 0 || page_nr >= swap_header->info.last_page) {
+ unsigned int page_nr = swap_header->info.badpages[i];
+ if (page_nr == 0 || page_nr > swap_header->info.last_page) {
error = -EINVAL;
goto bad_swap;
}
- swap_map[page_nr] = SWAP_MAP_BAD;
+ if (page_nr < maxpages) {
+ swap_map[page_nr] = SWAP_MAP_BAD;
+ nr_good_pages--;
+ }
}
error = swap_cgroup_swapon(type, maxpages);
if (error)
goto bad_swap;
- nr_good_pages = swap_header->info.last_page -
- swap_header->info.nr_badpages -
- 1 /* header page */;
-
if (nr_good_pages) {
swap_map[0] = SWAP_MAP_BAD;
p->max = maxpages;
@@ -2155,7 +2161,11 @@ void swap_shmem_alloc(swp_entry_t entry)
}
/*
- * increase reference count of swap entry by 1.
+ * Increase reference count of swap entry by 1.
+ * Returns 0 for success, or -ENOMEM if a swap_count_continuation is required
+ * but could not be atomically allocated. Returns 0, just as if it succeeded,
+ * if __swap_duplicate() fails for another reason (-EINVAL or -ENOENT), which
+ * might occur if a page table entry has got corrupted.
*/
int swap_duplicate(swp_entry_t entry)
{
diff --git a/mm/vmscan.c b/mm/vmscan.c
index c26986c85ce..79c809895fb 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -262,27 +262,6 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
return ret;
}
-/* Called without lock on whether page is mapped, so answer is unstable */
-static inline int page_mapping_inuse(struct page *page)
-{
- struct address_space *mapping;
-
- /* Page is in somebody's page tables. */
- if (page_mapped(page))
- return 1;
-
- /* Be more reluctant to reclaim swapcache than pagecache */
- if (PageSwapCache(page))
- return 1;
-
- mapping = page_mapping(page);
- if (!mapping)
- return 0;
-
- /* File is mmap'd by somebody? */
- return mapping_mapped(mapping);
-}
-
static inline int is_page_cache_freeable(struct page *page)
{
/*
@@ -579,6 +558,65 @@ redo:
put_page(page); /* drop ref from isolate */
}
+enum page_references {
+ PAGEREF_RECLAIM,
+ PAGEREF_RECLAIM_CLEAN,
+ PAGEREF_KEEP,
+ PAGEREF_ACTIVATE,
+};
+
+static enum page_references page_check_references(struct page *page,
+ struct scan_control *sc)
+{
+ int referenced_ptes, referenced_page;
+ unsigned long vm_flags;
+
+ referenced_ptes = page_referenced(page, 1, sc->mem_cgroup, &vm_flags);
+ referenced_page = TestClearPageReferenced(page);
+
+ /* Lumpy reclaim - ignore references */
+ if (sc->order > PAGE_ALLOC_COSTLY_ORDER)
+ return PAGEREF_RECLAIM;
+
+ /*
+ * Mlock lost the isolation race with us. Let try_to_unmap()
+ * move the page to the unevictable list.
+ */
+ if (vm_flags & VM_LOCKED)
+ return PAGEREF_RECLAIM;
+
+ if (referenced_ptes) {
+ if (PageAnon(page))
+ return PAGEREF_ACTIVATE;
+ /*
+ * All mapped pages start out with page table
+ * references from the instantiating fault, so we need
+ * to look twice if a mapped file page is used more
+ * than once.
+ *
+ * Mark it and spare it for another trip around the
+ * inactive list. Another page table reference will
+ * lead to its activation.
+ *
+ * Note: the mark is set for activated pages as well
+ * so that recently deactivated but used pages are
+ * quickly recovered.
+ */
+ SetPageReferenced(page);
+
+ if (referenced_page)
+ return PAGEREF_ACTIVATE;
+
+ return PAGEREF_KEEP;
+ }
+
+ /* Reclaim if clean, defer dirty pages to writeback */
+ if (referenced_page)
+ return PAGEREF_RECLAIM_CLEAN;
+
+ return PAGEREF_RECLAIM;
+}
+
/*
* shrink_page_list() returns the number of reclaimed pages
*/
@@ -590,16 +628,15 @@ static unsigned long shrink_page_list(struct list_head *page_list,
struct pagevec freed_pvec;
int pgactivate = 0;
unsigned long nr_reclaimed = 0;
- unsigned long vm_flags;
cond_resched();
pagevec_init(&freed_pvec, 1);
while (!list_empty(page_list)) {
+ enum page_references references;
struct address_space *mapping;
struct page *page;
int may_enter_fs;
- int referenced;
cond_resched();
@@ -641,17 +678,16 @@ static unsigned long shrink_page_list(struct list_head *page_list,
goto keep_locked;
}
- referenced = page_referenced(page, 1,
- sc->mem_cgroup, &vm_flags);
- /*
- * In active use or really unfreeable? Activate it.
- * If page which have PG_mlocked lost isoltation race,
- * try_to_unmap moves it to unevictable list
- */
- if (sc->order <= PAGE_ALLOC_COSTLY_ORDER &&
- referenced && page_mapping_inuse(page)
- && !(vm_flags & VM_LOCKED))
+ references = page_check_references(page, sc);
+ switch (references) {
+ case PAGEREF_ACTIVATE:
goto activate_locked;
+ case PAGEREF_KEEP:
+ goto keep_locked;
+ case PAGEREF_RECLAIM:
+ case PAGEREF_RECLAIM_CLEAN:
+ ; /* try to reclaim the page below */
+ }
/*
* Anonymous process memory has backing store?
@@ -685,7 +721,7 @@ static unsigned long shrink_page_list(struct list_head *page_list,
}
if (PageDirty(page)) {
- if (sc->order <= PAGE_ALLOC_COSTLY_ORDER && referenced)
+ if (references == PAGEREF_RECLAIM_CLEAN)
goto keep_locked;
if (!may_enter_fs)
goto keep_locked;
@@ -1350,9 +1386,7 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone,
continue;
}
- /* page_referenced clears PageReferenced */
- if (page_mapping_inuse(page) &&
- page_referenced(page, 0, sc->mem_cgroup, &vm_flags)) {
+ if (page_referenced(page, 0, sc->mem_cgroup, &vm_flags)) {
nr_rotated++;
/*
* Identify referenced, file-backed active pages and
@@ -1501,6 +1535,13 @@ static void get_scan_ratio(struct zone *zone, struct scan_control *sc,
unsigned long ap, fp;
struct zone_reclaim_stat *reclaim_stat = get_reclaim_stat(zone, sc);
+ /* If we have no swap space, do not bother scanning anon pages. */
+ if (!sc->may_swap || (nr_swap_pages <= 0)) {
+ percent[0] = 0;
+ percent[1] = 100;
+ return;
+ }
+
anon = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_ANON) +
zone_nr_lru_pages(zone, sc, LRU_INACTIVE_ANON);
file = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_FILE) +
@@ -1598,22 +1639,20 @@ static void shrink_zone(int priority, struct zone *zone,
unsigned long nr_reclaimed = sc->nr_reclaimed;
unsigned long nr_to_reclaim = sc->nr_to_reclaim;
struct zone_reclaim_stat *reclaim_stat = get_reclaim_stat(zone, sc);
- int noswap = 0;
- /* If we have no swap space, do not bother scanning anon pages. */
- if (!sc->may_swap || (nr_swap_pages <= 0)) {
- noswap = 1;
- percent[0] = 0;
- percent[1] = 100;
- } else
- get_scan_ratio(zone, sc, percent);
+ get_scan_ratio(zone, sc, percent);
for_each_evictable_lru(l) {
int file = is_file_lru(l);
unsigned long scan;
+ if (percent[file] == 0) {
+ nr[l] = 0;
+ continue;
+ }
+
scan = zone_nr_lru_pages(zone, sc, l);
- if (priority || noswap) {
+ if (priority) {
scan >>= priority;
scan = (scan * percent[file]) / 100;
}
@@ -1694,8 +1733,7 @@ static void shrink_zones(int priority, struct zonelist *zonelist,
continue;
note_zone_scanning_priority(zone, priority);
- if (zone_is_all_unreclaimable(zone) &&
- priority != DEF_PRIORITY)
+ if (zone->all_unreclaimable && priority != DEF_PRIORITY)
continue; /* Let kswapd poll it */
sc->all_unreclaimable = 0;
} else {
@@ -1922,7 +1960,7 @@ static int sleeping_prematurely(pg_data_t *pgdat, int order, long remaining)
if (!populated_zone(zone))
continue;
- if (zone_is_all_unreclaimable(zone))
+ if (zone->all_unreclaimable)
continue;
if (!zone_watermark_ok(zone, order, high_wmark_pages(zone),
@@ -2012,8 +2050,7 @@ loop_again:
if (!populated_zone(zone))
continue;
- if (zone_is_all_unreclaimable(zone) &&
- priority != DEF_PRIORITY)
+ if (zone->all_unreclaimable && priority != DEF_PRIORITY)
continue;
/*
@@ -2056,13 +2093,9 @@ loop_again:
if (!populated_zone(zone))
continue;
- if (zone_is_all_unreclaimable(zone) &&
- priority != DEF_PRIORITY)
+ if (zone->all_unreclaimable && priority != DEF_PRIORITY)
continue;
- if (!zone_watermark_ok(zone, order,
- high_wmark_pages(zone), end_zone, 0))
- all_zones_ok = 0;
temp_priority[i] = priority;
sc.nr_scanned = 0;
note_zone_scanning_priority(zone, priority);
@@ -2087,12 +2120,11 @@ loop_again:
lru_pages);
sc.nr_reclaimed += reclaim_state->reclaimed_slab;
total_scanned += sc.nr_scanned;
- if (zone_is_all_unreclaimable(zone))
+ if (zone->all_unreclaimable)
continue;
- if (nr_slab == 0 && zone->pages_scanned >=
- (zone_reclaimable_pages(zone) * 6))
- zone_set_flag(zone,
- ZONE_ALL_UNRECLAIMABLE);
+ if (nr_slab == 0 &&
+ zone->pages_scanned >= (zone_reclaimable_pages(zone) * 6))
+ zone->all_unreclaimable = 1;
/*
* If we've done a decent amount of scanning and
* the reclaim ratio is low, start doing writepage
@@ -2102,13 +2134,18 @@ loop_again:
total_scanned > sc.nr_reclaimed + sc.nr_reclaimed / 2)
sc.may_writepage = 1;
- /*
- * We are still under min water mark. it mean we have
- * GFP_ATOMIC allocation failure risk. Hurry up!
- */
- if (!zone_watermark_ok(zone, order, min_wmark_pages(zone),
- end_zone, 0))
- has_under_min_watermark_zone = 1;
+ if (!zone_watermark_ok(zone, order,
+ high_wmark_pages(zone), end_zone, 0)) {
+ all_zones_ok = 0;
+ /*
+ * We are still under min water mark. This
+ * means that we have a GFP_ATOMIC allocation
+ * failure risk. Hurry up!
+ */
+ if (!zone_watermark_ok(zone, order,
+ min_wmark_pages(zone), end_zone, 0))
+ has_under_min_watermark_zone = 1;
+ }
}
if (all_zones_ok)
@@ -2550,6 +2587,7 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
* and RECLAIM_SWAP.
*/
p->flags |= PF_MEMALLOC | PF_SWAPWRITE;
+ lockdep_set_current_reclaim_state(gfp_mask);
reclaim_state.reclaimed_slab = 0;
p->reclaim_state = &reclaim_state;
@@ -2593,6 +2631,7 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
p->reclaim_state = NULL;
current->flags &= ~(PF_MEMALLOC | PF_SWAPWRITE);
+ lockdep_clear_current_reclaim_state();
return sc.nr_reclaimed >= nr_pages;
}
@@ -2615,7 +2654,7 @@ int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
zone_page_state(zone, NR_SLAB_RECLAIMABLE) <= zone->min_slab_pages)
return ZONE_RECLAIM_FULL;
- if (zone_is_all_unreclaimable(zone))
+ if (zone->all_unreclaimable)
return ZONE_RECLAIM_FULL;
/*
diff --git a/mm/vmstat.c b/mm/vmstat.c
index fc5aa183bc4..7f760cbc73f 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -763,7 +763,7 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
"\n prev_priority: %i"
"\n start_pfn: %lu"
"\n inactive_ratio: %u",
- zone_is_all_unreclaimable(zone),
+ zone->all_unreclaimable,
zone->prev_priority,
zone->zone_start_pfn,
zone->inactive_ratio);
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c
index 400efa26ddb..4db7ae2fe07 100644
--- a/net/bluetooth/l2cap.c
+++ b/net/bluetooth/l2cap.c
@@ -3937,7 +3937,9 @@ drop:
return 0;
}
-static ssize_t l2cap_sysfs_show(struct class *dev, char *buf)
+static ssize_t l2cap_sysfs_show(struct class *dev,
+ struct class_attribute *attr,
+ char *buf)
{
struct sock *sk;
struct hlist_node *node;
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 89f4a59eb82..db8a68e1a5b 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -2098,7 +2098,9 @@ static struct hci_cb rfcomm_cb = {
.security_cfm = rfcomm_security_cfm
};
-static ssize_t rfcomm_dlc_sysfs_show(struct class *dev, char *buf)
+static ssize_t rfcomm_dlc_sysfs_show(struct class *dev,
+ struct class_attribute *attr,
+ char *buf)
{
struct rfcomm_session *s;
struct list_head *pp, *p;
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 4b5968dda67..ca87d6ac6a2 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -1061,7 +1061,9 @@ done:
return result;
}
-static ssize_t rfcomm_sock_sysfs_show(struct class *dev, char *buf)
+static ssize_t rfcomm_sock_sysfs_show(struct class *dev,
+ struct class_attribute *attr,
+ char *buf)
{
struct sock *sk;
struct hlist_node *node;
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index dd8f6ec57dc..f93b939539b 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -953,7 +953,9 @@ drop:
return 0;
}
-static ssize_t sco_sysfs_show(struct class *dev, char *buf)
+static ssize_t sco_sysfs_show(struct class *dev,
+ struct class_attribute *attr,
+ char *buf)
{
struct sock *sk;
struct hlist_node *node;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 1cf2cef7858..fef0384e3c0 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -423,7 +423,7 @@ extern void br_ifinfo_notify(int event, struct net_bridge_port *port);
#ifdef CONFIG_SYSFS
/* br_sysfs_if.c */
-extern struct sysfs_ops brport_sysfs_ops;
+extern const struct sysfs_ops brport_sysfs_ops;
extern int br_sysfs_addif(struct net_bridge_port *p);
/* br_sysfs_br.c */
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c
index 696596cd338..0b9916489d6 100644
--- a/net/bridge/br_sysfs_if.c
+++ b/net/bridge/br_sysfs_if.c
@@ -238,7 +238,7 @@ static ssize_t brport_store(struct kobject * kobj,
return ret;
}
-struct sysfs_ops brport_sysfs_ops = {
+const struct sysfs_ops brport_sysfs_ops = {
.show = brport_show,
.store = brport_store,
};
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 6dcf8c9c784..8420a4205b7 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -133,7 +133,7 @@ svc_pool_map_choose_mode(void)
return SVC_POOL_PERNODE;
}
- node = any_online_node(node_online_map);
+ node = first_online_node;
if (nr_cpus_node(node) > 2) {
/*
* Non-trivial SMP, or CONFIG_NUMA on
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index 7d1f9e928f6..8f0f1fb3dc5 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -173,11 +173,13 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl,
.sin_addr.s_addr = htonl(INADDR_ANY),
.sin_port = htons(port),
};
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct sockaddr_in6 sin6 = {
.sin6_family = AF_INET6,
.sin6_addr = IN6ADDR_ANY_INIT,
.sin6_port = htons(port),
};
+#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
struct sockaddr *sap;
size_t len;
@@ -186,10 +188,12 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl,
sap = (struct sockaddr *)&sin;
len = sizeof(sin);
break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
case PF_INET6:
sap = (struct sockaddr *)&sin6;
len = sizeof(sin6);
break;
+#endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
default:
return ERR_PTR(-EAFNOSUPPORT);
}
@@ -231,7 +235,10 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
err:
spin_unlock(&svc_xprt_class_lock);
dprintk("svc: transport %s not found\n", xprt_name);
- return -ENOENT;
+
+ /* This errno is exposed to user space. Provide a reasonable
+ * perror msg for a bad transport. */
+ return -EPROTONOSUPPORT;
}
EXPORT_SYMBOL_GPL(svc_create_xprt);
@@ -699,8 +706,10 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
spin_unlock_bh(&pool->sp_lock);
len = 0;
- if (test_bit(XPT_LISTENER, &xprt->xpt_flags) &&
- !test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
+ if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
+ dprintk("svc_recv: found XPT_CLOSE\n");
+ svc_delete_xprt(xprt);
+ } else if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) {
struct svc_xprt *newxpt;
newxpt = xprt->xpt_ops->xpo_accept(xprt);
if (newxpt) {
@@ -726,7 +735,7 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
svc_xprt_received(newxpt);
}
svc_xprt_received(xprt);
- } else if (!test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
+ } else {
dprintk("svc: server %p, pool %u, transport %p, inuse=%d\n",
rqstp, pool->sp_id, xprt,
atomic_read(&xprt->xpt_ref.refcount));
@@ -739,11 +748,6 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
dprintk("svc: got len=%d\n", len);
}
- if (test_bit(XPT_CLOSE, &xprt->xpt_flags)) {
- dprintk("svc_recv: found XPT_CLOSE\n");
- svc_delete_xprt(xprt);
- }
-
/* No data, incomplete (TCP) read, or accept() */
if (len == 0 || len == -EAGAIN) {
rqstp->rq_res.len = 0;
@@ -889,11 +893,8 @@ void svc_delete_xprt(struct svc_xprt *xprt)
if (test_bit(XPT_TEMP, &xprt->xpt_flags))
serv->sv_tmpcnt--;
- for (dr = svc_deferred_dequeue(xprt); dr;
- dr = svc_deferred_dequeue(xprt)) {
- svc_xprt_put(xprt);
+ while ((dr = svc_deferred_dequeue(xprt)) != NULL)
kfree(dr);
- }
svc_xprt_put(xprt);
spin_unlock_bh(&serv->sv_lock);
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index d8c04111449..afdcb0459a8 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#define RPCDBG_FACILITY RPCDBG_AUTH
+#include <linux/sunrpc/clnt.h>
/*
* AUTHUNIX and AUTHNULL credentials are both handled here.
@@ -187,10 +188,13 @@ static int ip_map_parse(struct cache_detail *cd,
* for scratch: */
char *buf = mesg;
int len;
- int b1, b2, b3, b4, b5, b6, b7, b8;
- char c;
char class[8];
- struct in6_addr addr;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in s4;
+ struct sockaddr_in6 s6;
+ } address;
+ struct sockaddr_in6 sin6;
int err;
struct ip_map *ipmp;
@@ -209,24 +213,24 @@ static int ip_map_parse(struct cache_detail *cd,
len = qword_get(&mesg, buf, mlen);
if (len <= 0) return -EINVAL;
- if (sscanf(buf, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) == 4) {
- addr.s6_addr32[0] = 0;
- addr.s6_addr32[1] = 0;
- addr.s6_addr32[2] = htonl(0xffff);
- addr.s6_addr32[3] =
- htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4);
- } else if (sscanf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x%c",
- &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &c) == 8) {
- addr.s6_addr16[0] = htons(b1);
- addr.s6_addr16[1] = htons(b2);
- addr.s6_addr16[2] = htons(b3);
- addr.s6_addr16[3] = htons(b4);
- addr.s6_addr16[4] = htons(b5);
- addr.s6_addr16[5] = htons(b6);
- addr.s6_addr16[6] = htons(b7);
- addr.s6_addr16[7] = htons(b8);
- } else
+ if (rpc_pton(buf, len, &address.sa, sizeof(address)) == 0)
return -EINVAL;
+ switch (address.sa.sa_family) {
+ case AF_INET:
+ /* Form a mapped IPv4 address in sin6 */
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
+ sin6.sin6_addr.s6_addr32[3] = address.s4.sin_addr.s_addr;
+ break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ case AF_INET6:
+ memcpy(&sin6, &address.s6, sizeof(sin6));
+ break;
+#endif
+ default:
+ return -EINVAL;
+ }
expiry = get_expiry(&mesg);
if (expiry ==0)
@@ -243,7 +247,8 @@ static int ip_map_parse(struct cache_detail *cd,
} else
dom = NULL;
- ipmp = ip_map_lookup(class, &addr);
+ /* IPv6 scope IDs are ignored for now */
+ ipmp = ip_map_lookup(class, &sin6.sin6_addr);
if (ipmp) {
err = ip_map_update(ipmp,
container_of(dom, struct unix_domain, h),
@@ -619,7 +624,7 @@ static int unix_gid_show(struct seq_file *m,
else
glen = 0;
- seq_printf(m, "%d %d:", ug->uid, glen);
+ seq_printf(m, "%u %d:", ug->uid, glen);
for (i = 0; i < glen; i++)
seq_printf(m, " %d", GROUP_AT(ug->gi, i));
seq_printf(m, "\n");
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 870929e08e5..a29f259204e 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -968,6 +968,7 @@ static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp)
return len;
err_delete:
set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
+ svc_xprt_received(&svsk->sk_xprt);
err_again:
return -EAGAIN;
}
@@ -1357,7 +1358,7 @@ int svc_addsock(struct svc_serv *serv, const int fd, char *name_return,
if (!so)
return err;
- if (so->sk->sk_family != AF_INET)
+ if ((so->sk->sk_family != PF_INET) && (so->sk->sk_family != PF_INET6))
err = -EAFNOSUPPORT;
else if (so->sk->sk_protocol != IPPROTO_TCP &&
so->sk->sk_protocol != IPPROTO_UDP)
diff --git a/samples/kobject/kobject-example.c b/samples/kobject/kobject-example.c
index 8d9b55a1202..86ea0c3ad97 100644
--- a/samples/kobject/kobject-example.c
+++ b/samples/kobject/kobject-example.c
@@ -44,7 +44,7 @@ static struct kobj_attribute foo_attribute =
__ATTR(foo, 0666, foo_show, foo_store);
/*
- * More complex function where we determine which varible is being accessed by
+ * More complex function where we determine which variable is being accessed by
* looking at the attribute for the "baz" and "bar" files.
*/
static ssize_t b_show(struct kobject *kobj, struct kobj_attribute *attr,
@@ -79,7 +79,7 @@ static struct kobj_attribute bar_attribute =
/*
- * Create a group of attributes so that we can create and destory them all
+ * Create a group of attributes so that we can create and destroy them all
* at once.
*/
static struct attribute *attrs[] = {
diff --git a/samples/kobject/kset-example.c b/samples/kobject/kset-example.c
index 45b7d56fb54..3b126d1f859 100644
--- a/samples/kobject/kset-example.c
+++ b/samples/kobject/kset-example.c
@@ -87,7 +87,7 @@ static ssize_t foo_attr_store(struct kobject *kobj,
}
/* Our custom sysfs_ops that we will associate with our ktype later on */
-static struct sysfs_ops foo_sysfs_ops = {
+static const struct sysfs_ops foo_sysfs_ops = {
.show = foo_attr_show,
.store = foo_attr_store,
};
@@ -127,7 +127,7 @@ static struct foo_attribute foo_attribute =
__ATTR(foo, 0666, foo_show, foo_store);
/*
- * More complex function where we determine which varible is being accessed by
+ * More complex function where we determine which variable is being accessed by
* looking at the attribute for the "baz" and "bar" files.
*/
static ssize_t b_show(struct foo_obj *foo_obj, struct foo_attribute *attr,
@@ -161,7 +161,7 @@ static struct foo_attribute bar_attribute =
__ATTR(bar, 0666, b_show, b_store);
/*
- * Create a group of attributes so that we can create and destory them all
+ * Create a group of attributes so that we can create and destroy them all
* at once.
*/
static struct attribute *foo_default_attrs[] = {
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 3257d3d9676..a4d74344d80 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -145,11 +145,14 @@ our $Sparse = qr{
__kprobes|
__ref
}x;
+
+# Notes to $Attribute:
+# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
our $Attribute = qr{
const|
__read_mostly|
__kprobes|
- __(?:mem|cpu|dev|)(?:initdata|init)|
+ __(?:mem|cpu|dev|)(?:initdata|initconst|init\b)|
____cacheline_aligned|
____cacheline_aligned_in_smp|
____cacheline_internodealigned_in_smp|
@@ -189,6 +192,14 @@ our $typeTypedefs = qr{(?x:
atomic_t
)};
+our $logFunctions = qr{(?x:
+ printk|
+ pr_(debug|dbg|vdbg|devel|info|warning|err|notice|alert|crit|emerg|cont)|
+ dev_(printk|dbg|vdbg|info|warn|err|notice|alert|crit|emerg|WARN)|
+ WARN|
+ panic
+)};
+
our @typeList = (
qr{void},
qr{(?:unsigned\s+)?char},
@@ -1377,12 +1388,17 @@ sub process {
#80 column limit
if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ &&
$rawline !~ /^.\s*\*\s*\@$Ident\s/ &&
- $line !~ /^\+\s*printk\s*\(\s*(?:KERN_\S+\s*)?"[X\t]*"\s*(?:,|\)\s*;)\s*$/ &&
+ $line !~ /^\+\s*$logFunctions\s*\(\s*(?:KERN_\S+\s*)?"[X\t]*"\s*(?:,|\)\s*;)\s*$/ &&
$length > 80)
{
WARN("line over 80 characters\n" . $herecurr);
}
+# check for spaces before a quoted newline
+ if ($rawline =~ /^.*\".*\s\\n/) {
+ WARN("unnecessary whitespace before a quoted newline\n" . $herecurr);
+ }
+
# check for adding lines without a newline.
if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) {
WARN("adding a line without newline at end of file\n" . $herecurr);
@@ -1411,6 +1427,12 @@ sub process {
ERROR("code indent should use tabs where possible\n" . $herevet);
}
+# check for space before tabs.
+ if ($rawline =~ /^\+/ && $rawline =~ / \t/) {
+ my $herevet = "$here\n" . cat_vet($rawline) . "\n";
+ WARN("please, no space before tabs\n" . $herevet);
+ }
+
# check we are in a valid C source file if not then ignore this hunk
next if ($realfile !~ /\.(h|c)$/);
@@ -2182,8 +2204,10 @@ sub process {
# Find out how long the conditional actually is.
my @newlines = ($c =~ /\n/gs);
my $cond_lines = 1 + $#newlines;
+ my $stat_real = '';
- my $stat_real = raw_line($linenr, $cond_lines);
+ $stat_real = raw_line($linenr, $cond_lines)
+ . "\n" if ($cond_lines);
if (defined($stat_real) && $cond_lines > 1) {
$stat_real = "[...]\n$stat_real";
}
@@ -2348,6 +2372,8 @@ sub process {
DECLARE_PER_CPU|
DEFINE_PER_CPU|
__typeof__\(|
+ union|
+ struct|
\.$Ident\s*=\s*|
^\"|\"$
}x;
@@ -2572,6 +2598,11 @@ sub process {
WARN("plain inline is preferred over $1\n" . $herecurr);
}
+# check for sizeof(&)
+ if ($line =~ /\bsizeof\s*\(\s*\&/) {
+ WARN("sizeof(& should be avoided\n" . $herecurr);
+ }
+
# check for new externs in .c files.
if ($realfile =~ /\.c$/ && defined $stat &&
$stat =~ /^.\s*(?:extern\s+)?$Type\s+($Ident)(\s*)\(/s)
@@ -2634,9 +2665,46 @@ sub process {
if ($line =~ /^.\s*__initcall\s*\(/) {
WARN("please use device_initcall() instead of __initcall()\n" . $herecurr);
}
-# check for struct file_operations, ensure they are const.
+# check for various ops structs, ensure they are const.
+ my $struct_ops = qr{acpi_dock_ops|
+ address_space_operations|
+ backlight_ops|
+ block_device_operations|
+ dentry_operations|
+ dev_pm_ops|
+ dma_map_ops|
+ extent_io_ops|
+ file_lock_operations|
+ file_operations|
+ hv_ops|
+ ide_dma_ops|
+ intel_dvo_dev_ops|
+ item_operations|
+ iwl_ops|
+ kgdb_arch|
+ kgdb_io|
+ kset_uevent_ops|
+ lock_manager_operations|
+ microcode_ops|
+ mtrr_ops|
+ neigh_ops|
+ nlmsvc_binding|
+ pci_raw_ops|
+ pipe_buf_operations|
+ platform_hibernation_ops|
+ platform_suspend_ops|
+ proto_ops|
+ rpc_pipe_ops|
+ seq_operations|
+ snd_ac97_build_ops|
+ soc_pcmcia_socket_ops|
+ stacktrace_ops|
+ sysfs_ops|
+ tty_operations|
+ usb_mon_operations|
+ wd_ops}x;
if ($line !~ /\bconst\b/ &&
- $line =~ /\bstruct\s+(file_operations|seq_operations)\b/) {
+ $line =~ /\bstruct\s+($struct_ops)\b/) {
WARN("struct $1 should normally be const\n" .
$herecurr);
}
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index 2f3230db7ff..f76f3d13276 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -41,6 +41,8 @@ my $web = 0;
my $subsystem = 0;
my $status = 0;
my $keywords = 1;
+my $sections = 0;
+my $file_emails = 0;
my $from_filename = 0;
my $pattern_depth = 0;
my $version = 0;
@@ -120,9 +122,11 @@ if (!GetOptions(
'web!' => \$web,
'pattern-depth=i' => \$pattern_depth,
'k|keywords!' => \$keywords,
+ 'sections!' => \$sections,
+ 'fe|file-emails!' => \$file_emails,
'f|file' => \$from_filename,
'v|version' => \$version,
- 'h|help' => \$help,
+ 'h|help|usage' => \$help,
)) {
die "$P: invalid argument - use --help if necessary\n";
}
@@ -137,9 +141,9 @@ if ($version != 0) {
exit 0;
}
-if ($#ARGV < 0) {
- usage();
- die "$P: argument missing: patchfile or -f file please\n";
+if (-t STDIN && !@ARGV) {
+ # We're talking to a terminal, but have no command line arguments.
+ die "$P: missing patchfile or -f file - use --help if necessary\n";
}
if ($output_separator ne ", ") {
@@ -150,16 +154,24 @@ if ($output_rolestats) {
$output_roles = 1;
}
-my $selections = $email + $scm + $status + $subsystem + $web;
-if ($selections == 0) {
- usage();
- die "$P: Missing required option: email, scm, status, subsystem or web\n";
+if ($sections) {
+ $email = 0;
+ $email_list = 0;
+ $scm = 0;
+ $status = 0;
+ $subsystem = 0;
+ $web = 0;
+ $keywords = 0;
+} else {
+ my $selections = $email + $scm + $status + $subsystem + $web;
+ if ($selections == 0) {
+ die "$P: Missing required option: email, scm, status, subsystem or web\n";
+ }
}
if ($email &&
($email_maintainer + $email_list + $email_subscriber_list +
$email_git + $email_git_penguin_chiefs + $email_git_blame) == 0) {
- usage();
die "$P: Please select at least 1 email option\n";
}
@@ -173,8 +185,9 @@ if (!top_of_kernel_tree($lk_path)) {
my @typevalue = ();
my %keyword_hash;
-open(MAINT, "<${lk_path}MAINTAINERS") || die "$P: Can't open MAINTAINERS\n";
-while (<MAINT>) {
+open (my $maint, '<', "${lk_path}MAINTAINERS")
+ or die "$P: Can't open MAINTAINERS: $!\n";
+while (<$maint>) {
my $line = $_;
if ($line =~ m/^(\C):\s*(.*)/) {
@@ -199,13 +212,14 @@ while (<MAINT>) {
push(@typevalue, $line);
}
}
-close(MAINT);
+close($maint);
my %mailmap;
if ($email_remove_duplicates) {
- open(MAILMAP, "<${lk_path}.mailmap") || warn "$P: Can't open .mailmap\n";
- while (<MAILMAP>) {
+ open(my $mailmap, '<', "${lk_path}.mailmap")
+ or warn "$P: Can't open .mailmap: $!\n";
+ while (<$mailmap>) {
my $line = $_;
next if ($line =~ m/^\s*#/);
@@ -224,7 +238,7 @@ if ($email_remove_duplicates) {
$mailmap{$name} = \@arr;
}
}
- close(MAILMAP);
+ close($mailmap);
}
## use the filenames on the command line or find the filenames in the patchfiles
@@ -232,31 +246,47 @@ if ($email_remove_duplicates) {
my @files = ();
my @range = ();
my @keyword_tvi = ();
+my @file_emails = ();
+
+if (!@ARGV) {
+ push(@ARGV, "&STDIN");
+}
foreach my $file (@ARGV) {
- ##if $file is a directory and it lacks a trailing slash, add one
- if ((-d $file)) {
- $file =~ s@([^/])$@$1/@;
- } elsif (!(-f $file)) {
- die "$P: file '${file}' not found\n";
+ if ($file ne "&STDIN") {
+ ##if $file is a directory and it lacks a trailing slash, add one
+ if ((-d $file)) {
+ $file =~ s@([^/])$@$1/@;
+ } elsif (!(-f $file)) {
+ die "$P: file '${file}' not found\n";
+ }
}
if ($from_filename) {
push(@files, $file);
- if (-f $file && $keywords) {
- open(FILE, "<$file") or die "$P: Can't open ${file}\n";
- my $text = do { local($/) ; <FILE> };
- foreach my $line (keys %keyword_hash) {
- if ($text =~ m/$keyword_hash{$line}/x) {
- push(@keyword_tvi, $line);
+ if (-f $file && ($keywords || $file_emails)) {
+ open(my $f, '<', $file)
+ or die "$P: Can't open $file: $!\n";
+ my $text = do { local($/) ; <$f> };
+ close($f);
+ if ($keywords) {
+ foreach my $line (keys %keyword_hash) {
+ if ($text =~ m/$keyword_hash{$line}/x) {
+ push(@keyword_tvi, $line);
+ }
}
}
- close(FILE);
+ if ($file_emails) {
+ my @poss_addr = $text =~ m$[A-Za-zÀ-ÿ\"\' \,\.\+-]*\s*[\,]*\s*[\(\<\{]{0,1}[A-Za-z0-9_\.\+-]+\@[A-Za-z0-9\.-]+\.[A-Za-z0-9]+[\)\>\}]{0,1}$g;
+ push(@file_emails, clean_file_emails(@poss_addr));
+ }
}
} else {
my $file_cnt = @files;
my $lastfile;
- open(PATCH, "<$file") or die "$P: Can't open ${file}\n";
- while (<PATCH>) {
+
+ open(my $patch, '<', $file)
+ or die "$P: Can't open $file: $!\n";
+ while (<$patch>) {
my $patch_line = $_;
if (m/^\+\+\+\s+(\S+)/) {
my $filename = $1;
@@ -276,7 +306,8 @@ foreach my $file (@ARGV) {
}
}
}
- close(PATCH);
+ close($patch);
+
if ($file_cnt == @files) {
warn "$P: file '${file}' doesn't appear to be a patch. "
. "Add -f to options?\n";
@@ -285,6 +316,8 @@ foreach my $file (@ARGV) {
}
}
+@file_emails = uniq(@file_emails);
+
my @email_to = ();
my @list_to = ();
my @scm = ();
@@ -314,6 +347,7 @@ foreach my $file (@files) {
if ($type eq 'X') {
if (file_match_pattern($file, $value)) {
$exclude = 1;
+ last;
}
}
}
@@ -340,12 +374,28 @@ foreach my $file (@files) {
}
}
- $tvi += ($end - $start);
-
+ $tvi = $end + 1;
}
foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
add_categories($line);
+ if ($sections) {
+ my $i;
+ my $start = find_starting_index($line);
+ my $end = find_ending_index($line);
+ for ($i = $start; $i < $end; $i++) {
+ my $line = $typevalue[$i];
+ if ($line =~ /^[FX]:/) { ##Restore file patterns
+ $line =~ s/([^\\])\.([^\*])/$1\?$2/g;
+ $line =~ s/([^\\])\.$/$1\?/g; ##Convert . back to ?
+ $line =~ s/\\\./\./g; ##Convert \. to .
+ $line =~ s/\.\*/\*/g; ##Convert .* to *
+ }
+ $line =~ s/^([A-Z]):/$1:\t/g;
+ print("$line\n");
+ }
+ print("\n");
+ }
}
if ($email && $email_git) {
@@ -377,6 +427,14 @@ if ($email) {
}
}
}
+
+ foreach my $email (@file_emails) {
+ my ($name, $address) = parse_email($email);
+
+ my $tmp_email = format_email($name, $address, $email_usename);
+ push_email_address($tmp_email, '');
+ add_role($tmp_email, 'in file');
+ }
}
if ($email || $email_list) {
@@ -453,6 +511,7 @@ MAINTAINER field selection options:
--remove-duplicates => minimize duplicate email names/addresses
--roles => show roles (status:subsystem, git-signer, list, etc...)
--rolestats => show roles and statistics (commits/total_commits, %)
+ --file-emails => add email addresses found in -f file (default: 0 (off))
--scm => print SCM tree(s) if any
--status => print status if any
--subsystem => print subsystem name if any
@@ -466,6 +525,7 @@ Output type options:
Other options:
--pattern-depth => Number of pattern directory traversals (default: 0 (all))
--keywords => scan patch for keywords (default: 1 (on))
+ --sections => print the entire subsystem sections with pattern matches
--version => show version
--help => show this help information
@@ -545,7 +605,7 @@ sub parse_email {
$name =~ s/^\"|\"$//g;
$address =~ s/^\s+|\s+$//g;
- if ($name =~ /[^a-z0-9 \.\-]/i) { ##has "must quote" chars
+ if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
$name =~ s/(?<!\\)"/\\"/g; ##escape quotes
$name = "\"$name\"";
}
@@ -562,7 +622,7 @@ sub format_email {
$name =~ s/^\"|\"$//g;
$address =~ s/^\s+|\s+$//g;
- if ($name =~ /[^a-z0-9 \.\-]/i) { ##has "must quote" chars
+ if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
$name =~ s/(?<!\\)"/\\"/g; ##escape quotes
$name = "\"$name\"";
}
@@ -811,7 +871,9 @@ sub add_role {
foreach my $entry (@email_to) {
if ($email_remove_duplicates) {
my ($entry_name, $entry_address) = parse_email($entry->[0]);
- if ($name eq $entry_name || $address eq $entry_address) {
+ if (($name eq $entry_name || $address eq $entry_address)
+ && ($role eq "" || !($entry->[1] =~ m/$role/))
+ ) {
if ($entry->[1] eq "") {
$entry->[1] = "$role";
} else {
@@ -819,7 +881,9 @@ sub add_role {
}
}
} else {
- if ($email eq $entry->[0]) {
+ if ($email eq $entry->[0]
+ && ($role eq "" || !($entry->[1] =~ m/$role/))
+ ) {
if ($entry->[1] eq "") {
$entry->[1] = "$role";
} else {
@@ -1099,6 +1163,51 @@ sub sort_and_uniq {
return @parms;
}
+sub clean_file_emails {
+ my (@file_emails) = @_;
+ my @fmt_emails = ();
+
+ foreach my $email (@file_emails) {
+ $email =~ s/[\(\<\{]{0,1}([A-Za-z0-9_\.\+-]+\@[A-Za-z0-9\.-]+)[\)\>\}]{0,1}/\<$1\>/g;
+ my ($name, $address) = parse_email($email);
+ if ($name eq '"[,\.]"') {
+ $name = "";
+ }
+
+ my @nw = split(/[^A-Za-zÀ-ÿ\'\,\.\+-]/, $name);
+ if (@nw > 2) {
+ my $first = $nw[@nw - 3];
+ my $middle = $nw[@nw - 2];
+ my $last = $nw[@nw - 1];
+
+ if (((length($first) == 1 && $first =~ m/[A-Za-z]/) ||
+ (length($first) == 2 && substr($first, -1) eq ".")) ||
+ (length($middle) == 1 ||
+ (length($middle) == 2 && substr($middle, -1) eq "."))) {
+ $name = "$first $middle $last";
+ } else {
+ $name = "$middle $last";
+ }
+ }
+
+ if (substr($name, -1) =~ /[,\.]/) {
+ $name = substr($name, 0, length($name) - 1);
+ } elsif (substr($name, -2) =~ /[,\.]"/) {
+ $name = substr($name, 0, length($name) - 2) . '"';
+ }
+
+ if (substr($name, 0, 1) =~ /[,\.]/) {
+ $name = substr($name, 1, length($name) - 1);
+ } elsif (substr($name, 0, 2) =~ /"[,\.]/) {
+ $name = '"' . substr($name, 2, length($name) - 2);
+ }
+
+ my $fmt_email = format_email($name, $address, $email_usename);
+ push(@fmt_emails, $fmt_email);
+ }
+ return @fmt_emails;
+}
+
sub merge_email {
my @lines;
my %saw;
@@ -1183,7 +1292,7 @@ sub rfc822_strip_comments {
# valid: returns true if the parameter is an RFC822 valid address
#
-sub rfc822_valid ($) {
+sub rfc822_valid {
my $s = rfc822_strip_comments(shift);
if (!$rfc822re) {
@@ -1203,7 +1312,7 @@ sub rfc822_valid ($) {
# from success with no addresses found, because an empty string is
# a valid list.
-sub rfc822_validlist ($) {
+sub rfc822_validlist {
my $s = rfc822_strip_comments(shift);
if (!$rfc822re) {
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 8f8b17ac074..73943651cae 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -393,7 +393,7 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
event == SNDRV_TIMER_EVENT_CONTINUE)
resolution = snd_timer_resolution(ti);
if (ti->ccallback)
- ti->ccallback(ti, SNDRV_TIMER_EVENT_START, &tstamp, resolution);
+ ti->ccallback(ti, event, &tstamp, resolution);
if (ti->flags & SNDRV_TIMER_IFLG_SLAVE)
return;
timer = ti->timer;
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index b865e45a8f9..5913717c1be 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -1558,7 +1558,7 @@ static int __devinit snd_card_miro_pnp(struct snd_miro *chip,
err = pnp_activate_dev(devmc);
if (err < 0) {
- snd_printk(KERN_ERR "OPL syntg pnp configure failure: %d\n",
+ snd_printk(KERN_ERR "MC pnp configure failure: %d\n",
err);
return err;
}
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index a4af53b5c1c..becd90d7536 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -144,12 +144,8 @@ struct snd_opti9xx {
spinlock_t lock;
+ long wss_base;
int irq;
-
-#ifdef CONFIG_PNP
- struct pnp_dev *dev;
- struct pnp_dev *devmpu;
-#endif /* CONFIG_PNP */
};
static int snd_opti9xx_pnp_is_probed;
@@ -159,12 +155,17 @@ static int snd_opti9xx_pnp_is_probed;
static struct pnp_card_device_id snd_opti9xx_pnpids[] = {
#ifndef OPTi93X
/* OPTi 82C924 */
- { .id = "OPT0924", .devs = { { "OPT0000" }, { "OPT0002" } }, .driver_data = 0x0924 },
+ { .id = "OPT0924",
+ .devs = { { "OPT0000" }, { "OPT0002" }, { "OPT0005" } },
+ .driver_data = 0x0924 },
/* OPTi 82C925 */
- { .id = "OPT0925", .devs = { { "OPT9250" }, { "OPT0002" } }, .driver_data = 0x0925 },
+ { .id = "OPT0925",
+ .devs = { { "OPT9250" }, { "OPT0002" }, { "OPT0005" } },
+ .driver_data = 0x0925 },
#else
/* OPTi 82C931/3 */
- { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } }, .driver_data = 0x0931 },
+ { .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } },
+ .driver_data = 0x0931 },
#endif /* OPTi93X */
{ .id = "" }
};
@@ -207,24 +208,34 @@ static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip,
chip->hardware = hardware;
strcpy(chip->name, snd_opti9xx_names[hardware]);
- chip->mc_base_size = opti9xx_mc_size[hardware];
-
spin_lock_init(&chip->lock);
chip->irq = -1;
+#ifndef OPTi93X
+#ifdef CONFIG_PNP
+ if (isapnp && chip->mc_base)
+ /* PnP resource gives the least 10 bits */
+ chip->mc_base |= 0xc00;
+#endif /* CONFIG_PNP */
+ else {
+ chip->mc_base = 0xf8c;
+ chip->mc_base_size = opti9xx_mc_size[hardware];
+ }
+#else
+ chip->mc_base_size = opti9xx_mc_size[hardware];
+#endif
+
switch (hardware) {
#ifndef OPTi93X
case OPTi9XX_HW_82C928:
case OPTi9XX_HW_82C929:
- chip->mc_base = 0xf8c;
chip->password = (hardware == OPTi9XX_HW_82C928) ? 0xe2 : 0xe3;
chip->pwd_reg = 3;
break;
case OPTi9XX_HW_82C924:
case OPTi9XX_HW_82C925:
- chip->mc_base = 0xf8c;
chip->password = 0xe5;
chip->pwd_reg = 3;
break;
@@ -292,7 +303,7 @@ static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip,
spin_unlock_irqrestore(&chip->lock, flags);
return retval;
}
-
+
static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg,
unsigned char value)
{
@@ -341,7 +352,7 @@ static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg,
static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip,
- long wss_base,
+ long port,
int irq, int dma1, int dma2,
long mpu_port, int mpu_irq)
{
@@ -354,16 +365,23 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip,
switch (chip->hardware) {
#ifndef OPTi93X
case OPTi9XX_HW_82C924:
+ /* opti 929 mode (?), OPL3 clock output, audio enable */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0xf0, 0xfc);
+ /* enable wave audio */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02);
case OPTi9XX_HW_82C925:
+ /* enable WSS mode */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
+ /* OPL3 FM synthesis */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20);
+ /* disable Sound Blaster IRQ and DMA */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff);
#ifdef CS4231
+ /* cs4231/4248 fix enabled */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
#else
+ /* cs4231/4248 fix disabled */
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02);
#endif /* CS4231 */
break;
@@ -411,21 +429,26 @@ static int __devinit snd_opti9xx_configure(struct snd_opti9xx *chip,
return -EINVAL;
}
- switch (wss_base) {
- case 0x530:
+ /* PnP resource says it decodes only 10 bits of address */
+ switch (port & 0x3ff) {
+ case 0x130:
+ chip->wss_base = 0x530;
wss_base_bits = 0x00;
break;
- case 0x604:
+ case 0x204:
+ chip->wss_base = 0x604;
wss_base_bits = 0x03;
break;
- case 0xe80:
+ case 0x280:
+ chip->wss_base = 0xe80;
wss_base_bits = 0x01;
break;
- case 0xf40:
+ case 0x340:
+ chip->wss_base = 0xf40;
wss_base_bits = 0x02;
break;
default:
- snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", wss_base);
+ snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", port);
goto __skip_base;
}
snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30);
@@ -487,7 +510,7 @@ __skip_base:
#endif /* CS4231 || OPTi93X */
#ifndef OPTi93X
- outb(irq_bits << 3 | dma_bits, wss_base);
+ outb(irq_bits << 3 | dma_bits, chip->wss_base);
#else /* OPTi93X */
snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits));
#endif /* OPTi93X */
@@ -729,15 +752,15 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
{
struct pnp_dev *pdev;
int err;
+ struct pnp_dev *devmpu;
+#ifndef OPTi93X
+ struct pnp_dev *devmc;
+#endif
- chip->dev = pnp_request_card_device(card, pid->devs[0].id, NULL);
- if (chip->dev == NULL)
+ pdev = pnp_request_card_device(card, pid->devs[0].id, NULL);
+ if (pdev == NULL)
return -EBUSY;
- chip->devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL);
-
- pdev = chip->dev;
-
err = pnp_activate_dev(pdev);
if (err < 0) {
snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err);
@@ -750,9 +773,24 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
chip->mc_indir_index = pnp_port_start(pdev, 3) + 2;
chip->mc_indir_size = pnp_port_len(pdev, 3) - 2;
#else
- if (pid->driver_data != 0x0924)
- port = pnp_port_start(pdev, 1);
+ devmc = pnp_request_card_device(card, pid->devs[2].id, NULL);
+ if (devmc == NULL)
+ return -EBUSY;
+
+ err = pnp_activate_dev(devmc);
+ if (err < 0) {
+ snd_printk(KERN_ERR "MC pnp configure failure: %d\n", err);
+ return err;
+ }
+
+ port = pnp_port_start(pdev, 1);
fm_port = pnp_port_start(pdev, 2) + 8;
+ /*
+ * The MC(0) is never accessed and card does not
+ * include it in the PnP resource range. OPTI93x include it.
+ */
+ chip->mc_base = pnp_port_start(devmc, 0) - 1;
+ chip->mc_base_size = pnp_port_len(devmc, 0) + 1;
#endif /* OPTi93X */
irq = pnp_irq(pdev, 0);
dma1 = pnp_dma(pdev, 0);
@@ -760,16 +798,16 @@ static int __devinit snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
dma2 = pnp_dma(pdev, 1);
#endif /* CS4231 || OPTi93X */
- pdev = chip->devmpu;
- if (pdev && mpu_port > 0) {
- err = pnp_activate_dev(pdev);
+ devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL);
+
+ if (devmpu && mpu_port > 0) {
+ err = pnp_activate_dev(devmpu);
if (err < 0) {
- snd_printk(KERN_ERR "AUDIO pnp configure failure\n");
+ snd_printk(KERN_ERR "MPU401 pnp configure failure\n");
mpu_port = -1;
- chip->devmpu = NULL;
} else {
- mpu_port = pnp_port_start(pdev, 0);
- mpu_irq = pnp_irq(pdev, 0);
+ mpu_port = pnp_port_start(devmpu, 0);
+ mpu_irq = pnp_irq(devmpu, 0);
}
}
return pid->driver_data;
@@ -824,7 +862,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
if (error)
return error;
- error = snd_wss_create(card, port + 4, -1, irq, dma1, xdma2,
+ error = snd_wss_create(card, chip->wss_base + 4, -1, irq, dma1, xdma2,
#ifdef OPTi93X
WSS_HW_OPTI93X, WSS_HWSHARE_IRQ,
#else
@@ -865,10 +903,11 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
sprintf(card->shortname, "OPTi %s", card->driver);
#if defined(CS4231) || defined(OPTi93X)
sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d&%d",
- card->shortname, pcm->name, port + 4, irq, dma1, xdma2);
+ card->shortname, pcm->name,
+ chip->wss_base + 4, irq, dma1, xdma2);
#else
sprintf(card->longname, "%s, %s at 0x%lx, irq %d, dma %d",
- card->shortname, pcm->name, port + 4, irq, dma1);
+ card->shortname, pcm->name, chip->wss_base + 4, irq, dma1);
#endif /* CS4231 || OPTi93X */
if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT)
@@ -1062,9 +1101,6 @@ static int __devinit snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
snd_card_free(card);
return error;
}
- if (hw <= OPTi9XX_HW_82C930)
- chip->mc_base -= 0x80;
-
error = snd_opti9xx_read_check(chip);
if (error) {
snd_printk(KERN_ERR "OPTI chip not found\n");
diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c
index 8d21a3feda3..8ccbcddf08e 100644
--- a/sound/isa/sb/jazz16.c
+++ b/sound/isa/sb/jazz16.c
@@ -14,6 +14,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/io.h>
+#include <linux/delay.h>
#include <asm/dma.h>
#include <linux/isa.h>
#include <sound/core.h>
diff --git a/sound/oss/coproc.h b/sound/oss/coproc.h
index 7306346e9ac..7bec21bbdd8 100644
--- a/sound/oss/coproc.h
+++ b/sound/oss/coproc.h
@@ -4,7 +4,7 @@
*/
/*
- * Coprocessor access types
+ * Coprocessor access types
*/
#define COPR_CUSTOM 0x0001 /* Custom applications */
#define COPR_MIDI 0x0002 /* MIDI (MPU-401) emulation */
diff --git a/sound/oss/v_midi.h b/sound/oss/v_midi.h
index 1b86cb45c60..08e2185ee81 100644
--- a/sound/oss/v_midi.h
+++ b/sound/oss/v_midi.h
@@ -2,9 +2,9 @@ typedef struct vmidi_devc {
int dev;
/* State variables */
- int opened;
+ int opened;
spinlock_t lock;
-
+
/* MIDI fields */
int my_mididev;
int pair_mididev;
@@ -12,4 +12,3 @@ typedef struct vmidi_devc {
int intr_active;
void (*midi_input_intr) (int dev, unsigned char data);
} vmidi_devc;
-
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index 556cff937be..567348b05b5 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -157,7 +157,7 @@ config SND_HDA_CODEC_INTELHDMI
config SND_HDA_ELD
def_bool y
- depends on SND_HDA_CODEC_INTELHDMI
+ depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI
config SND_HDA_CODEC_CIRRUS
bool "Build Cirrus Logic codec support"
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 315a1c4f899..24bc195b02d 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -3,7 +3,7 @@ snd-hda-intel-objs := hda_intel.o
snd-hda-codec-y := hda_codec.o
snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
-# snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o
+snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o
snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
@@ -18,7 +18,7 @@ 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
-snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o hda_eld.o
+snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o
# common driver
obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 76d3c4c049d..5bd7cf45f3a 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -978,8 +978,9 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
*
* Returns 0 if successful, or a negative error code.
*/
-int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
- struct hda_codec **codecp)
+int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus,
+ unsigned int codec_addr,
+ struct hda_codec **codecp)
{
struct hda_codec *codec;
char component[31];
@@ -1186,7 +1187,7 @@ 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_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))
@@ -1356,7 +1357,8 @@ u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
if (!codec->no_trigger_sense) {
pincap = snd_hda_query_pin_caps(codec, nid);
if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
- snd_hda_codec_read(codec, nid, 0, AC_VERB_SET_PIN_SENSE, 0);
+ snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_SET_PIN_SENSE, 0);
}
return snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_SENSE, 0);
@@ -1372,8 +1374,8 @@ EXPORT_SYMBOL_HDA(snd_hda_pin_sense);
*/
int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
{
- u32 sense = snd_hda_pin_sense(codec, nid);
- return !!(sense & AC_PINSENSE_PRESENCE);
+ u32 sense = snd_hda_pin_sense(codec, nid);
+ return !!(sense & AC_PINSENSE_PRESENCE);
}
EXPORT_SYMBOL_HDA(snd_hda_jack_detect);
@@ -1952,7 +1954,7 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
err = snd_hda_ctl_add(codec, 0, kctl);
if (err < 0)
return err;
-
+
for (s = slaves; *s; s++) {
struct snd_kcontrol *sctl;
int i = 0;
@@ -2439,27 +2441,27 @@ static struct snd_kcontrol_new dig_mixes[] = {
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, CON_MASK),
.info = snd_hda_spdif_mask_info,
.get = snd_hda_spdif_cmask_get,
},
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PRO_MASK),
.info = snd_hda_spdif_mask_info,
.get = snd_hda_spdif_pmask_get,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
.info = snd_hda_spdif_mask_info,
.get = snd_hda_spdif_default_get,
.put = snd_hda_spdif_default_put,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
+ .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, SWITCH),
.info = snd_hda_spdif_out_switch_info,
.get = snd_hda_spdif_out_switch_get,
.put = snd_hda_spdif_out_switch_put,
@@ -2610,7 +2612,7 @@ static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
static struct snd_kcontrol_new dig_in_ctls[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
+ .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH),
.info = snd_hda_spdif_in_switch_info,
.get = snd_hda_spdif_in_switch_get,
.put = snd_hda_spdif_in_switch_put,
@@ -2618,7 +2620,7 @@ static struct snd_kcontrol_new dig_in_ctls[] = {
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
+ .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
.info = snd_hda_spdif_mask_info,
.get = snd_hda_spdif_in_status_get,
},
@@ -2883,7 +2885,7 @@ int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
int err = snd_hda_codec_build_controls(codec);
if (err < 0) {
printk(KERN_ERR "hda_codec: cannot build controls"
- "for #%d (error %d)\n", codec->addr, err);
+ "for #%d (error %d)\n", codec->addr, err);
err = snd_hda_codec_reset(codec);
if (err < 0) {
printk(KERN_ERR
@@ -2979,8 +2981,12 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
val |= channels - 1;
switch (snd_pcm_format_width(format)) {
- case 8: val |= 0x00; break;
- case 16: val |= 0x10; break;
+ case 8:
+ val |= 0x00;
+ break;
+ case 16:
+ val |= 0x10;
+ break;
case 20:
case 24:
case 32:
@@ -3298,7 +3304,8 @@ static int get_empty_pcm_device(struct hda_bus *bus, int type)
if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits))
return audio_idx[type][i];
- snd_printk(KERN_WARNING "Too many %s devices\n", snd_hda_pcm_type_name[type]);
+ snd_printk(KERN_WARNING "Too many %s devices\n",
+ snd_hda_pcm_type_name[type]);
return -EAGAIN;
}
@@ -3336,7 +3343,7 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec)
err = codec->patch_ops.build_pcms(codec);
if (err < 0) {
printk(KERN_ERR "hda_codec: cannot build PCMs"
- "for #%d (error %d)\n", codec->addr, err);
+ "for #%d (error %d)\n", codec->addr, err);
err = snd_hda_codec_reset(codec);
if (err < 0) {
printk(KERN_ERR
@@ -3466,8 +3473,8 @@ EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
/**
* snd_hda_check_board_codec_sid_config - compare the current codec
- subsystem ID with the
- config table
+ subsystem ID with the
+ config table
This is important for Gateway notebooks with SB450 HDA Audio
where the vendor ID of the PCI device is:
@@ -3607,7 +3614,7 @@ void snd_hda_update_power_acct(struct hda_codec *codec)
*
* Increment the power-up counter and power up the hardware really when
* not turned on yet.
- */
+ */
void snd_hda_power_up(struct hda_codec *codec)
{
struct hda_bus *bus = codec->bus;
@@ -3636,7 +3643,7 @@ EXPORT_SYMBOL_HDA(snd_hda_power_up);
*
* Decrement the power-up counter and schedules the power-off work if
* the counter rearches to zero.
- */
+ */
void snd_hda_power_down(struct hda_codec *codec)
{
--codec->power_count;
@@ -3662,7 +3669,7 @@ EXPORT_SYMBOL_HDA(snd_hda_power_down);
*
* This function is supposed to be set or called from the check_power_status
* patch ops.
- */
+ */
int snd_hda_check_amp_list_power(struct hda_codec *codec,
struct hda_loopback_check *check,
hda_nid_t nid)
@@ -3830,7 +3837,7 @@ static void setup_dig_out_stream(struct hda_codec *codec, hda_nid_t nid,
{
/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
- set_dig_out_convert(codec, nid,
+ set_dig_out_convert(codec, nid,
codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff,
-1);
snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
@@ -4089,13 +4096,13 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list)
/*
* Sort an associated group of pins according to their sequence numbers.
*/
-static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
+static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences,
int num_pins)
{
int i, j;
short seq;
hda_nid_t nid;
-
+
for (i = 0; i < num_pins; i++) {
for (j = i + 1; j < num_pins; j++) {
if (sequences[i] > sequences[j]) {
@@ -4123,7 +4130,7 @@ static void sort_pins_by_sequence(hda_nid_t * pins, short * sequences,
* is detected, one of speaker of HP pins is assigned as the primary
* output, i.e. to line_out_pins[0]. So, line_outs is always positive
* if any analog output exists.
- *
+ *
* The analog input pins are assigned to input_pins array.
* The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
* respectively.
@@ -4186,9 +4193,9 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
case AC_JACK_SPEAKER:
seq = get_defcfg_sequence(def_conf);
assoc = get_defcfg_association(def_conf);
- if (! assoc)
+ if (!assoc)
continue;
- if (! assoc_speaker)
+ if (!assoc_speaker)
assoc_speaker = assoc;
else if (assoc_speaker != assoc)
continue;
@@ -4286,7 +4293,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
cfg->speaker_outs);
sort_pins_by_sequence(cfg->hp_pins, sequences_hp,
cfg->hp_outs);
-
+
/* if we have only one mic, make it AUTO_PIN_MIC */
if (!cfg->input_pins[AUTO_PIN_MIC] &&
cfg->input_pins[AUTO_PIN_FRONT_MIC]) {
@@ -4436,7 +4443,7 @@ EXPORT_SYMBOL_HDA(snd_hda_resume);
/**
* snd_array_new - get a new element from the given array
* @array: the array object
- *
+ *
* Get a new element from the given array. If it exceeds the
* pre-allocated array size, re-allocate the array.
*
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index 4228f2fe595..dcd22446cfc 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -331,6 +331,7 @@ int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid)
return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE,
AC_DIPSIZE_ELD_BUF);
}
+EXPORT_SYMBOL_HDA(snd_hdmi_get_eld_size);
int snd_hdmi_get_eld(struct hdmi_eld *eld,
struct hda_codec *codec, hda_nid_t nid)
@@ -366,6 +367,7 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,
kfree(buf);
return ret;
}
+EXPORT_SYMBOL_HDA(snd_hdmi_get_eld);
static void hdmi_show_short_audio_desc(struct cea_sad *a)
{
@@ -404,6 +406,7 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen)
}
buf[j] = '\0'; /* necessary when j == 0 */
}
+EXPORT_SYMBOL_HDA(snd_print_channel_allocation);
void snd_hdmi_show_eld(struct hdmi_eld *e)
{
@@ -422,6 +425,7 @@ void snd_hdmi_show_eld(struct hdmi_eld *e)
for (i = 0; i < e->sad_count; i++)
hdmi_show_short_audio_desc(e->sad + i);
}
+EXPORT_SYMBOL_HDA(snd_hdmi_show_eld);
#ifdef CONFIG_PROC_FS
@@ -580,6 +584,7 @@ int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld,
return 0;
}
+EXPORT_SYMBOL_HDA(snd_hda_eld_proc_new);
void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld)
{
@@ -588,5 +593,6 @@ void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld)
eld->proc_entry = NULL;
}
}
+EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free);
#endif /* CONFIG_PROC_FS */
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index d5c93ad852e..43b7cfb7cff 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -267,7 +267,8 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
#define RIRB_INT_MASK 0x05
/* STATESTS int mask: S3,SD2,SD1,SD0 */
-#define AZX_MAX_CODECS 4
+#define AZX_MAX_CODECS 8
+#define AZX_DEFAULT_CODECS 4
#define STATESTS_INT_MASK ((1 << AZX_MAX_CODECS) - 1)
/* SD_CTL bits */
@@ -1367,6 +1368,7 @@ static void azx_bus_reset(struct hda_bus *bus)
/* number of codec slots for each chipset: 0 = default slots (i.e. 4) */
static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = {
+ [AZX_DRIVER_NVIDIA] = 8,
[AZX_DRIVER_TERA] = 1,
};
@@ -1399,7 +1401,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
codecs = 0;
max_slots = azx_max_codecs[chip->driver_type];
if (!max_slots)
- max_slots = AZX_MAX_CODECS;
+ max_slots = AZX_DEFAULT_CODECS;
/* First try to probe all given codec slots */
for (c = 0; c < max_slots; c++) {
@@ -2263,10 +2265,12 @@ static int azx_dev_free(struct snd_device *device)
static struct snd_pci_quirk position_fix_list[] __devinitdata = {
SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
+ SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB),
SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
+ SND_PCI_QUIRK(0x1565, 0x820f, "Biostar Microtech", POS_FIX_LPIB),
{}
};
@@ -2354,6 +2358,7 @@ static void __devinit check_probe_mask(struct azx *chip, int dev)
static struct snd_pci_quirk msi_black_list[] __devinitdata = {
SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */
+ SND_PCI_QUIRK(0x1849, 0x0888, "ASRock", 0), /* Athlon64 X2 + nvidia */
{}
};
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
new file mode 100644
index 00000000000..2c2bafbf025
--- /dev/null
+++ b/sound/pci/hda/patch_hdmi.c
@@ -0,0 +1,849 @@
+/*
+ *
+ * patch_hdmi.c - routines for HDMI/DisplayPort codecs
+ *
+ * Copyright(c) 2008-2010 Intel Corporation. All rights reserved.
+ *
+ * Authors:
+ * Wu Fengguang <wfg@linux.intel.com>
+ *
+ * Maintained by:
+ * Wu Fengguang <wfg@linux.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.
+ *
+ * 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.
+ */
+
+
+struct hdmi_spec {
+ int num_cvts;
+ int num_pins;
+ hda_nid_t cvt[MAX_HDMI_CVTS+1]; /* audio sources */
+ hda_nid_t pin[MAX_HDMI_PINS+1]; /* audio sinks */
+
+ /*
+ * source connection for each pin
+ */
+ hda_nid_t pin_cvt[MAX_HDMI_PINS+1];
+
+ /*
+ * HDMI sink attached to each pin
+ */
+ struct hdmi_eld sink_eld[MAX_HDMI_PINS];
+
+ /*
+ * export one pcm per pipe
+ */
+ struct hda_pcm pcm_rec[MAX_HDMI_CVTS];
+
+ /*
+ * nvhdmi specific
+ */
+ struct hda_multi_out multiout;
+ unsigned int codec_type;
+};
+
+
+struct hdmi_audio_infoframe {
+ u8 type; /* 0x84 */
+ u8 ver; /* 0x01 */
+ u8 len; /* 0x0a */
+
+ u8 checksum; /* PB0 */
+ u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */
+ u8 SS01_SF24;
+ u8 CXT04;
+ u8 CA;
+ u8 LFEPBL01_LSV36_DM_INH7;
+ u8 reserved[5]; /* PB6 - PB10 */
+};
+
+/*
+ * CEA speaker placement:
+ *
+ * FLH FCH FRH
+ * FLW FL FLC FC FRC FR FRW
+ *
+ * LFE
+ * TC
+ *
+ * RL RLC RC RRC RR
+ *
+ * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
+ * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
+ */
+enum cea_speaker_placement {
+ FL = (1 << 0), /* Front Left */
+ FC = (1 << 1), /* Front Center */
+ FR = (1 << 2), /* Front Right */
+ FLC = (1 << 3), /* Front Left Center */
+ FRC = (1 << 4), /* Front Right Center */
+ RL = (1 << 5), /* Rear Left */
+ RC = (1 << 6), /* Rear Center */
+ RR = (1 << 7), /* Rear Right */
+ RLC = (1 << 8), /* Rear Left Center */
+ RRC = (1 << 9), /* Rear Right Center */
+ LFE = (1 << 10), /* Low Frequency Effect */
+ FLW = (1 << 11), /* Front Left Wide */
+ FRW = (1 << 12), /* Front Right Wide */
+ FLH = (1 << 13), /* Front Left High */
+ FCH = (1 << 14), /* Front Center High */
+ FRH = (1 << 15), /* Front Right High */
+ TC = (1 << 16), /* Top Center */
+};
+
+/*
+ * ELD SA bits in the CEA Speaker Allocation data block
+ */
+static int eld_speaker_allocation_bits[] = {
+ [0] = FL | FR,
+ [1] = LFE,
+ [2] = FC,
+ [3] = RL | RR,
+ [4] = RC,
+ [5] = FLC | FRC,
+ [6] = RLC | RRC,
+ /* the following are not defined in ELD yet */
+ [7] = FLW | FRW,
+ [8] = FLH | FRH,
+ [9] = TC,
+ [10] = FCH,
+};
+
+struct cea_channel_speaker_allocation {
+ int ca_index;
+ int speakers[8];
+
+ /* derived values, just for convenience */
+ int channels;
+ int spk_mask;
+};
+
+/*
+ * ALSA sequence is:
+ *
+ * surround40 surround41 surround50 surround51 surround71
+ * ch0 front left = = = =
+ * ch1 front right = = = =
+ * ch2 rear left = = = =
+ * ch3 rear right = = = =
+ * ch4 LFE center center center
+ * ch5 LFE LFE
+ * ch6 side left
+ * ch7 side right
+ *
+ * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
+ */
+static int hdmi_channel_mapping[0x32][8] = {
+ /* stereo */
+ [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
+ /* 2.1 */
+ [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
+ /* Dolby Surround */
+ [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
+ /* surround40 */
+ [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
+ /* 4ch */
+ [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
+ /* surround41 */
+ [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
+ /* surround50 */
+ [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
+ /* surround51 */
+ [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
+ /* 7.1 */
+ [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 },
+};
+
+/*
+ * This is an ordered list!
+ *
+ * The preceding ones have better chances to be selected by
+ * hdmi_setup_channel_allocation().
+ */
+static struct cea_channel_speaker_allocation channel_allocations[] = {
+/* channel: 7 6 5 4 3 2 1 0 */
+{ .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } },
+ /* 2.1 */
+{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } },
+ /* Dolby Surround */
+{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } },
+ /* surround40 */
+{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } },
+ /* surround41 */
+{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } },
+ /* surround50 */
+{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } },
+ /* surround51 */
+{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } },
+ /* 6.1 */
+{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } },
+ /* surround71 */
+{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } },
+
+{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } },
+{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } },
+{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } },
+{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } },
+{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } },
+{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } },
+{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } },
+{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } },
+{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } },
+{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } },
+{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } },
+{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } },
+{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } },
+{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } },
+{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } },
+{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } },
+{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } },
+{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } },
+{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } },
+{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } },
+{ .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } },
+{ .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } },
+{ .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } },
+{ .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } },
+{ .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } },
+{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } },
+};
+
+
+/*
+ * HDMI routines
+ */
+
+static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
+{
+ int i;
+
+ for (i = 0; nids[i]; i++)
+ if (nids[i] == nid)
+ return i;
+
+ snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
+ return -EINVAL;
+}
+
+static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
+ struct hdmi_eld *eld)
+{
+ if (!snd_hdmi_get_eld(eld, codec, pin_nid))
+ snd_hdmi_show_eld(eld);
+}
+
+#ifdef BE_PARANOID
+static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
+ int *packet_index, int *byte_index)
+{
+ int val;
+
+ val = snd_hda_codec_read(codec, pin_nid, 0,
+ AC_VERB_GET_HDMI_DIP_INDEX, 0);
+
+ *packet_index = val >> 5;
+ *byte_index = val & 0x1f;
+}
+#endif
+
+static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
+ int packet_index, int byte_index)
+{
+ int val;
+
+ val = (packet_index << 5) | (byte_index & 0x1f);
+
+ snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
+}
+
+static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
+ unsigned char val)
+{
+ snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
+}
+
+static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+ /* Unmute */
+ if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
+ snd_hda_codec_write(codec, pin_nid, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+ /* Enable pin out */
+ snd_hda_codec_write(codec, pin_nid, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+}
+
+static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
+{
+ return 1 + snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_CVT_CHAN_COUNT, 0);
+}
+
+static void hdmi_set_channel_count(struct hda_codec *codec,
+ hda_nid_t nid, int chs)
+{
+ if (chs != hdmi_get_channel_count(codec, nid))
+ snd_hda_codec_write(codec, nid, 0,
+ AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
+}
+
+
+/*
+ * Channel mapping routines
+ */
+
+/*
+ * Compute derived values in channel_allocations[].
+ */
+static void init_channel_allocations(void)
+{
+ int i, j;
+ struct cea_channel_speaker_allocation *p;
+
+ for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+ p = channel_allocations + i;
+ p->channels = 0;
+ p->spk_mask = 0;
+ for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
+ if (p->speakers[j]) {
+ p->channels++;
+ p->spk_mask |= p->speakers[j];
+ }
+ }
+}
+
+/*
+ * The transformation takes two steps:
+ *
+ * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
+ * spk_mask => (channel_allocations[]) => ai->CA
+ *
+ * TODO: it could select the wrong CA from multiple candidates.
+*/
+static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
+ struct hdmi_audio_infoframe *ai)
+{
+ struct hdmi_spec *spec = codec->spec;
+ struct hdmi_eld *eld;
+ int i;
+ int spk_mask = 0;
+ int channels = 1 + (ai->CC02_CT47 & 0x7);
+ char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
+
+ /*
+ * CA defaults to 0 for basic stereo audio
+ */
+ if (channels <= 2)
+ return 0;
+
+ i = hda_node_index(spec->pin_cvt, nid);
+ if (i < 0)
+ return 0;
+ eld = &spec->sink_eld[i];
+
+ /*
+ * HDMI sink's ELD info cannot always be retrieved for now, e.g.
+ * in console or for audio devices. Assume the highest speakers
+ * configuration, to _not_ prohibit multi-channel audio playback.
+ */
+ if (!eld->spk_alloc)
+ eld->spk_alloc = 0xffff;
+
+ /*
+ * expand ELD's speaker allocation mask
+ *
+ * ELD tells the speaker mask in a compact(paired) form,
+ * expand ELD's notions to match the ones used by Audio InfoFrame.
+ */
+ for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
+ if (eld->spk_alloc & (1 << i))
+ spk_mask |= eld_speaker_allocation_bits[i];
+ }
+
+ /* search for the first working match in the CA table */
+ for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
+ if (channels == channel_allocations[i].channels &&
+ (spk_mask & channel_allocations[i].spk_mask) ==
+ channel_allocations[i].spk_mask) {
+ ai->CA = channel_allocations[i].ca_index;
+ break;
+ }
+ }
+
+ snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
+ snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n",
+ ai->CA, channels, buf);
+
+ return ai->CA;
+}
+
+static void hdmi_debug_channel_mapping(struct hda_codec *codec,
+ hda_nid_t pin_nid)
+{
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+ int i;
+ int slot;
+
+ for (i = 0; i < 8; i++) {
+ slot = snd_hda_codec_read(codec, pin_nid, 0,
+ AC_VERB_GET_HDMI_CHAN_SLOT, i);
+ printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
+ slot >> 4, slot & 0xf);
+ }
+#endif
+}
+
+
+static void hdmi_setup_channel_mapping(struct hda_codec *codec,
+ hda_nid_t pin_nid,
+ struct hdmi_audio_infoframe *ai)
+{
+ int i;
+ int ca = ai->CA;
+ int err;
+
+ if (hdmi_channel_mapping[ca][1] == 0) {
+ for (i = 0; i < channel_allocations[ca].channels; i++)
+ hdmi_channel_mapping[ca][i] = i | (i << 4);
+ for (; i < 8; i++)
+ hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
+ }
+
+ for (i = 0; i < 8; i++) {
+ err = snd_hda_codec_write(codec, pin_nid, 0,
+ AC_VERB_SET_HDMI_CHAN_SLOT,
+ hdmi_channel_mapping[ca][i]);
+ if (err) {
+ snd_printdd(KERN_NOTICE
+ "HDMI: channel mapping failed\n");
+ break;
+ }
+ }
+
+ hdmi_debug_channel_mapping(codec, pin_nid);
+}
+
+
+/*
+ * Audio InfoFrame routines
+ */
+
+/*
+ * Enable Audio InfoFrame Transmission
+ */
+static void hdmi_start_infoframe_trans(struct hda_codec *codec,
+ hda_nid_t pin_nid)
+{
+ hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+ snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
+ AC_DIPXMIT_BEST);
+}
+
+/*
+ * Disable Audio InfoFrame Transmission
+ */
+static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
+ hda_nid_t pin_nid)
+{
+ hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+ snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
+ AC_DIPXMIT_DISABLE);
+}
+
+static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+ int i;
+ int size;
+
+ size = snd_hdmi_get_eld_size(codec, pin_nid);
+ printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
+
+ for (i = 0; i < 8; i++) {
+ size = snd_hda_codec_read(codec, pin_nid, 0,
+ AC_VERB_GET_HDMI_DIP_SIZE, i);
+ printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
+ }
+#endif
+}
+
+static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+#ifdef BE_PARANOID
+ int i, j;
+ int size;
+ int pi, bi;
+ for (i = 0; i < 8; i++) {
+ size = snd_hda_codec_read(codec, pin_nid, 0,
+ AC_VERB_GET_HDMI_DIP_SIZE, i);
+ if (size == 0)
+ continue;
+
+ hdmi_set_dip_index(codec, pin_nid, i, 0x0);
+ for (j = 1; j < 1000; j++) {
+ hdmi_write_dip_byte(codec, pin_nid, 0x0);
+ hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
+ if (pi != i)
+ snd_printd(KERN_INFO "dip index %d: %d != %d\n",
+ bi, pi, i);
+ if (bi == 0) /* byte index wrapped around */
+ break;
+ }
+ snd_printd(KERN_INFO
+ "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
+ i, size, j);
+ }
+#endif
+}
+
+static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
+{
+ u8 *bytes = (u8 *)ai;
+ u8 sum = 0;
+ int i;
+
+ ai->checksum = 0;
+
+ for (i = 0; i < sizeof(*ai); i++)
+ sum += bytes[i];
+
+ ai->checksum = -sum;
+}
+
+static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
+ hda_nid_t pin_nid,
+ struct hdmi_audio_infoframe *ai)
+{
+ u8 *bytes = (u8 *)ai;
+ int i;
+
+ hdmi_debug_dip_size(codec, pin_nid);
+ hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
+
+ hdmi_checksum_audio_infoframe(ai);
+
+ hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+ for (i = 0; i < sizeof(*ai); i++)
+ hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
+}
+
+static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
+ struct hdmi_audio_infoframe *ai)
+{
+ u8 *bytes = (u8 *)ai;
+ u8 val;
+ int i;
+
+ if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
+ != AC_DIPXMIT_BEST)
+ return false;
+
+ hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
+ for (i = 0; i < sizeof(*ai); i++) {
+ val = snd_hda_codec_read(codec, pin_nid, 0,
+ AC_VERB_GET_HDMI_DIP_DATA, 0);
+ if (val != bytes[i])
+ return false;
+ }
+
+ return true;
+}
+
+static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
+ struct snd_pcm_substream *substream)
+{
+ struct hdmi_spec *spec = codec->spec;
+ hda_nid_t pin_nid;
+ int i;
+ struct hdmi_audio_infoframe ai = {
+ .type = 0x84,
+ .ver = 0x01,
+ .len = 0x0a,
+ .CC02_CT47 = substream->runtime->channels - 1,
+ };
+
+ hdmi_setup_channel_allocation(codec, nid, &ai);
+
+ for (i = 0; i < spec->num_pins; i++) {
+ if (spec->pin_cvt[i] != nid)
+ continue;
+ if (!spec->sink_eld[i].monitor_present)
+ continue;
+
+ pin_nid = spec->pin[i];
+ if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
+ snd_printdd("hdmi_setup_audio_infoframe: "
+ "cvt=%d pin=%d channels=%d\n",
+ nid, pin_nid,
+ substream->runtime->channels);
+ hdmi_setup_channel_mapping(codec, pin_nid, &ai);
+ hdmi_stop_infoframe_trans(codec, pin_nid);
+ hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
+ hdmi_start_infoframe_trans(codec, pin_nid);
+ }
+ }
+}
+
+
+/*
+ * Unsolicited events
+ */
+
+static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
+ struct hdmi_spec *spec = codec->spec;
+ int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+ int pind = !!(res & AC_UNSOL_RES_PD);
+ int eldv = !!(res & AC_UNSOL_RES_ELDV);
+ int index;
+
+ printk(KERN_INFO
+ "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
+ tag, pind, eldv);
+
+ index = hda_node_index(spec->pin, tag);
+ if (index < 0)
+ return;
+
+ spec->sink_eld[index].monitor_present = pind;
+ spec->sink_eld[index].eld_valid = eldv;
+
+ if (pind && eldv) {
+ hdmi_get_show_eld(codec, spec->pin[index],
+ &spec->sink_eld[index]);
+ /* TODO: do real things about ELD */
+ }
+}
+
+static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
+{
+ int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+ int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
+ int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
+ int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
+
+ printk(KERN_INFO
+ "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
+ tag,
+ subtag,
+ cp_state,
+ cp_ready);
+
+ /* TODO */
+ if (cp_state)
+ ;
+ if (cp_ready)
+ ;
+}
+
+
+static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+ struct hdmi_spec *spec = codec->spec;
+ int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+ int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
+
+ if (hda_node_index(spec->pin, tag) < 0) {
+ snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
+ return;
+ }
+
+ if (subtag == 0)
+ hdmi_intrinsic_event(codec, res);
+ else
+ hdmi_non_intrinsic_event(codec, res);
+}
+
+/*
+ * Callbacks
+ */
+
+static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
+ u32 stream_tag, int format)
+{
+ int tag;
+ int fmt;
+
+ tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
+ fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
+
+ snd_printdd("hdmi_setup_stream: "
+ "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
+ nid,
+ tag == stream_tag ? "" : "new-",
+ stream_tag,
+ fmt == format ? "" : "new-",
+ format);
+
+ if (tag != stream_tag)
+ snd_hda_codec_write(codec, nid, 0,
+ AC_VERB_SET_CHANNEL_STREAMID,
+ stream_tag << 4);
+ if (fmt != format)
+ snd_hda_codec_write(codec, nid, 0,
+ AC_VERB_SET_STREAM_FORMAT, format);
+}
+
+/*
+ * HDA/HDMI auto parsing
+ */
+
+static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+ struct hdmi_spec *spec = codec->spec;
+ hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
+ int conn_len, curr;
+ int index;
+
+ if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
+ snd_printk(KERN_WARNING
+ "HDMI: pin %d wcaps %#x "
+ "does not support connection list\n",
+ pin_nid, get_wcaps(codec, pin_nid));
+ return -EINVAL;
+ }
+
+ conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
+ HDA_MAX_CONNECTIONS);
+ if (conn_len > 1)
+ curr = snd_hda_codec_read(codec, pin_nid, 0,
+ AC_VERB_GET_CONNECT_SEL, 0);
+ else
+ curr = 0;
+
+ index = hda_node_index(spec->pin, pin_nid);
+ if (index < 0)
+ return -EINVAL;
+
+ spec->pin_cvt[index] = conn_list[curr];
+
+ return 0;
+}
+
+static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
+ struct hdmi_eld *eld)
+{
+ int present = snd_hda_pin_sense(codec, pin_nid);
+
+ eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE);
+ eld->eld_valid = !!(present & AC_PINSENSE_ELDV);
+
+ if (present & AC_PINSENSE_ELDV)
+ hdmi_get_show_eld(codec, pin_nid, eld);
+}
+
+static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
+{
+ struct hdmi_spec *spec = codec->spec;
+
+ if (spec->num_pins >= MAX_HDMI_PINS) {
+ snd_printk(KERN_WARNING
+ "HDMI: no space for pin %d\n", pin_nid);
+ return -EINVAL;
+ }
+
+ hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
+
+ spec->pin[spec->num_pins] = pin_nid;
+ spec->num_pins++;
+
+ /*
+ * It is assumed that converter nodes come first in the node list and
+ * hence have been registered and usable now.
+ */
+ return hdmi_read_pin_conn(codec, pin_nid);
+}
+
+static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
+{
+ struct hdmi_spec *spec = codec->spec;
+
+ if (spec->num_cvts >= MAX_HDMI_CVTS) {
+ snd_printk(KERN_WARNING
+ "HDMI: no space for converter %d\n", nid);
+ return -EINVAL;
+ }
+
+ spec->cvt[spec->num_cvts] = nid;
+ spec->num_cvts++;
+
+ return 0;
+}
+
+static int hdmi_parse_codec(struct hda_codec *codec)
+{
+ hda_nid_t nid;
+ int i, nodes;
+
+ nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
+ if (!nid || nodes < 0) {
+ snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < nodes; i++, nid++) {
+ unsigned int caps;
+ unsigned int type;
+
+ caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
+ type = get_wcaps_type(caps);
+
+ if (!(caps & AC_WCAP_DIGITAL))
+ continue;
+
+ switch (type) {
+ case AC_WID_AUD_OUT:
+ if (hdmi_add_cvt(codec, nid) < 0)
+ return -EINVAL;
+ break;
+ case AC_WID_PIN:
+ caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+ if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
+ continue;
+ if (hdmi_add_pin(codec, nid) < 0)
+ return -EINVAL;
+ break;
+ }
+ }
+
+ /*
+ * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
+ * can be lost and presence sense verb will become inaccurate if the
+ * HDA link is powered off at hot plug or hw initialization time.
+ */
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+ if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
+ AC_PWRST_EPSS))
+ codec->bus->power_keep_link_on = 1;
+#endif
+
+ return 0;
+}
+
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c
index 918f40378d5..88d035104cc 100644
--- a/sound/pci/hda/patch_intelhdmi.c
+++ b/sound/pci/hda/patch_intelhdmi.c
@@ -40,815 +40,20 @@
*
* The HDA correspondence of pipes/ports are converter/pin nodes.
*/
-#define INTEL_HDMI_CVTS 2
-#define INTEL_HDMI_PINS 3
+#define MAX_HDMI_CVTS 2
+#define MAX_HDMI_PINS 3
-static char *intel_hdmi_pcm_names[INTEL_HDMI_CVTS] = {
+#include "patch_hdmi.c"
+
+static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = {
"INTEL HDMI 0",
"INTEL HDMI 1",
};
-struct intel_hdmi_spec {
- int num_cvts;
- int num_pins;
- hda_nid_t cvt[INTEL_HDMI_CVTS+1]; /* audio sources */
- hda_nid_t pin[INTEL_HDMI_PINS+1]; /* audio sinks */
-
- /*
- * source connection for each pin
- */
- hda_nid_t pin_cvt[INTEL_HDMI_PINS+1];
-
- /*
- * HDMI sink attached to each pin
- */
- struct hdmi_eld sink_eld[INTEL_HDMI_PINS];
-
- /*
- * export one pcm per pipe
- */
- struct hda_pcm pcm_rec[INTEL_HDMI_CVTS];
-};
-
-struct hdmi_audio_infoframe {
- u8 type; /* 0x84 */
- u8 ver; /* 0x01 */
- u8 len; /* 0x0a */
-
- u8 checksum; /* PB0 */
- u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */
- u8 SS01_SF24;
- u8 CXT04;
- u8 CA;
- u8 LFEPBL01_LSV36_DM_INH7;
- u8 reserved[5]; /* PB6 - PB10 */
-};
-
-/*
- * CEA speaker placement:
- *
- * FLH FCH FRH
- * FLW FL FLC FC FRC FR FRW
- *
- * LFE
- * TC
- *
- * RL RLC RC RRC RR
- *
- * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
- * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
- */
-enum cea_speaker_placement {
- FL = (1 << 0), /* Front Left */
- FC = (1 << 1), /* Front Center */
- FR = (1 << 2), /* Front Right */
- FLC = (1 << 3), /* Front Left Center */
- FRC = (1 << 4), /* Front Right Center */
- RL = (1 << 5), /* Rear Left */
- RC = (1 << 6), /* Rear Center */
- RR = (1 << 7), /* Rear Right */
- RLC = (1 << 8), /* Rear Left Center */
- RRC = (1 << 9), /* Rear Right Center */
- LFE = (1 << 10), /* Low Frequency Effect */
- FLW = (1 << 11), /* Front Left Wide */
- FRW = (1 << 12), /* Front Right Wide */
- FLH = (1 << 13), /* Front Left High */
- FCH = (1 << 14), /* Front Center High */
- FRH = (1 << 15), /* Front Right High */
- TC = (1 << 16), /* Top Center */
-};
-
-/*
- * ELD SA bits in the CEA Speaker Allocation data block
- */
-static int eld_speaker_allocation_bits[] = {
- [0] = FL | FR,
- [1] = LFE,
- [2] = FC,
- [3] = RL | RR,
- [4] = RC,
- [5] = FLC | FRC,
- [6] = RLC | RRC,
- /* the following are not defined in ELD yet */
- [7] = FLW | FRW,
- [8] = FLH | FRH,
- [9] = TC,
- [10] = FCH,
-};
-
-struct cea_channel_speaker_allocation {
- int ca_index;
- int speakers[8];
-
- /* derived values, just for convenience */
- int channels;
- int spk_mask;
-};
-
-/*
- * ALSA sequence is:
- *
- * surround40 surround41 surround50 surround51 surround71
- * ch0 front left = = = =
- * ch1 front right = = = =
- * ch2 rear left = = = =
- * ch3 rear right = = = =
- * ch4 LFE center center center
- * ch5 LFE LFE
- * ch6 side left
- * ch7 side right
- *
- * surround71 = {FL, FR, RLC, RRC, FC, LFE, RL, RR}
- */
-static int hdmi_channel_mapping[0x32][8] = {
- /* stereo */
- [0x00] = { 0x00, 0x11, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
- /* 2.1 */
- [0x01] = { 0x00, 0x11, 0x22, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7 },
- /* Dolby Surround */
- [0x02] = { 0x00, 0x11, 0x23, 0xf2, 0xf4, 0xf5, 0xf6, 0xf7 },
- /* surround40 */
- [0x08] = { 0x00, 0x11, 0x24, 0x35, 0xf3, 0xf2, 0xf6, 0xf7 },
- /* 4ch */
- [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 },
- /* surround41 */
- [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 },
- /* surround50 */
- [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 },
- /* surround51 */
- [0x0b] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0x52, 0xf6, 0xf7 },
- /* 7.1 */
- [0x13] = { 0x00, 0x11, 0x26, 0x37, 0x43, 0x52, 0x64, 0x75 },
-};
-
-/*
- * This is an ordered list!
- *
- * The preceding ones have better chances to be selected by
- * hdmi_setup_channel_allocation().
- */
-static struct cea_channel_speaker_allocation channel_allocations[] = {
-/* channel: 7 6 5 4 3 2 1 0 */
-{ .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } },
- /* 2.1 */
-{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } },
- /* Dolby Surround */
-{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } },
- /* surround40 */
-{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } },
- /* surround41 */
-{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } },
- /* surround50 */
-{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } },
- /* surround51 */
-{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } },
- /* 6.1 */
-{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } },
- /* surround71 */
-{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } },
-
-{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } },
-{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } },
-{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } },
-{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } },
-{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } },
-{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } },
-{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } },
-{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } },
-{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } },
-{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } },
-{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } },
-{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } },
-{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } },
-{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } },
-{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } },
-{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } },
-{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } },
-{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } },
-{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } },
-{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } },
-{ .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } },
-{ .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } },
-{ .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } },
-{ .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } },
-};
-
-/*
- * HDA/HDMI auto parsing
- */
-
-static int hda_node_index(hda_nid_t *nids, hda_nid_t nid)
-{
- int i;
-
- for (i = 0; nids[i]; i++)
- if (nids[i] == nid)
- return i;
-
- snd_printk(KERN_WARNING "HDMI: nid %d not registered\n", nid);
- return -EINVAL;
-}
-
-static int intel_hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid)
-{
- struct intel_hdmi_spec *spec = codec->spec;
- hda_nid_t conn_list[HDA_MAX_CONNECTIONS];
- int conn_len, curr;
- int index;
-
- if (!(get_wcaps(codec, pin_nid) & AC_WCAP_CONN_LIST)) {
- snd_printk(KERN_WARNING
- "HDMI: pin %d wcaps %#x "
- "does not support connection list\n",
- pin_nid, get_wcaps(codec, pin_nid));
- return -EINVAL;
- }
-
- conn_len = snd_hda_get_connections(codec, pin_nid, conn_list,
- HDA_MAX_CONNECTIONS);
- if (conn_len > 1)
- curr = snd_hda_codec_read(codec, pin_nid, 0,
- AC_VERB_GET_CONNECT_SEL, 0);
- else
- curr = 0;
-
- index = hda_node_index(spec->pin, pin_nid);
- if (index < 0)
- return -EINVAL;
-
- spec->pin_cvt[index] = conn_list[curr];
-
- return 0;
-}
-
-static void hdmi_get_show_eld(struct hda_codec *codec, hda_nid_t pin_nid,
- struct hdmi_eld *eld)
-{
- if (!snd_hdmi_get_eld(eld, codec, pin_nid))
- snd_hdmi_show_eld(eld);
-}
-
-static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
- struct hdmi_eld *eld)
-{
- int present = snd_hda_pin_sense(codec, pin_nid);
-
- eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE);
- eld->eld_valid = !!(present & AC_PINSENSE_ELDV);
-
- if (present & AC_PINSENSE_ELDV)
- hdmi_get_show_eld(codec, pin_nid, eld);
-}
-
-static int intel_hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
-{
- struct intel_hdmi_spec *spec = codec->spec;
-
- if (spec->num_pins >= INTEL_HDMI_PINS) {
- snd_printk(KERN_WARNING
- "HDMI: no space for pin %d \n", pin_nid);
- return -EINVAL;
- }
-
- hdmi_present_sense(codec, pin_nid, &spec->sink_eld[spec->num_pins]);
-
- spec->pin[spec->num_pins] = pin_nid;
- spec->num_pins++;
-
- /*
- * It is assumed that converter nodes come first in the node list and
- * hence have been registered and usable now.
- */
- return intel_hdmi_read_pin_conn(codec, pin_nid);
-}
-
-static int intel_hdmi_add_cvt(struct hda_codec *codec, hda_nid_t nid)
-{
- struct intel_hdmi_spec *spec = codec->spec;
-
- if (spec->num_cvts >= INTEL_HDMI_CVTS) {
- snd_printk(KERN_WARNING
- "HDMI: no space for converter %d \n", nid);
- return -EINVAL;
- }
-
- spec->cvt[spec->num_cvts] = nid;
- spec->num_cvts++;
-
- return 0;
-}
-
-static int intel_hdmi_parse_codec(struct hda_codec *codec)
-{
- hda_nid_t nid;
- int i, nodes;
-
- nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
- if (!nid || nodes < 0) {
- snd_printk(KERN_WARNING "HDMI: failed to get afg sub nodes\n");
- return -EINVAL;
- }
-
- for (i = 0; i < nodes; i++, nid++) {
- unsigned int caps;
- unsigned int type;
-
- caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
- type = get_wcaps_type(caps);
-
- if (!(caps & AC_WCAP_DIGITAL))
- continue;
-
- switch (type) {
- case AC_WID_AUD_OUT:
- if (intel_hdmi_add_cvt(codec, nid) < 0)
- return -EINVAL;
- break;
- case AC_WID_PIN:
- caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
- if (!(caps & (AC_PINCAP_HDMI | AC_PINCAP_DP)))
- continue;
- if (intel_hdmi_add_pin(codec, nid) < 0)
- return -EINVAL;
- break;
- }
- }
-
- /*
- * G45/IbexPeak don't support EPSS: the unsolicited pin hot plug event
- * can be lost and presence sense verb will become inaccurate if the
- * HDA link is powered off at hot plug or hw initialization time.
- */
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) &
- AC_PWRST_EPSS))
- codec->bus->power_keep_link_on = 1;
-#endif
-
- return 0;
-}
-
-/*
- * HDMI routines
- */
-
-#ifdef BE_PARANOID
-static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
- int *packet_index, int *byte_index)
-{
- int val;
-
- val = snd_hda_codec_read(codec, pin_nid, 0,
- AC_VERB_GET_HDMI_DIP_INDEX, 0);
-
- *packet_index = val >> 5;
- *byte_index = val & 0x1f;
-}
-#endif
-
-static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
- int packet_index, int byte_index)
-{
- int val;
-
- val = (packet_index << 5) | (byte_index & 0x1f);
-
- snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
-}
-
-static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t pin_nid,
- unsigned char val)
-{
- snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
-}
-
-static void hdmi_enable_output(struct hda_codec *codec, hda_nid_t pin_nid)
-{
- /* Unmute */
- if (get_wcaps(codec, pin_nid) & AC_WCAP_OUT_AMP)
- snd_hda_codec_write(codec, pin_nid, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
- /* Enable pin out */
- snd_hda_codec_write(codec, pin_nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
-}
-
-/*
- * Enable Audio InfoFrame Transmission
- */
-static void hdmi_start_infoframe_trans(struct hda_codec *codec,
- hda_nid_t pin_nid)
-{
- hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
- snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
- AC_DIPXMIT_BEST);
-}
-
-/*
- * Disable Audio InfoFrame Transmission
- */
-static void hdmi_stop_infoframe_trans(struct hda_codec *codec,
- hda_nid_t pin_nid)
-{
- hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
- snd_hda_codec_write(codec, pin_nid, 0, AC_VERB_SET_HDMI_DIP_XMIT,
- AC_DIPXMIT_DISABLE);
-}
-
-static int hdmi_get_channel_count(struct hda_codec *codec, hda_nid_t nid)
-{
- return 1 + snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_CVT_CHAN_COUNT, 0);
-}
-
-static void hdmi_set_channel_count(struct hda_codec *codec,
- hda_nid_t nid, int chs)
-{
- if (chs != hdmi_get_channel_count(codec, nid))
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
-}
-
-static void hdmi_debug_channel_mapping(struct hda_codec *codec,
- hda_nid_t pin_nid)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- int i;
- int slot;
-
- for (i = 0; i < 8; i++) {
- slot = snd_hda_codec_read(codec, pin_nid, 0,
- AC_VERB_GET_HDMI_CHAN_SLOT, i);
- printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
- slot >> 4, slot & 0xf);
- }
-#endif
-}
-
-
-/*
- * Audio InfoFrame routines
- */
-
-static void hdmi_debug_dip_size(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- int i;
- int size;
-
- size = snd_hdmi_get_eld_size(codec, pin_nid);
- printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
-
- for (i = 0; i < 8; i++) {
- size = snd_hda_codec_read(codec, pin_nid, 0,
- AC_VERB_GET_HDMI_DIP_SIZE, i);
- printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
- }
-#endif
-}
-
-static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid)
-{
-#ifdef BE_PARANOID
- int i, j;
- int size;
- int pi, bi;
- for (i = 0; i < 8; i++) {
- size = snd_hda_codec_read(codec, pin_nid, 0,
- AC_VERB_GET_HDMI_DIP_SIZE, i);
- if (size == 0)
- continue;
-
- hdmi_set_dip_index(codec, pin_nid, i, 0x0);
- for (j = 1; j < 1000; j++) {
- hdmi_write_dip_byte(codec, pin_nid, 0x0);
- hdmi_get_dip_index(codec, pin_nid, &pi, &bi);
- if (pi != i)
- snd_printd(KERN_INFO "dip index %d: %d != %d\n",
- bi, pi, i);
- if (bi == 0) /* byte index wrapped around */
- break;
- }
- snd_printd(KERN_INFO
- "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
- i, size, j);
- }
-#endif
-}
-
-static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai)
-{
- u8 *bytes = (u8 *)ai;
- u8 sum = 0;
- int i;
-
- ai->checksum = 0;
-
- for (i = 0; i < sizeof(*ai); i++)
- sum += bytes[i];
-
- ai->checksum = - sum;
-}
-
-static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
- hda_nid_t pin_nid,
- struct hdmi_audio_infoframe *ai)
-{
- u8 *bytes = (u8 *)ai;
- int i;
-
- hdmi_debug_dip_size(codec, pin_nid);
- hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */
-
- hdmi_checksum_audio_infoframe(ai);
-
- hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
- for (i = 0; i < sizeof(*ai); i++)
- hdmi_write_dip_byte(codec, pin_nid, bytes[i]);
-}
-
-/*
- * Compute derived values in channel_allocations[].
- */
-static void init_channel_allocations(void)
-{
- int i, j;
- struct cea_channel_speaker_allocation *p;
-
- for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
- p = channel_allocations + i;
- p->channels = 0;
- p->spk_mask = 0;
- for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
- if (p->speakers[j]) {
- p->channels++;
- p->spk_mask |= p->speakers[j];
- }
- }
-}
-
-/*
- * The transformation takes two steps:
- *
- * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
- * spk_mask => (channel_allocations[]) => ai->CA
- *
- * TODO: it could select the wrong CA from multiple candidates.
-*/
-static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid,
- struct hdmi_audio_infoframe *ai)
-{
- struct intel_hdmi_spec *spec = codec->spec;
- struct hdmi_eld *eld;
- int i;
- int spk_mask = 0;
- int channels = 1 + (ai->CC02_CT47 & 0x7);
- char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
-
- /*
- * CA defaults to 0 for basic stereo audio
- */
- if (channels <= 2)
- return 0;
-
- i = hda_node_index(spec->pin_cvt, nid);
- if (i < 0)
- return 0;
- eld = &spec->sink_eld[i];
-
- /*
- * HDMI sink's ELD info cannot always be retrieved for now, e.g.
- * in console or for audio devices. Assume the highest speakers
- * configuration, to _not_ prohibit multi-channel audio playback.
- */
- if (!eld->spk_alloc)
- eld->spk_alloc = 0xffff;
-
- /*
- * expand ELD's speaker allocation mask
- *
- * ELD tells the speaker mask in a compact(paired) form,
- * expand ELD's notions to match the ones used by Audio InfoFrame.
- */
- for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
- if (eld->spk_alloc & (1 << i))
- spk_mask |= eld_speaker_allocation_bits[i];
- }
-
- /* search for the first working match in the CA table */
- for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
- if (channels == channel_allocations[i].channels &&
- (spk_mask & channel_allocations[i].spk_mask) ==
- channel_allocations[i].spk_mask) {
- ai->CA = channel_allocations[i].ca_index;
- break;
- }
- }
-
- snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
- snd_printdd(KERN_INFO
- "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
- ai->CA, channels, buf);
-
- return ai->CA;
-}
-
-static void hdmi_setup_channel_mapping(struct hda_codec *codec,
- hda_nid_t pin_nid,
- struct hdmi_audio_infoframe *ai)
-{
- int i;
- int ca = ai->CA;
- int err;
-
- if (hdmi_channel_mapping[ca][1] == 0) {
- for (i = 0; i < channel_allocations[ca].channels; i++)
- hdmi_channel_mapping[ca][i] = i | (i << 4);
- for (; i < 8; i++)
- hdmi_channel_mapping[ca][i] = 0xf | (i << 4);
- }
-
- for (i = 0; i < 8; i++) {
- err = snd_hda_codec_write(codec, pin_nid, 0,
- AC_VERB_SET_HDMI_CHAN_SLOT,
- hdmi_channel_mapping[ca][i]);
- if (err) {
- snd_printdd(KERN_INFO "HDMI: channel mapping failed\n");
- break;
- }
- }
-
- hdmi_debug_channel_mapping(codec, pin_nid);
-}
-
-static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid,
- struct hdmi_audio_infoframe *ai)
-{
- u8 *bytes = (u8 *)ai;
- u8 val;
- int i;
-
- if (snd_hda_codec_read(codec, pin_nid, 0, AC_VERB_GET_HDMI_DIP_XMIT, 0)
- != AC_DIPXMIT_BEST)
- return false;
-
- hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0);
- for (i = 0; i < sizeof(*ai); i++) {
- val = snd_hda_codec_read(codec, pin_nid, 0,
- AC_VERB_GET_HDMI_DIP_DATA, 0);
- if (val != bytes[i])
- return false;
- }
-
- return true;
-}
-
-static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid,
- struct snd_pcm_substream *substream)
-{
- struct intel_hdmi_spec *spec = codec->spec;
- hda_nid_t pin_nid;
- int i;
- struct hdmi_audio_infoframe ai = {
- .type = 0x84,
- .ver = 0x01,
- .len = 0x0a,
- .CC02_CT47 = substream->runtime->channels - 1,
- };
-
- hdmi_setup_channel_allocation(codec, nid, &ai);
-
- for (i = 0; i < spec->num_pins; i++) {
- if (spec->pin_cvt[i] != nid)
- continue;
- if (!spec->sink_eld[i].monitor_present)
- continue;
-
- pin_nid = spec->pin[i];
- if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) {
- hdmi_setup_channel_mapping(codec, pin_nid, &ai);
- hdmi_stop_infoframe_trans(codec, pin_nid);
- hdmi_fill_audio_infoframe(codec, pin_nid, &ai);
- hdmi_start_infoframe_trans(codec, pin_nid);
- }
- }
-}
-
-
/*
- * Unsolicited events
+ * HDMI callbacks
*/
-static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
- struct intel_hdmi_spec *spec = codec->spec;
- int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
- int pind = !!(res & AC_UNSOL_RES_PD);
- int eldv = !!(res & AC_UNSOL_RES_ELDV);
- int index;
-
- printk(KERN_INFO
- "HDMI hot plug event: Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
- tag, pind, eldv);
-
- index = hda_node_index(spec->pin, tag);
- if (index < 0)
- return;
-
- spec->sink_eld[index].monitor_present = pind;
- spec->sink_eld[index].eld_valid = eldv;
-
- if (pind && eldv) {
- hdmi_get_show_eld(codec, spec->pin[index], &spec->sink_eld[index]);
- /* TODO: do real things about ELD */
- }
-}
-
-static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
- int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
- int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
- int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
- int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
-
- printk(KERN_INFO
- "HDMI CP event: PIN=%d SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
- tag,
- subtag,
- cp_state,
- cp_ready);
-
- /* TODO */
- if (cp_state)
- ;
- if (cp_ready)
- ;
-}
-
-
-static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- struct intel_hdmi_spec *spec = codec->spec;
- int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
- int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
-
- if (hda_node_index(spec->pin, tag) < 0) {
- snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
- return;
- }
-
- if (subtag == 0)
- hdmi_intrinsic_event(codec, res);
- else
- hdmi_non_intrinsic_event(codec, res);
-}
-
-/*
- * Callbacks
- */
-
-static void hdmi_setup_stream(struct hda_codec *codec, hda_nid_t nid,
- u32 stream_tag, int format)
-{
- int tag;
- int fmt;
-
- tag = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0) >> 4;
- fmt = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_STREAM_FORMAT, 0);
-
- snd_printdd("hdmi_setup_stream: "
- "NID=0x%x, %sstream=0x%x, %sformat=0x%x\n",
- nid,
- tag == stream_tag ? "" : "new-",
- stream_tag,
- fmt == format ? "" : "new-",
- format);
-
- if (tag != stream_tag)
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_CHANNEL_STREAMID, stream_tag << 4);
- if (fmt != format)
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_STREAM_FORMAT, format);
-}
-
static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
unsigned int stream_tag,
@@ -882,7 +87,7 @@ static struct hda_pcm_stream intel_hdmi_pcm_playback = {
static int intel_hdmi_build_pcms(struct hda_codec *codec)
{
- struct intel_hdmi_spec *spec = codec->spec;
+ struct hdmi_spec *spec = codec->spec;
struct hda_pcm *info = spec->pcm_rec;
int i;
@@ -908,7 +113,7 @@ static int intel_hdmi_build_pcms(struct hda_codec *codec)
static int intel_hdmi_build_controls(struct hda_codec *codec)
{
- struct intel_hdmi_spec *spec = codec->spec;
+ struct hdmi_spec *spec = codec->spec;
int err;
int i;
@@ -923,7 +128,7 @@ static int intel_hdmi_build_controls(struct hda_codec *codec)
static int intel_hdmi_init(struct hda_codec *codec)
{
- struct intel_hdmi_spec *spec = codec->spec;
+ struct hdmi_spec *spec = codec->spec;
int i;
for (i = 0; spec->pin[i]; i++) {
@@ -937,7 +142,7 @@ static int intel_hdmi_init(struct hda_codec *codec)
static void intel_hdmi_free(struct hda_codec *codec)
{
- struct intel_hdmi_spec *spec = codec->spec;
+ struct hdmi_spec *spec = codec->spec;
int i;
for (i = 0; i < spec->num_pins; i++)
@@ -951,12 +156,12 @@ static struct hda_codec_ops intel_hdmi_patch_ops = {
.free = intel_hdmi_free,
.build_pcms = intel_hdmi_build_pcms,
.build_controls = intel_hdmi_build_controls,
- .unsol_event = intel_hdmi_unsol_event,
+ .unsol_event = hdmi_unsol_event,
};
static int patch_intel_hdmi(struct hda_codec *codec)
{
- struct intel_hdmi_spec *spec;
+ struct hdmi_spec *spec;
int i;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
@@ -964,7 +169,7 @@ static int patch_intel_hdmi(struct hda_codec *codec)
return -ENOMEM;
codec->spec = spec;
- if (intel_hdmi_parse_codec(codec) < 0) {
+ if (hdmi_parse_codec(codec) < 0) {
codec->spec = NULL;
kfree(spec);
return -EINVAL;
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c
index 6afdab09bab..70669a24690 100644
--- a/sound/pci/hda/patch_nvhdmi.c
+++ b/sound/pci/hda/patch_nvhdmi.c
@@ -29,13 +29,23 @@
#include "hda_codec.h"
#include "hda_local.h"
+#define MAX_HDMI_CVTS 1
+#define MAX_HDMI_PINS 1
+
+#include "patch_hdmi.c"
+
+static char *nvhdmi_pcm_names[MAX_HDMI_CVTS] = {
+ "NVIDIA HDMI",
+};
+
/* define below to restrict the supported rates and formats */
/* #define LIMITED_RATE_FMT_SUPPORT */
-struct nvhdmi_spec {
- struct hda_multi_out multiout;
-
- struct hda_pcm pcm_rec;
+enum HDACodec {
+ HDA_CODEC_NVIDIA_MCP7X,
+ HDA_CODEC_NVIDIA_MCP89,
+ HDA_CODEC_NVIDIA_GT21X,
+ HDA_CODEC_INVALID
};
#define Nv_VERB_SET_Channel_Allocation 0xF79
@@ -43,15 +53,18 @@ struct nvhdmi_spec {
#define Nv_VERB_SET_Audio_Protection_On 0xF98
#define Nv_VERB_SET_Audio_Protection_Off 0xF99
-#define Nv_Master_Convert_nid 0x04
-#define Nv_Master_Pin_nid 0x05
+#define nvhdmi_master_con_nid_7x 0x04
+#define nvhdmi_master_pin_nid_7x 0x05
-static hda_nid_t nvhdmi_convert_nids[4] = {
+#define nvhdmi_master_con_nid_89 0x04
+#define nvhdmi_master_pin_nid_89 0x05
+
+static hda_nid_t nvhdmi_con_nids_7x[4] = {
/*front, rear, clfe, rear_surr */
0x6, 0x8, 0xa, 0xc,
};
-static struct hda_verb nvhdmi_basic_init[] = {
+static struct hda_verb nvhdmi_basic_init_7x[] = {
/* set audio protect on */
{ 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1},
/* enable digital output on pin widget */
@@ -84,22 +97,60 @@ static struct hda_verb nvhdmi_basic_init[] = {
*/
static int nvhdmi_build_controls(struct hda_codec *codec)
{
- struct nvhdmi_spec *spec = codec->spec;
+ struct hdmi_spec *spec = codec->spec;
int err;
+ int i;
- err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
- if (err < 0)
- return err;
+ if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
+ || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
+ for (i = 0; i < codec->num_pcms; i++) {
+ err = snd_hda_create_spdif_out_ctls(codec,
+ spec->cvt[i]);
+ if (err < 0)
+ return err;
+ }
+ } else {
+ err = snd_hda_create_spdif_out_ctls(codec,
+ spec->multiout.dig_out_nid);
+ if (err < 0)
+ return err;
+ }
return 0;
}
static int nvhdmi_init(struct hda_codec *codec)
{
- snd_hda_sequence_write(codec, nvhdmi_basic_init);
+ struct hdmi_spec *spec = codec->spec;
+ int i;
+ if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
+ || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
+ for (i = 0; spec->pin[i]; i++) {
+ hdmi_enable_output(codec, spec->pin[i]);
+ snd_hda_codec_write(codec, spec->pin[i], 0,
+ AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | spec->pin[i]);
+ }
+ } else {
+ snd_hda_sequence_write(codec, nvhdmi_basic_init_7x);
+ }
return 0;
}
+static void nvhdmi_free(struct hda_codec *codec)
+{
+ struct hdmi_spec *spec = codec->spec;
+ int i;
+
+ if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89)
+ || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) {
+ for (i = 0; i < spec->num_pins; i++)
+ snd_hda_eld_proc_free(codec, &spec->sink_eld[i]);
+ }
+
+ kfree(spec);
+}
+
/*
* Digital out
*/
@@ -107,25 +158,25 @@ static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream)
{
- struct nvhdmi_spec *spec = codec->spec;
+ struct hdmi_spec *spec = codec->spec;
return snd_hda_multi_out_dig_open(codec, &spec->multiout);
}
-static int nvhdmi_dig_playback_pcm_close_8ch(struct hda_pcm_stream *hinfo,
+static int nvhdmi_dig_playback_pcm_close_8ch_7x(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream)
{
- struct nvhdmi_spec *spec = codec->spec;
+ struct hdmi_spec *spec = codec->spec;
int i;
- snd_hda_codec_write(codec, Nv_Master_Convert_nid,
+ snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x,
0, AC_VERB_SET_CHANNEL_STREAMID, 0);
for (i = 0; i < 4; i++) {
/* set the stream id */
- snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0,
+ snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
AC_VERB_SET_CHANNEL_STREAMID, 0);
/* set the stream format */
- snd_hda_codec_write(codec, nvhdmi_convert_nids[i], 0,
+ snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0,
AC_VERB_SET_STREAM_FORMAT, 0);
}
@@ -136,10 +187,25 @@ static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
struct snd_pcm_substream *substream)
{
- struct nvhdmi_spec *spec = codec->spec;
+ struct hdmi_spec *spec = codec->spec;
return snd_hda_multi_out_dig_close(codec, &spec->multiout);
}
+static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ unsigned int stream_tag,
+ unsigned int format,
+ struct snd_pcm_substream *substream)
+{
+ hdmi_set_channel_count(codec, hinfo->nid,
+ substream->runtime->channels);
+
+ hdmi_setup_audio_infoframe(codec, hinfo->nid, substream);
+
+ hdmi_setup_stream(codec, hinfo->nid, stream_tag, format);
+ return 0;
+}
+
static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
unsigned int stream_tag,
@@ -181,29 +247,29 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
snd_hda_codec_write(codec,
- Nv_Master_Convert_nid,
+ nvhdmi_master_con_nid_7x,
0,
AC_VERB_SET_DIGI_CONVERT_1,
codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
/* set the stream id */
- snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0,
+ snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0);
/* set the stream format */
- snd_hda_codec_write(codec, Nv_Master_Convert_nid, 0,
+ snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0,
AC_VERB_SET_STREAM_FORMAT, format);
/* turn on again (if needed) */
/* enable and set the channel status audio/data flag */
if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) {
snd_hda_codec_write(codec,
- Nv_Master_Convert_nid,
+ nvhdmi_master_con_nid_7x,
0,
AC_VERB_SET_DIGI_CONVERT_1,
codec->spdif_ctls & 0xff);
snd_hda_codec_write(codec,
- Nv_Master_Convert_nid,
+ nvhdmi_master_con_nid_7x,
0,
AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
}
@@ -220,19 +286,19 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
if (codec->spdif_status_reset &&
(codec->spdif_ctls & AC_DIG1_ENABLE))
snd_hda_codec_write(codec,
- nvhdmi_convert_nids[i],
+ nvhdmi_con_nids_7x[i],
0,
AC_VERB_SET_DIGI_CONVERT_1,
codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff);
/* set the stream id */
snd_hda_codec_write(codec,
- nvhdmi_convert_nids[i],
+ nvhdmi_con_nids_7x[i],
0,
AC_VERB_SET_CHANNEL_STREAMID,
(stream_tag << 4) | channel_id);
/* set the stream format */
snd_hda_codec_write(codec,
- nvhdmi_convert_nids[i],
+ nvhdmi_con_nids_7x[i],
0,
AC_VERB_SET_STREAM_FORMAT,
format);
@@ -241,12 +307,12 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
if (codec->spdif_status_reset &&
(codec->spdif_ctls & AC_DIG1_ENABLE)) {
snd_hda_codec_write(codec,
- nvhdmi_convert_nids[i],
+ nvhdmi_con_nids_7x[i],
0,
AC_VERB_SET_DIGI_CONVERT_1,
codec->spdif_ctls & 0xff);
snd_hda_codec_write(codec,
- nvhdmi_convert_nids[i],
+ nvhdmi_con_nids_7x[i],
0,
AC_VERB_SET_DIGI_CONVERT_2, dataDCC2);
}
@@ -261,28 +327,47 @@ static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo,
return 0;
}
+static int nvhdmi_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream)
+{
+ return 0;
+}
+
static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo,
struct hda_codec *codec,
unsigned int stream_tag,
unsigned int format,
struct snd_pcm_substream *substream)
{
- struct nvhdmi_spec *spec = codec->spec;
+ struct hdmi_spec *spec = codec->spec;
return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
format, substream);
}
-static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch = {
+static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = {
+ .substreams = 1,
+ .channels_min = 2,
+ .rates = SUPPORTED_RATES,
+ .maxbps = SUPPORTED_MAXBPS,
+ .formats = SUPPORTED_FORMATS,
+ .ops = {
+ .prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89,
+ .cleanup = nvhdmi_playback_pcm_cleanup,
+ },
+};
+
+static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_7x = {
.substreams = 1,
.channels_min = 2,
.channels_max = 8,
- .nid = Nv_Master_Convert_nid,
+ .nid = nvhdmi_master_con_nid_7x,
.rates = SUPPORTED_RATES,
.maxbps = SUPPORTED_MAXBPS,
.formats = SUPPORTED_FORMATS,
.ops = {
.open = nvhdmi_dig_playback_pcm_open,
- .close = nvhdmi_dig_playback_pcm_close_8ch,
+ .close = nvhdmi_dig_playback_pcm_close_8ch_7x,
.prepare = nvhdmi_dig_playback_pcm_prepare_8ch
},
};
@@ -291,7 +376,7 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
- .nid = Nv_Master_Convert_nid,
+ .nid = nvhdmi_master_con_nid_7x,
.rates = SUPPORTED_RATES,
.maxbps = SUPPORTED_MAXBPS,
.formats = SUPPORTED_FORMATS,
@@ -302,10 +387,36 @@ static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = {
},
};
-static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
+static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec)
+{
+ struct hdmi_spec *spec = codec->spec;
+ struct hda_pcm *info = spec->pcm_rec;
+ int i;
+
+ codec->num_pcms = spec->num_cvts;
+ codec->pcm_info = info;
+
+ for (i = 0; i < codec->num_pcms; i++, info++) {
+ unsigned int chans;
+
+ chans = get_wcaps(codec, spec->cvt[i]);
+ chans = get_wcaps_channels(chans);
+
+ info->name = nvhdmi_pcm_names[i];
+ info->pcm_type = HDA_PCM_TYPE_HDMI;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK]
+ = nvhdmi_pcm_digital_playback_8ch_89;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i];
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans;
+ }
+
+ return 0;
+}
+
+static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec)
{
- struct nvhdmi_spec *spec = codec->spec;
- struct hda_pcm *info = &spec->pcm_rec;
+ struct hdmi_spec *spec = codec->spec;
+ struct hda_pcm *info = spec->pcm_rec;
codec->num_pcms = 1;
codec->pcm_info = info;
@@ -313,15 +424,15 @@ static int nvhdmi_build_pcms_8ch(struct hda_codec *codec)
info->name = "NVIDIA HDMI";
info->pcm_type = HDA_PCM_TYPE_HDMI;
info->stream[SNDRV_PCM_STREAM_PLAYBACK]
- = nvhdmi_pcm_digital_playback_8ch;
+ = nvhdmi_pcm_digital_playback_8ch_7x;
return 0;
}
static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
{
- struct nvhdmi_spec *spec = codec->spec;
- struct hda_pcm *info = &spec->pcm_rec;
+ struct hdmi_spec *spec = codec->spec;
+ struct hda_pcm *info = spec->pcm_rec;
codec->num_pcms = 1;
codec->pcm_info = info;
@@ -334,14 +445,17 @@ static int nvhdmi_build_pcms_2ch(struct hda_codec *codec)
return 0;
}
-static void nvhdmi_free(struct hda_codec *codec)
-{
- kfree(codec->spec);
-}
+static struct hda_codec_ops nvhdmi_patch_ops_8ch_89 = {
+ .build_controls = nvhdmi_build_controls,
+ .build_pcms = nvhdmi_build_pcms_8ch_89,
+ .init = nvhdmi_init,
+ .free = nvhdmi_free,
+ .unsol_event = hdmi_unsol_event,
+};
-static struct hda_codec_ops nvhdmi_patch_ops_8ch = {
+static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = {
.build_controls = nvhdmi_build_controls,
- .build_pcms = nvhdmi_build_pcms_8ch,
+ .build_pcms = nvhdmi_build_pcms_8ch_7x,
.init = nvhdmi_init,
.free = nvhdmi_free,
};
@@ -353,9 +467,36 @@ static struct hda_codec_ops nvhdmi_patch_ops_2ch = {
.free = nvhdmi_free,
};
-static int patch_nvhdmi_8ch(struct hda_codec *codec)
+static int patch_nvhdmi_8ch_89(struct hda_codec *codec)
+{
+ struct hdmi_spec *spec;
+ int i;
+
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+ if (spec == NULL)
+ return -ENOMEM;
+
+ codec->spec = spec;
+ spec->codec_type = HDA_CODEC_NVIDIA_MCP89;
+
+ if (hdmi_parse_codec(codec) < 0) {
+ codec->spec = NULL;
+ kfree(spec);
+ return -EINVAL;
+ }
+ codec->patch_ops = nvhdmi_patch_ops_8ch_89;
+
+ for (i = 0; i < spec->num_pins; i++)
+ snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i);
+
+ init_channel_allocations();
+
+ return 0;
+}
+
+static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
{
- struct nvhdmi_spec *spec;
+ struct hdmi_spec *spec;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
@@ -365,16 +506,17 @@ static int patch_nvhdmi_8ch(struct hda_codec *codec)
spec->multiout.num_dacs = 0; /* no analog */
spec->multiout.max_channels = 8;
- spec->multiout.dig_out_nid = Nv_Master_Convert_nid;
+ spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
+ spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
- codec->patch_ops = nvhdmi_patch_ops_8ch;
+ codec->patch_ops = nvhdmi_patch_ops_8ch_7x;
return 0;
}
static int patch_nvhdmi_2ch(struct hda_codec *codec)
{
- struct nvhdmi_spec *spec;
+ struct hdmi_spec *spec;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
@@ -384,7 +526,8 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
spec->multiout.num_dacs = 0; /* no analog */
spec->multiout.max_channels = 2;
- spec->multiout.dig_out_nid = Nv_Master_Convert_nid;
+ spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x;
+ spec->codec_type = HDA_CODEC_NVIDIA_MCP7X;
codec->patch_ops = nvhdmi_patch_ops_2ch;
@@ -395,13 +538,24 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec)
* patch entries
*/
static struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
- { .id = 0x10de0002, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
- { .id = 0x10de0003, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
- { .id = 0x10de0005, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
- { .id = 0x10de0006, .name = "MCP78 HDMI", .patch = patch_nvhdmi_8ch },
- { .id = 0x10de0007, .name = "MCP7A HDMI", .patch = patch_nvhdmi_8ch },
{ .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch },
{ .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch },
+ { .id = 0x10de0002, .name = "MCP77/78 HDMI",
+ .patch = patch_nvhdmi_8ch_7x },
+ { .id = 0x10de0003, .name = "MCP77/78 HDMI",
+ .patch = patch_nvhdmi_8ch_7x },
+ { .id = 0x10de0005, .name = "MCP77/78 HDMI",
+ .patch = patch_nvhdmi_8ch_7x },
+ { .id = 0x10de0006, .name = "MCP77/78 HDMI",
+ .patch = patch_nvhdmi_8ch_7x },
+ { .id = 0x10de0007, .name = "MCP79/7A HDMI",
+ .patch = patch_nvhdmi_8ch_7x },
+ { .id = 0x10de000c, .name = "MCP89 HDMI",
+ .patch = patch_nvhdmi_8ch_89 },
+ { .id = 0x10de000b, .name = "GT21x HDMI",
+ .patch = patch_nvhdmi_8ch_89 },
+ { .id = 0x10de000d, .name = "GT240 HDMI",
+ .patch = patch_nvhdmi_8ch_89 },
{} /* terminator */
};
@@ -412,9 +566,12 @@ MODULE_ALIAS("snd-hda-codec-id:10de0006");
MODULE_ALIAS("snd-hda-codec-id:10de0007");
MODULE_ALIAS("snd-hda-codec-id:10de0067");
MODULE_ALIAS("snd-hda-codec-id:10de8001");
+MODULE_ALIAS("snd-hda-codec-id:10de000c");
+MODULE_ALIAS("snd-hda-codec-id:10de000b");
+MODULE_ALIAS("snd-hda-codec-id:10de000d");
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Nvidia HDMI HD-audio codec");
+MODULE_DESCRIPTION("NVIDIA HDMI HD-audio codec");
static struct hda_codec_preset_list nvhdmi_list = {
.preset = snd_hda_preset_nvhdmi,
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index e8cbe216e91..5d2fbb87b87 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -4915,7 +4915,7 @@ static void fixup_automic_adc(struct hda_codec *codec)
static void fixup_single_adc(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- hda_nid_t pin;
+ hda_nid_t pin = 0;
int i;
/* search for the input pin; there must be only one */
@@ -13561,6 +13561,8 @@ static void alc269_lifebook_unsol_event(struct hda_codec *codec,
static void alc269_quanta_fl1_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x19;
@@ -13656,6 +13658,8 @@ static void alc269_laptop_unsol_event(struct hda_codec *codec,
static void alc269_laptop_dmic_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x12;
@@ -13666,6 +13670,8 @@ static void alc269_laptop_dmic_setup(struct hda_codec *codec)
static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x12;
@@ -13676,6 +13682,8 @@ static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
static void alc269_laptop_amic_setup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
+ spec->autocfg.hp_pins[0] = 0x15;
+ spec->autocfg.speaker_pins[0] = 0x14;
spec->ext_mic.pin = 0x18;
spec->ext_mic.mux_idx = 0;
spec->int_mic.pin = 0x19;
diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c
index 7754db166d9..dbc4b89d74e 100644
--- a/sound/pci/oxygen/xonar_wm87x6.c
+++ b/sound/pci/oxygen/xonar_wm87x6.c
@@ -68,7 +68,7 @@ static void wm8776_write(struct oxygen *chip,
OXYGEN_SPI_CEN_LATCH_CLOCK_LO,
(reg << 9) | value);
if (reg < ARRAY_SIZE(data->wm8776_regs)) {
- if (reg >= WM8776_HPLVOL || reg <= WM8776_DACMASTER)
+ if (reg >= WM8776_HPLVOL && reg <= WM8776_DACMASTER)
value &= ~WM8776_UPDATE;
data->wm8776_regs[reg] = value;
}
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index 960a227eb65..ad446267761 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -1974,9 +1974,9 @@ snd_riptide_proc_read(struct snd_info_entry *entry,
}
snd_iprintf(buffer, "Paths:\n");
i = getpaths(cif, p);
- while (i--) {
- snd_iprintf(buffer, "%x->%x ", p[i - 1], p[i]);
- i--;
+ while (i >= 2) {
+ i -= 2;
+ snd_iprintf(buffer, "%x->%x ", p[i], p[i + 1]);
}
snd_iprintf(buffer, "\n");
}
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index b9ef7e45891..b68d99fb6af 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -90,12 +90,10 @@ static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg,
if (reg >= codec->reg_cache_size)
return -EINVAL;
- reg &= AK4104_REG_MASK;
- reg |= AK4104_WRITE;
-
/* only write to the hardware if value has changed */
if (cache[reg] != value) {
- u8 tmp[2] = { reg, value };
+ u8 tmp[2] = { (reg & AK4104_REG_MASK) | AK4104_WRITE, value };
+
if (spi_write(spi, tmp, sizeof(tmp))) {
dev_err(&spi->dev, "SPI write failed\n");
return -EIO;
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index a2763c2e734..9cd0a66b766 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -137,7 +137,7 @@ static void uda1380_flush_work(struct work_struct *work)
{
int bit, reg;
- for_each_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) {
+ for_each_set_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) {
reg = 0x10 + bit;
pr_debug("uda1380: flush reg %x val %x:\n", reg,
uda1380_read_reg_cache(uda1380_codec, reg));
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 718ef912e75..df2c6d9617f 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -1349,7 +1349,7 @@ static irqreturn_t wm8350_hp_jack_handler(int irq, void *data)
int mask;
struct wm8350_jack_data *jack = NULL;
- switch (irq) {
+ switch (irq - wm8350->irq_base) {
case WM8350_IRQ_CODEC_JCK_DET_L:
jack = &priv->hpl;
mask = WM8350_JACK_L_LVL;
@@ -1424,7 +1424,7 @@ int wm8350_hp_jack_detect(struct snd_soc_codec *codec, enum wm8350_jack which,
wm8350_set_bits(wm8350, WM8350_JACK_DETECT, ena);
/* Sync status */
- wm8350_hp_jack_handler(irq, priv);
+ wm8350_hp_jack_handler(irq + wm8350->irq_base, priv);
return 0;
}
@@ -1521,8 +1521,8 @@ static int wm8350_remove(struct platform_device *pdev)
WM8350_JDL_ENA | WM8350_JDR_ENA);
wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA);
- wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L);
- wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, priv);
+ wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, priv);
priv->hpl.jack = NULL;
priv->hpr.jack = NULL;
diff --git a/sound/soc/sh/siu.h b/sound/soc/sh/siu.h
index 9cc04ab2bce..c0bfab8fed3 100644
--- a/sound/soc/sh/siu.h
+++ b/sound/soc/sh/siu.h
@@ -72,7 +72,7 @@ struct siu_firmware {
#include <linux/interrupt.h>
#include <linux/io.h>
-#include <asm/dma-sh.h>
+#include <asm/dmaengine.h>
#include <sound/core.h>
#include <sound/pcm.h>
diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c
index c5efc30f013..ba7f8d05d97 100644
--- a/sound/soc/sh/siu_pcm.c
+++ b/sound/soc/sh/siu_pcm.c
@@ -32,7 +32,7 @@
#include <sound/pcm_params.h>
#include <sound/soc-dai.h>
-#include <asm/dma-sh.h>
+#include <asm/dmaengine.h>
#include <asm/siu.h>
#include "siu.h"
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index a03bac943aa..c8b0556ef43 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -427,24 +427,24 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
if (!runtime->hw.rates) {
printk(KERN_ERR "asoc: %s <-> %s No matching rates\n",
codec_dai->name, cpu_dai->name);
- goto machine_err;
+ goto config_err;
}
if (!runtime->hw.formats) {
printk(KERN_ERR "asoc: %s <-> %s No matching formats\n",
codec_dai->name, cpu_dai->name);
- goto machine_err;
+ goto config_err;
}
if (!runtime->hw.channels_min || !runtime->hw.channels_max) {
printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
codec_dai->name, cpu_dai->name);
- goto machine_err;
+ goto config_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;
+ goto config_err;
}
pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name);
@@ -464,10 +464,14 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
mutex_unlock(&pcm_mutex);
return 0;
-machine_err:
+config_err:
if (machine->ops && machine->ops->shutdown)
machine->ops->shutdown(substream);
+machine_err:
+ if (codec_dai->ops->shutdown)
+ codec_dai->ops->shutdown(substream, codec_dai);
+
codec_dai_err:
if (platform->pcm_ops->close)
platform->pcm_ops->close(substream);
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index 8c2925814ce..c570ae3e6d5 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -22,13 +22,13 @@ config SND_USB_AUDIO
will be called snd-usb-audio.
config SND_USB_UA101
- tristate "Edirol UA-101 driver (EXPERIMENTAL)"
+ tristate "Edirol UA-101/UA-1000 driver (EXPERIMENTAL)"
depends on EXPERIMENTAL
select SND_PCM
select SND_RAWMIDI
help
- Say Y here to include support for the Edirol UA-101 audio/MIDI
- interface.
+ Say Y here to include support for the Edirol UA-101 and UA-1000
+ audio/MIDI interfaces.
To compile this driver as a module, choose M here: the module
will be called snd-ua101.
diff --git a/sound/usb/caiaq/midi.h b/sound/usb/caiaq/midi.h
index 9d16db027fc..380f984babc 100644
--- a/sound/usb/caiaq/midi.h
+++ b/sound/usb/caiaq/midi.h
@@ -3,6 +3,6 @@
int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *dev);
void snd_usb_caiaq_midi_handle_input(struct snd_usb_caiaqdev *dev, int port, const char *buf, int len);
-void snd_usb_caiaq_midi_output_done(struct urb* urb);
+void snd_usb_caiaq_midi_output_done(struct urb *urb);
#endif /* CAIAQ_MIDI_H */
diff --git a/sound/usb/ua101.c b/sound/usb/ua101.c
index 4f4ccdf70dd..3d458d3b996 100644
--- a/sound/usb/ua101.c
+++ b/sound/usb/ua101.c
@@ -1,5 +1,5 @@
/*
- * Edirol UA-101 driver
+ * Edirol UA-101/UA-1000 driver
* Copyright (c) Clemens Ladisch <clemens@ladisch.de>
*
* This driver is free software: you can redistribute it and/or modify
@@ -25,13 +25,10 @@
#include <sound/pcm_params.h>
#include "usbaudio.h"
-MODULE_DESCRIPTION("Edirol UA-101 driver");
+MODULE_DESCRIPTION("Edirol UA-101/1000 driver");
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
MODULE_LICENSE("GPL v2");
-MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101}}");
-
-/* I use my UA-1A for testing because I don't have a UA-101 ... */
-#define UA1A_HACK
+MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101},{Edirol,UA-1000}}");
/*
* Should not be lower than the minimum scheduling delay of the host
@@ -132,9 +129,6 @@ struct ua101 {
dma_addr_t dma;
} buffers[MAX_MEMORY_BUFFERS];
} capture, playback;
-
- unsigned int fps[10];
- unsigned int frame_counter;
};
static DEFINE_MUTEX(devices_mutex);
@@ -424,16 +418,6 @@ static void capture_urb_complete(struct urb *urb)
if (do_period_elapsed)
snd_pcm_period_elapsed(stream->substream);
- /* for debugging: measure the sample rate relative to the USB clock */
- ua->fps[ua->frame_counter++ / ua->packets_per_second] += frames;
- if (ua->frame_counter >= ARRAY_SIZE(ua->fps) * ua->packets_per_second) {
- printk(KERN_DEBUG "capture rate:");
- for (frames = 0; frames < ARRAY_SIZE(ua->fps); ++frames)
- printk(KERN_CONT " %u", ua->fps[frames]);
- printk(KERN_CONT "\n");
- memset(ua->fps, 0, sizeof(ua->fps));
- ua->frame_counter = 0;
- }
return;
stream_stopped:
@@ -1200,13 +1184,30 @@ static int ua101_probe(struct usb_interface *interface,
.type = QUIRK_MIDI_FIXED_ENDPOINT,
.data = &midi_ep
};
+ static const int intf_numbers[2][3] = {
+ { /* UA-101 */
+ [INTF_PLAYBACK] = 0,
+ [INTF_CAPTURE] = 1,
+ [INTF_MIDI] = 2,
+ },
+ { /* UA-1000 */
+ [INTF_CAPTURE] = 1,
+ [INTF_PLAYBACK] = 2,
+ [INTF_MIDI] = 3,
+ },
+ };
struct snd_card *card;
struct ua101 *ua;
unsigned int card_index, i;
+ int is_ua1000;
+ const char *name;
char usb_path[32];
int err;
- if (interface->altsetting->desc.bInterfaceNumber != 0)
+ is_ua1000 = usb_id->idProduct == 0x0044;
+
+ if (interface->altsetting->desc.bInterfaceNumber !=
+ intf_numbers[is_ua1000][0])
return -ENODEV;
mutex_lock(&devices_mutex);
@@ -1239,20 +1240,13 @@ static int ua101_probe(struct usb_interface *interface,
init_waitqueue_head(&ua->rate_feedback_wait);
init_waitqueue_head(&ua->alsa_playback_wait);
-#ifdef UA1A_HACK
- if (ua->dev->descriptor.idProduct == cpu_to_le16(0x0018)) {
- ua->intf[2] = interface;
- ua->intf[0] = usb_ifnum_to_if(ua->dev, 1);
- ua->intf[1] = usb_ifnum_to_if(ua->dev, 2);
- usb_driver_claim_interface(&ua101_driver, ua->intf[0], ua);
- usb_driver_claim_interface(&ua101_driver, ua->intf[1], ua);
- } else {
-#endif
ua->intf[0] = interface;
for (i = 1; i < ARRAY_SIZE(ua->intf); ++i) {
- ua->intf[i] = usb_ifnum_to_if(ua->dev, i);
+ ua->intf[i] = usb_ifnum_to_if(ua->dev,
+ intf_numbers[is_ua1000][i]);
if (!ua->intf[i]) {
- dev_err(&ua->dev->dev, "interface %u not found\n", i);
+ dev_err(&ua->dev->dev, "interface %u not found\n",
+ intf_numbers[is_ua1000][i]);
err = -ENXIO;
goto probe_error;
}
@@ -1264,39 +1258,19 @@ static int ua101_probe(struct usb_interface *interface,
goto probe_error;
}
}
-#ifdef UA1A_HACK
- }
-#endif
snd_card_set_dev(card, &interface->dev);
-#ifdef UA1A_HACK
- if (ua->dev->descriptor.idProduct == cpu_to_le16(0x0018)) {
- ua->format_bit = SNDRV_PCM_FMTBIT_S16_LE;
- ua->rate = 44100;
- ua->packets_per_second = 1000;
- ua->capture.channels = 2;
- ua->playback.channels = 2;
- ua->capture.frame_bytes = 4;
- ua->playback.frame_bytes = 4;
- ua->capture.usb_pipe = usb_rcvisocpipe(ua->dev, 2);
- ua->playback.usb_pipe = usb_sndisocpipe(ua->dev, 1);
- ua->capture.max_packet_bytes = 192;
- ua->playback.max_packet_bytes = 192;
- } else {
-#endif
err = detect_usb_format(ua);
if (err < 0)
goto probe_error;
-#ifdef UA1A_HACK
- }
-#endif
+ name = usb_id->idProduct == 0x0044 ? "UA-1000" : "UA-101";
strcpy(card->driver, "UA-101");
- strcpy(card->shortname, "UA-101");
+ strcpy(card->shortname, name);
usb_make_path(ua->dev, usb_path, sizeof(usb_path));
snprintf(ua->card->longname, sizeof(ua->card->longname),
- "EDIROL UA-101 (serial %s), %u Hz at %s, %s speed",
+ "EDIROL %s (serial %s), %u Hz at %s, %s speed", name,
ua->dev->serial ? ua->dev->serial : "?", ua->rate, usb_path,
ua->dev->speed == USB_SPEED_HIGH ? "high" : "full");
@@ -1314,24 +1288,18 @@ static int ua101_probe(struct usb_interface *interface,
if (err < 0)
goto probe_error;
- err = snd_pcm_new(card, "UA-101", 0, 1, 1, &ua->pcm);
+ err = snd_pcm_new(card, name, 0, 1, 1, &ua->pcm);
if (err < 0)
goto probe_error;
ua->pcm->private_data = ua;
- strcpy(ua->pcm->name, "UA-101");
+ strcpy(ua->pcm->name, name);
snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_pcm_ops);
snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_pcm_ops);
-#ifdef UA1A_HACK
- if (ua->dev->descriptor.idProduct != cpu_to_le16(0x0018)) {
-#endif
err = snd_usbmidi_create(card, ua->intf[INTF_MIDI],
&ua->midi_list, &midi_quirk);
if (err < 0)
goto probe_error;
-#ifdef UA1A_HACK
- }
-#endif
err = snd_card_register(card);
if (err < 0)
@@ -1386,11 +1354,9 @@ static void ua101_disconnect(struct usb_interface *interface)
}
static struct usb_device_id ua101_ids[] = {
-#ifdef UA1A_HACK
- { USB_DEVICE(0x0582, 0x0018) },
-#endif
- { USB_DEVICE(0x0582, 0x007d) },
- { USB_DEVICE(0x0582, 0x008d) },
+ { USB_DEVICE(0x0582, 0x0044) }, /* UA-1000 high speed */
+ { USB_DEVICE(0x0582, 0x007d) }, /* UA-101 high speed */
+ { USB_DEVICE(0x0582, 0x008d) }, /* UA-101 full speed */
{ }
};
MODULE_DEVICE_TABLE(usb, ua101_ids);
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index c539f7fe292..11b0826b8fe 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -2483,7 +2483,6 @@ static int parse_audio_format_i_type(struct snd_usb_audio *chip,
sample_width, sample_bytes);
}
/* check the format byte size */
- printk(" XXXXX SAMPLE BYTES %d\n", sample_bytes);
switch (sample_bytes) {
case 1:
pcm_format = SNDRV_PCM_FORMAT_S8;
@@ -2581,6 +2580,9 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
chip->usb_id == USB_ID(0x0d8c, 0x0102)) &&
fp->altsetting == 5 && fp->maxpacksize == 392)
rate = 96000;
+ /* Creative VF0470 Live Cam reports 16 kHz instead of 8kHz */
+ if (rate == 16000 && chip->usb_id == USB_ID(0x041e, 0x4068))
+ rate = 8000;
fp->rate_table[fp->nr_rates] = rate;
if (!fp->rate_min || rate < fp->rate_min)
fp->rate_min = rate;
@@ -3386,58 +3388,6 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
return 0;
}
-/*
- * Create a stream for an Edirol UA-1000 interface.
- */
-static int create_ua1000_quirk(struct snd_usb_audio *chip,
- struct usb_interface *iface,
- const struct snd_usb_audio_quirk *quirk)
-{
- static const struct audioformat ua1000_format = {
- .format = SNDRV_PCM_FORMAT_S32_LE,
- .fmt_type = UAC_FORMAT_TYPE_I,
- .altsetting = 1,
- .altset_idx = 1,
- .attributes = 0,
- .rates = SNDRV_PCM_RATE_CONTINUOUS,
- };
- struct usb_host_interface *alts;
- struct usb_interface_descriptor *altsd;
- struct audioformat *fp;
- int stream, err;
-
- if (iface->num_altsetting != 2)
- return -ENXIO;
- alts = &iface->altsetting[1];
- altsd = get_iface_desc(alts);
- if (alts->extralen != 11 || alts->extra[1] != USB_DT_CS_INTERFACE ||
- altsd->bNumEndpoints != 1)
- return -ENXIO;
-
- fp = kmemdup(&ua1000_format, sizeof(*fp), GFP_KERNEL);
- if (!fp)
- return -ENOMEM;
-
- fp->channels = alts->extra[4];
- fp->iface = altsd->bInterfaceNumber;
- fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
- fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
- fp->datainterval = parse_datainterval(chip, alts);
- fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
- fp->rate_max = fp->rate_min = combine_triple(&alts->extra[8]);
-
- stream = (fp->endpoint & USB_DIR_IN)
- ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
- err = add_audio_endpoint(chip, stream, fp);
- if (err < 0) {
- kfree(fp);
- return err;
- }
- /* FIXME: playback must be synchronized to capture */
- usb_set_interface(chip->dev, fp->iface, 0);
- return 0;
-}
-
static int snd_usb_create_quirk(struct snd_usb_audio *chip,
struct usb_interface *iface,
const struct snd_usb_audio_quirk *quirk);
@@ -3686,7 +3636,6 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip,
[QUIRK_MIDI_CME] = create_any_midi_quirk,
[QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
[QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
- [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk,
[QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
[QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk
};
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 6b016d4aac6..42c299cbf63 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -75,7 +75,6 @@ enum quirk_type {
QUIRK_MIDI_US122L,
QUIRK_AUDIO_STANDARD_INTERFACE,
QUIRK_AUDIO_FIXED_ENDPOINT,
- QUIRK_AUDIO_EDIROL_UA1000,
QUIRK_AUDIO_EDIROL_UAXX,
QUIRK_AUDIO_ALIGN_TRANSFER,
@@ -112,7 +111,7 @@ struct snd_usb_midi_endpoint_info {
/* for QUIRK_AUDIO/MIDI_STANDARD_INTERFACE, data is NULL */
-/* for QUIRK_AUDIO_EDIROL_UA700_UA25/UA1000, data is NULL */
+/* for QUIRK_AUDIO_EDIROL_UAXX, data is NULL */
/* for QUIRK_IGNORE_INTERFACE, data is NULL */
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index f06faf7917b..2b426c1fd0e 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -1016,36 +1016,6 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
- USB_DEVICE(0x0582, 0x0044),
- .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
- .vendor_name = "Roland",
- .product_name = "UA-1000",
- .ifnum = QUIRK_ANY_INTERFACE,
- .type = QUIRK_COMPOSITE,
- .data = (const struct snd_usb_audio_quirk[]) {
- {
- .ifnum = 1,
- .type = QUIRK_AUDIO_EDIROL_UA1000
- },
- {
- .ifnum = 2,
- .type = QUIRK_AUDIO_EDIROL_UA1000
- },
- {
- .ifnum = 3,
- .type = QUIRK_MIDI_FIXED_ENDPOINT,
- .data = & (const struct snd_usb_midi_endpoint_info) {
- .out_cables = 0x0003,
- .in_cables = 0x0003
- }
- },
- {
- .ifnum = -1
- }
- }
- }
-},
-{
/* has ID 0x0049 when not in "Advanced Driver" mode */
USB_DEVICE(0x0582, 0x0047),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {